"getenv... function ... may be unsafe" - really?
Asked Answered
R

2

14

I'm using MSVC to compile some C code which uses standard-library functions, such as getenv(), sprintf and others, with /W3 set for warnings. I'm told by MSVC that:

'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS

Questions:

  • Why would this be unsafe, theoretically - as opposed to its use on other platforms?
  • Is it unsafe on Windows in practice?
  • Assuming I'm not writing security-oriented code - should I disable this warning or actually start aliasing a bunch of standard library functions?
Rollo answered 1/2, 2018 at 17:40 Comment(2)
Did you look here: stackoverflow.com/questions/4286934Famagusta
wiki.sei.cmu.edu/confluence/display/c/…Dogtired
D
15

getenv() is potentially unsafe in that subsequent calls to that same function may invalidate earlier returned pointers. As a result, usage such as

char *a = getenv("A");
char *b = getenv("B");
/* do stuff with both a and b */

may break, because there's no guarantee a is still usable at that point.

getenv_s() - available in the C standard library since C11 - avoids this by immediately copying the value into a caller-supplied buffer, where the caller has full control over the buffer's lifetime. dupenv_s() avoids this by making the caller responsible for managing the lifetime of the allocated buffer.

However, the signature for getenv_s is somewhat controvertial, and the function may even be removed from the C standard at some point... see this report.

Detrition answered 1/2, 2018 at 22:54 Comment(4)
According co cppreference this is not the case for C++11 and later. Old results may be invalidated by calls to POSIX setenv(), unsetenv(), and putenv() but not by other calls to getenv.Hewart
@AndrewPenkrat: What about C11?Rollo
@Rollo for C11 it's still an issue and getenv_s was introduced there. This question, however, has both C and C++ tags while current answers only cover the C language.Hewart
So what is the exact way in which you can rewrite getenv("environment_variable") in terms of _dupenv_s?Tatiania
S
1

getenv suffers like much of the classic C Standard Library by not bounding the string buffer length. This is where security bugs like buffer overrun often originate from.

If you look at getenv_s you'll see it provides an explicit bound on the length of the returned string. It's recommended for all coding by the Security Development Lifecycle best practice, which is why Visual C++ emits deprecation warnings for the less secure versions.

See MSDN and this blog post

There was an effort by Microsoft to get the C/C++ ISO Standard Library to include the Secure CRT here, some of which was approved for C11 Annex K as noted here. That also means that getenv_s should be part of the C++17 Standard Library by reference. That said, Annex K is officially considered optional for conformance. The _s bounds-checking versions of these functions are also still a subject of some debate in the C/C++ community.

Stocktaking answered 1/2, 2018 at 22:21 Comment(2)
But the interface of getenv() does not have the caller provide the buffer. So where's the risk? As long as the library itself does not introduce a bug, i.e. does not overrun anything, and makes sure to return a '\0'-terminated-string - the caller is perfectly safe. Or am I missing something? Of course returning the length of the environment string is nicer, but that's not about security.Rollo
If the function is used in a mutlithreaded environment, then the buffer could be modified while someone is reading from it. It is also not re-entrant, meaning that if, while reading the buffer, you make a function call that also eventually calls getenv(), then the value could change unexpectedly.Roundhouse

© 2022 - 2024 — McMap. All rights reserved.