Skip to content

Commit

Permalink
fs: fix handling of uv_stat_t fields
Browse files Browse the repository at this point in the history
`FChown` and `Chown` test that the `uid` and `gid` parameters
they receive are unsigned integers, but `Stat()` and `FStat()`
would return the corresponding fields of `uv_stat_t` as signed
integers. Applications which pass those these values directly
to `Chown` may fail
(e.g. for `nobody` on OS X, who has an `uid` of `-2`, see e.g.
nodejs/node-v0.x-archive#5890).

This patch changes the `Integer::New()` call for `uid` and `gid`
to `Integer::NewFromUnsigned()`.

All other fields are kept as they are, for performance, but
strictly speaking the respective sizes of those
fields aren’t specified, either.

Ref: npm/npm#13918
  • Loading branch information
addaleax committed Sep 13, 2016
1 parent 7f2c9ba commit 28ccbf1
Showing 1 changed file with 20 additions and 10 deletions.
30 changes: 20 additions & 10 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -433,34 +433,44 @@ Local<Value> BuildStatsObject(Environment* env, const uv_stat_t* s) {
// crash();
// }
//
// We need to check the return value of Integer::New() and Date::New()
// We need to check the return value of Number::New() and Date::New()
// and make sure that we bail out when V8 returns an empty handle.

// Integers.
// Unsigned integers. It does not actually seem to be specified whether
// uid and gid are unsigned or not, but in practice they are unsigned,
// and Node’s (F)Chown functions do check their arguments for unsignedness.
#define X(name) \
Local<Value> name = Integer::New(env->isolate(), s->st_##name); \
Local<Value> name = Integer::NewFromUnsigned(env->isolate(), s->st_##name); \
if (name.IsEmpty()) \
return handle_scope.Escape(Local<Object>()); \
return Local<Object>(); \

X(dev)
X(mode)
X(nlink)
X(uid)
X(gid)
X(rdev)
# if defined(__POSIX__)
X(blksize)
# else
Local<Value> blksize = Undefined(env->isolate());
# endif
#undef X

// Integers.
#define X(name) \
Local<Value> name = Integer::NewFromUnsigned(env->isolate(), s->st_##name); \
if (name.IsEmpty()) \
return Local<Object>(); \

X(dev)
X(mode)
X(nlink)
X(rdev)
#undef X

// Numbers.
#define X(name) \
Local<Value> name = Number::New(env->isolate(), \
static_cast<double>(s->st_##name)); \
if (name.IsEmpty()) \
return handle_scope.Escape(Local<Object>()); \
return Local<Object>(); \

X(ino)
X(size)
Expand All @@ -479,7 +489,7 @@ Local<Value> BuildStatsObject(Environment* env, const uv_stat_t* s) {
(static_cast<double>(s->st_##name.tv_nsec / 1000000))); \
\
if (name##_msec.IsEmpty()) \
return handle_scope.Escape(Local<Object>()); \
return Local<Object>(); \

X(atim)
X(mtim)
Expand Down

0 comments on commit 28ccbf1

Please sign in to comment.