Skip to content
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
@othiym23

Description

@othiym23

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().

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions