win: support environment variables > 32767 chars
The Windows documentation states these should not be possible but several people have reported that they do in fact happen. Try with a smallish stack-allocated buffer first and switch to a heap-allocated buffer if the first one is too small. Fixes: https://github.com/libuv/libuv/issues/2587 PR-URL: https://github.com/libuv/libuv/pull/2589 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
75c8850c91
commit
db96a61c26
@ -60,9 +60,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximum environment variable size, including the terminating null */
|
||||
#define MAX_ENV_VAR_LENGTH 32767
|
||||
|
||||
/* A RtlGenRandom() by any other name... */
|
||||
extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength);
|
||||
|
||||
@ -1515,7 +1512,9 @@ fail:
|
||||
|
||||
|
||||
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
wchar_t var[MAX_ENV_VAR_LENGTH];
|
||||
wchar_t fastvar[512];
|
||||
wchar_t* var;
|
||||
DWORD varlen;
|
||||
wchar_t* name_w;
|
||||
DWORD bufsize;
|
||||
size_t len;
|
||||
@ -1529,25 +1528,52 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
|
||||
var = fastvar;
|
||||
varlen = ARRAY_SIZE(fastvar);
|
||||
|
||||
for (;;) {
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
len = GetEnvironmentVariableW(name_w, var, varlen);
|
||||
|
||||
if (len < varlen)
|
||||
break;
|
||||
|
||||
/* Try repeatedly because we might have been preempted by another thread
|
||||
* modifying the environment variable just as we're trying to read it.
|
||||
*/
|
||||
if (var != fastvar)
|
||||
uv__free(var);
|
||||
|
||||
varlen = 1 + len;
|
||||
var = uv__malloc(varlen * sizeof(*var));
|
||||
|
||||
if (var == NULL) {
|
||||
r = UV_ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
uv__free(name_w);
|
||||
assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
|
||||
name_w = NULL;
|
||||
|
||||
if (len == 0) {
|
||||
r = GetLastError();
|
||||
if (r != ERROR_SUCCESS)
|
||||
return uv_translate_sys_error(r);
|
||||
if (r != ERROR_SUCCESS) {
|
||||
r = uv_translate_sys_error(r);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check how much space we need */
|
||||
bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (bufsize == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
r = uv_translate_sys_error(GetLastError());
|
||||
goto fail;
|
||||
} else if (bufsize > *size) {
|
||||
*size = bufsize;
|
||||
return UV_ENOBUFS;
|
||||
r = UV_ENOBUFS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
@ -1560,11 +1586,23 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (bufsize == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
if (bufsize == 0) {
|
||||
r = uv_translate_sys_error(GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*size = bufsize - 1;
|
||||
return 0;
|
||||
r = 0;
|
||||
|
||||
fail:
|
||||
|
||||
if (name_w != NULL)
|
||||
uv__free(name_w);
|
||||
|
||||
if (var != fastvar)
|
||||
uv__free(var);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -142,5 +142,29 @@ TEST_IMPL(env_vars) {
|
||||
r = uv_os_unsetenv(name2);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 1; i <= 4; i++) {
|
||||
size_t n;
|
||||
char* p;
|
||||
|
||||
n = i * 32768;
|
||||
size = n + 1;
|
||||
|
||||
p = malloc(size);
|
||||
ASSERT_NOT_NULL(p);
|
||||
|
||||
memset(p, 'x', n);
|
||||
p[n] = '\0';
|
||||
|
||||
ASSERT_EQ(0, uv_os_setenv(name, p));
|
||||
ASSERT_EQ(0, uv_os_getenv(name, p, &size));
|
||||
ASSERT_EQ(n, size);
|
||||
|
||||
for (n = 0; n < size; n++)
|
||||
ASSERT_EQ('x', p[n]);
|
||||
|
||||
ASSERT_EQ(0, uv_os_unsetenv(name));
|
||||
free(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user