This repository was archived by the owner on Apr 22, 2023. It is now read-only.
This repository was archived by the owner on Apr 22, 2023. It is now read-only.
node::Chown() throws up on large UID values on OS X #5890
Closed
Description
Let's look up the UID of our old buddy nobody
and change a file to be owned by nobody
using the following code:
var fs = require("fs");
var exec = require("child_process").exec;
function mapIds(username, groupname, callback) {
if (!callback) throw new Error("mapIds requires callback");
if (!username) return callback(new Error("mapIds requires username"));
if (!groupname) return callback(new Error("mapIds requires groupname"));
exec('id -u ' + username, function (error, stdout, stderr) {
if (error) return callback(error);
if (stderr) return callback(new Error(stderr));
var uid = +stdout;
exec('id -g ' + groupname, function (error, stdout, stderr) {
if (error) return callback(error);
if (stderr) return callback(new Error(stderr));
var gid = +stdout;
callback(null, uid, gid);
});
});
}
mapIds('nobody', 'nobody', function(error, uid, gid) {
console.log("uid: %s, gid: %s", uid, gid); // => "uid: 4294967294, gid: 4294967294"
fs.chown('/dev/null', uid, gid, function(error) {
console.log("execution will never reach this point.");
});
});
Instead of returning an error through the callback, or actually doing what you'd expect, instead this stacktrace gets dumped:
fs.js:853
binding.chown(pathModule._makeLong(path), uid, gid, callback);
^
TypeError: uid must be an int
at Object.fs.chown (fs.js:853:11)
at repl:3:4
at repl:16:1
at ChildProcess.exithandler (child_process.js:635:7)
at ChildProcess.EventEmitter.emit (events.js:98:17)
at maybeClose (child_process.js:735:16)
at Socket.<anonymous> (child_process.js:948:11)
at Socket.EventEmitter.emit (events.js:95:17)
at Pipe.close (net.js:466:12)
uid_t
is defined to be unsigned int, and by convention and tradition the uid and gid for nobody
on Darwin are -2 (which wraps around via implicit casting), so it seems that the checks in node_file.cc
should be modified to use ->IsUint32()
instead of ->IsInt32()
.