Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 15 additions & 30 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2752,28 +2752,15 @@ static void EnvGetter(Local<Name> property,
if (property->IsSymbol()) {
return info.GetReturnValue().SetUndefined();
}
#ifdef __POSIX__
node::Utf8Value key(isolate, property);
const char* val = getenv(*key);
if (val) {
return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
}
#else // _WIN32
node::TwoByteValue key(isolate, property);
WCHAR buffer[32767]; // The maximum size allowed for environment variables.
DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
buffer,
arraysize(buffer));
// If result >= sizeof buffer the buffer was too small. That should never
// happen. If result == 0 and result != ERROR_SUCCESS the variable was not
// not found.
if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
result < arraysize(buffer)) {
const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
return info.GetReturnValue().Set(rc);
// On POSIX there is not explicitly defined size limit, but on Windows
// environment variables have a maximum size limit of 2**15 - 1.
char buffer[32768];
size_t buf_size = sizeof(buffer);
int ret = uv_os_getenv(*key, buffer, &buf_size);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should retry with a bigger buffer when ret == UV_ENOBUFS, otherwise you introduce an arbitrary size restriction on Unices that wasn't there before.

(And also, can you rename it to err for consistency?)

if (!ret) {
return info.GetReturnValue().Set(String::NewFromUtf8(isolate, buffer));
}
#endif
}


Expand Down Expand Up @@ -2802,24 +2789,22 @@ static void EnvQuery(Local<Name> property,
const PropertyCallbackInfo<Integer>& info) {
int32_t rc = -1; // Not found unless proven otherwise.
if (property->IsString()) {
#ifdef __POSIX__
node::Utf8Value key(info.GetIsolate(), property);
if (getenv(*key))
rc = 0;
#else // _WIN32
node::TwoByteValue key(info.GetIsolate(), property);
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
GetLastError() == ERROR_SUCCESS) {
// We are only interested in existence, so we can keep the buffer small.
char buffer[256];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're only interested in existence, couldn't you go much smaller than 256?

size_t buf_size = sizeof(buffer);
int ret = uv_os_getenv(*key, buffer, &buf_size);
if (ret != UV_ENOENT) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reads uninitialized memory when ret == UV_ENOBUFS (i.e., buffer too small.)

rc = 0;
if (key_ptr[0] == L'=') {
#ifdef _WIN32
if (key[0] == L'=') {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just '=', not L'='.

// Environment variables that start with '=' are hidden and read-only.
rc = static_cast<int32_t>(v8::ReadOnly) |
static_cast<int32_t>(v8::DontDelete) |
static_cast<int32_t>(v8::DontEnum);
}
}
#endif
}
}
if (rc != -1)
info.GetReturnValue().Set(rc);
Expand Down