Compare commits

...

3 Commits

Author SHA1 Message Date
claude[bot]
13bdc66300 fix: use toWTFString for JSValue string conversion in initgroups
- Replace user.getString(globalObject) with user.toWTFString(globalObject)
- Fix compilation errors: JSString* type mismatch and missing utf8() method
- Proper exception handling with RETURN_IF_EXCEPTION

Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-05-30 00:35:23 +00:00
Jarred-Sumner
8577c88edd Sync Node.js tests with upstream 2025-05-30 00:23:07 +00:00
Jarred Sumner
1aadf018b1 fix initgroups gating 2025-05-29 17:22:29 -07:00
2 changed files with 116 additions and 2 deletions

View File

@@ -2335,7 +2335,7 @@ static JSValue constructEnv(VM& vm, JSObject* processObject)
return globalObject->processEnvObject();
}
#if !OS(WINDOWS)
#if OS(DARWIN) || OS(LINUX)
JSC_DEFINE_HOST_FUNCTION(Process_functiongetuid, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
@@ -2527,6 +2527,59 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionsetgroups, (JSGlobalObject * globalObje
return JSValue::encode(jsNumber(result));
}
JSC_DEFINE_HOST_FUNCTION(Process_functioninitgroups, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
auto& vm = JSC::getVM(globalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue user = callFrame->argument(0);
JSValue extraGroup = callFrame->argument(1);
if (!user.isNumber() && !user.isString())
return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, "user"_s, "number or string"_s, user);
if (!extraGroup.isNumber() && !extraGroup.isString())
return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, "extraGroup"_s, "number or string"_s, extraGroup);
gid_t gid = 0;
if (extraGroup.isNumber()) {
Bun::V::validateInteger(scope, globalObject, extraGroup, "extraGroup"_s, jsNumber(0), jsNumber(std::pow(2, 31) - 1), &gid);
RETURN_IF_EXCEPTION(scope, {});
} else {
extraGroup = maybe_gid_by_name(scope, globalObject, extraGroup);
RETURN_IF_EXCEPTION(scope, {});
gid = extraGroup.toUInt32(globalObject);
}
const char* username = nullptr;
struct passwd pwd;
struct passwd* pp = nullptr;
char buf[8192];
if (user.isNumber()) {
uint32_t uid = 0;
Bun::V::validateInteger(scope, globalObject, user, "user"_s, jsNumber(0), jsNumber(std::pow(2, 31) - 1), &uid);
RETURN_IF_EXCEPTION(scope, {});
if (getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp) != 0 || pp == nullptr) {
auto message = makeString("User identifier does not exist: "_s, String::number(uid));
scope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
return {};
}
username = pp->pw_name;
} else {
auto userString = user.toWTFString(globalObject);
RETURN_IF_EXCEPTION(scope, {});
auto utf8 = userString.utf8();
username = utf8.data();
}
int result = initgroups(username, gid);
if (result != 0) {
throwSystemError(scope, globalObject, "initgroups"_s, errno);
return {};
}
return JSValue::encode(jsNumber(result));
}
#endif
JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, CallFrame* callFrame))
@@ -3658,7 +3711,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
version constructVersion PropertyCallback
versions constructVersions PropertyCallback
#if !OS(WINDOWS)
#if OS(DARWIN) || OS(LINUX)
getegid Process_functiongetegid Function 0
geteuid Process_functiongeteuid Function 0
getgid Process_functiongetgid Function 0
@@ -3669,6 +3722,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
seteuid Process_functionseteuid Function 1
setgid Process_functionsetgid Function 1
setgroups Process_functionsetgroups Function 1
initgroups Process_functioninitgroups Function 2
setuid Process_functionsetuid Function 1
#endif
@end

View File

@@ -0,0 +1,60 @@
'use strict';
const common = require('../common');
const assert = require('assert');
if (common.isWindows) {
assert.strictEqual(process.initgroups, undefined);
return;
}
const { isMainThread } = require('worker_threads');
if (!isMainThread) {
return;
}
[undefined, null, true, {}, [], () => {}].forEach((val) => {
assert.throws(
() => {
process.initgroups(val);
},
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message:
'The "user" argument must be ' +
'one of type number or string.' +
common.invalidArgTypeHelper(val)
}
);
});
[undefined, null, true, {}, [], () => {}].forEach((val) => {
assert.throws(
() => {
process.initgroups('foo', val);
},
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message:
'The "extraGroup" argument must be ' +
'one of type number or string.' +
common.invalidArgTypeHelper(val)
}
);
});
assert.throws(
() => {
process.initgroups(
'fhqwhgadshgnsdhjsdbkhsdabkfabkveyb',
'fhqwhgadshgnsdhjsdbkhsdabkfabkveyb'
);
},
{
code: 'ERR_UNKNOWN_CREDENTIAL',
message:
'Group identifier does not exist: fhqwhgadshgnsdhjsdbkhsdabkfabkveyb'
}
);