diff options
author | Jay Satiro <raysatiro@yahoo.com> | 2020-01-29 03:23:55 -0500 |
---|---|---|
committer | Jay Satiro <raysatiro@yahoo.com> | 2020-02-12 18:37:31 -0500 |
commit | 9dc350b60c1345aea548847de414c55468a4d123 (patch) | |
tree | 0f2b5f439f83ab148dcb158e2d63342d752a8658 /lib | |
parent | 39d5621cbd81ff456d295af7c648a31215958c93 (diff) |
tool_homedir: Change GetEnv() to use libcurl's curl_getenv()
- Deduplicate GetEnv() code.
- On Windows change ultimate call to use Windows API
GetEnvironmentVariable() instead of C runtime getenv().
Prior to this change both libcurl and the tool had their own GetEnv
which over time diverged. Now the tool's GetEnv is a wrapper around
curl_getenv (libcurl API function which is itself a wrapper around
libcurl's GetEnv).
Furthermore this change fixes a bug in that Windows API
GetEnvironmentVariable() is called instead of C runtime getenv() to get
the environment variable since some changes aren't always visible to the
latter.
Reported-by: Christoph M. Becker
Fixes https://github.com/curl/curl/issues/4774
Closes https://github.com/curl/curl/pull/4863
Diffstat (limited to 'lib')
-rw-r--r-- | lib/getenv.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/lib/getenv.c b/lib/getenv.c index e444a6a3a..a50226e73 100644 --- a/lib/getenv.c +++ b/lib/getenv.c @@ -27,25 +27,48 @@ #include "memdebug.h" -static -char *GetEnv(const char *variable) +static char *GetEnv(const char *variable) { #if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) (void)variable; return NULL; -#else -#ifdef WIN32 - char env[4096]; - char *temp = getenv(variable); - env[0] = '\0'; - if(temp != NULL) - ExpandEnvironmentStringsA(temp, env, sizeof(env)); - return (env[0] != '\0')?strdup(env):NULL; +#elif defined(WIN32) + /* This uses Windows API instead of C runtime getenv() to get the environment + variable since some changes aren't always visible to the latter. #4774 */ + char *buf = NULL; + char *tmp; + DWORD bufsize; + DWORD rc = 1; + const DWORD max = 32768; /* max env var size from MSCRT source */ + + for(;;) { + tmp = realloc(buf, rc); + if(!tmp) { + free(buf); + return NULL; + } + + buf = tmp; + bufsize = rc; + + /* It's possible for rc to be 0 if the variable was found but empty. + Since getenv doesn't make that distinction we ignore it as well. */ + rc = GetEnvironmentVariableA(variable, buf, bufsize); + if(!rc || rc == bufsize || rc > max) { + free(buf); + return NULL; + } + + /* if rc < bufsize then rc is bytes written not including null */ + if(rc < bufsize) + return buf; + + /* else rc is bytes needed, try again */ + } #else char *env = getenv(variable); return (env && env[0])?strdup(env):NULL; #endif -#endif } char *curl_getenv(const char *v) |