Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process: EnvGetter to use libuv #14641

Closed
Closed
Changes from 2 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 = arraysize(buffer);
Copy link
Contributor

Choose a reason for hiding this comment

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

Still arraysize() 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought I had woken up. Apparently not, so I need more coffee.

int ret = uv_os_getenv(*key, buffer, &buf_size);
Copy link
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 exsistance, so we can keep the buffer small.
Copy link
Contributor

Choose a reason for hiding this comment

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

exsistance -> existence

char buffer[256];
Copy link
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 = sizeof(buffer);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this compile?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well obviously not (which means my way of locally compiling is broken. I was trying to not compile everything 'cause Windows)

int ret = uv_os_getenv(*key, buffer, &buf_size);
if (ret != UV_ENOENT) {
Copy link
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'=') {
// 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