Skip to content

Commit ad7e344

Browse files
RaisinTenMylesBorins
authored andcommitted
fs: fix chown abort
This syncs the type assertion introduced in the referenced PR in the C++ side. Since chown, lchown, and fchown can accept -1 as a value for uid and gid, we should also accept signed integers from the JS side. Fixes: #37995 Refs: #31694 PR-URL: #38004 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent ce14080 commit ad7e344

File tree

3 files changed

+25
-24
lines changed

3 files changed

+25
-24
lines changed

lib/internal/fs/promises.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const kReadFileBufferLength = 512 * 1024;
88
const kReadFileUnknownBufferLength = 64 * 1024;
99
const kWriteFileMaxChunkSize = 512 * 1024;
1010

11+
// 2 ** 32 - 1
12+
const kMaxUserId = 4294967295;
13+
1114
const {
1215
ArrayPrototypePush,
1316
Error,
@@ -71,7 +74,6 @@ const {
7174
validateBoolean,
7275
validateBuffer,
7376
validateInteger,
74-
validateUint32
7577
} = require('internal/validators');
7678
const pathModule = require('path');
7779
const { promisify } = require('internal/util');
@@ -615,22 +617,22 @@ async function lchmod(path, mode) {
615617

616618
async function lchown(path, uid, gid) {
617619
path = getValidatedPath(path);
618-
validateUint32(uid, 'uid');
619-
validateUint32(gid, 'gid');
620+
validateInteger(uid, 'uid', -1, kMaxUserId);
621+
validateInteger(gid, 'gid', -1, kMaxUserId);
620622
return binding.lchown(pathModule.toNamespacedPath(path),
621623
uid, gid, kUsePromises);
622624
}
623625

624626
async function fchown(handle, uid, gid) {
625-
validateUint32(uid, 'uid');
626-
validateUint32(gid, 'gid');
627+
validateInteger(uid, 'uid', -1, kMaxUserId);
628+
validateInteger(gid, 'gid', -1, kMaxUserId);
627629
return binding.fchown(handle.fd, uid, gid, kUsePromises);
628630
}
629631

630632
async function chown(path, uid, gid) {
631633
path = getValidatedPath(path);
632-
validateUint32(uid, 'uid');
633-
validateUint32(gid, 'gid');
634+
validateInteger(uid, 'uid', -1, kMaxUserId);
635+
validateInteger(gid, 'gid', -1, kMaxUserId);
634636
return binding.chown(pathModule.toNamespacedPath(path),
635637
uid, gid, kUsePromises);
636638
}

src/node_file.cc

+12-13
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ using v8::ObjectTemplate;
7171
using v8::Promise;
7272
using v8::String;
7373
using v8::Symbol;
74-
using v8::Uint32;
7574
using v8::Undefined;
7675
using v8::Value;
7776

@@ -2184,11 +2183,11 @@ static void Chown(const FunctionCallbackInfo<Value>& args) {
21842183
BufferValue path(env->isolate(), args[0]);
21852184
CHECK_NOT_NULL(*path);
21862185

2187-
CHECK(args[1]->IsUint32());
2188-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Uint32>()->Value());
2186+
CHECK(IsSafeJsInt(args[1]));
2187+
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
21892188

2190-
CHECK(args[2]->IsUint32());
2191-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Uint32>()->Value());
2189+
CHECK(IsSafeJsInt(args[2]));
2190+
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
21922191

21932192
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
21942193
if (req_wrap_async != nullptr) { // chown(path, uid, gid, req)
@@ -2217,11 +2216,11 @@ static void FChown(const FunctionCallbackInfo<Value>& args) {
22172216
CHECK(args[0]->IsInt32());
22182217
const int fd = args[0].As<Int32>()->Value();
22192218

2220-
CHECK(args[1]->IsUint32());
2221-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Uint32>()->Value());
2219+
CHECK(IsSafeJsInt(args[1]));
2220+
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
22222221

2223-
CHECK(args[2]->IsUint32());
2224-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Uint32>()->Value());
2222+
CHECK(IsSafeJsInt(args[2]));
2223+
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
22252224

22262225
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
22272226
if (req_wrap_async != nullptr) { // fchown(fd, uid, gid, req)
@@ -2247,11 +2246,11 @@ static void LChown(const FunctionCallbackInfo<Value>& args) {
22472246
BufferValue path(env->isolate(), args[0]);
22482247
CHECK_NOT_NULL(*path);
22492248

2250-
CHECK(args[1]->IsUint32());
2251-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Uint32>()->Value());
2249+
CHECK(IsSafeJsInt(args[1]));
2250+
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
22522251

2253-
CHECK(args[2]->IsUint32());
2254-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Uint32>()->Value());
2252+
CHECK(IsSafeJsInt(args[2]));
2253+
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
22552254

22562255
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
22572256
if (req_wrap_async != nullptr) { // lchown(path, uid, gid, req)

test/parallel/test-fs-promises.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -191,24 +191,24 @@ async function getHandle(dest) {
191191

192192
assert.rejects(
193193
async () => {
194-
await chown(dest, 1, -1);
194+
await chown(dest, 1, -2);
195195
},
196196
{
197197
code: 'ERR_OUT_OF_RANGE',
198198
name: 'RangeError',
199199
message: 'The value of "gid" is out of range. ' +
200-
'It must be >= 0 && < 4294967296. Received -1'
200+
'It must be >= -1 && <= 4294967295. Received -2'
201201
});
202202

203203
assert.rejects(
204204
async () => {
205-
await handle.chown(1, -1);
205+
await handle.chown(1, -2);
206206
},
207207
{
208208
code: 'ERR_OUT_OF_RANGE',
209209
name: 'RangeError',
210210
message: 'The value of "gid" is out of range. ' +
211-
'It must be >= 0 && < 4294967296. Received -1'
211+
'It must be >= -1 && <= 4294967295. Received -2'
212212
});
213213

214214
await handle.close();

0 commit comments

Comments
 (0)