diff --git a/lib/fs.js b/lib/fs.js index 7cad38ad1f1..1854a486b89 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -206,7 +206,7 @@ function modeNum(m, def) { } } -fs.open = function(path, flags, mode, callback) { +fs.open = safeWrap(0, function(path, flags, mode, callback) { callback = arguments[arguments.length - 1]; if (typeof(callback) !== 'function') { callback = noop; @@ -215,12 +215,12 @@ fs.open = function(path, flags, mode, callback) { mode = modeNum(mode, '0666'); binding.open(path, stringToFlags(flags), mode, callback); -}; +}); -fs.openSync = function(path, flags, mode) { +fs.openSync = safeWrap(0, function(path, flags, mode) { mode = modeNum(mode, '0666'); return binding.open(path, stringToFlags(flags), mode); -}; +}); fs.read = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { @@ -313,13 +313,13 @@ fs.writeSync = function(fd, buffer, offset, length, position) { return binding.write(fd, buffer, offset, length, position); }; -fs.rename = function(oldPath, newPath, callback) { +fs.rename = safeWrap(0, 1, function(oldPath, newPath, callback) { binding.rename(oldPath, newPath, callback || noop); -}; +}); -fs.renameSync = function(oldPath, newPath) { +fs.renameSync = safeWrap(0, 1, function(oldPath, newPath) { return binding.rename(oldPath, newPath); -}; +}); fs.truncate = function(fd, len, callback) { binding.truncate(fd, len, callback || noop); @@ -329,13 +329,13 @@ fs.truncateSync = function(fd, len) { return binding.truncate(fd, len); }; -fs.rmdir = function(path, callback) { +fs.rmdir = safeWrap(0, function(path, callback) { binding.rmdir(path, callback || noop); -}; +}); -fs.rmdirSync = function(path) { +fs.rmdirSync = safeWrap(0, function(path) { return binding.rmdir(path); -}; +}); fs.fdatasync = function(fd, callback) { binding.fdatasync(fd, callback || noop); @@ -353,13 +353,13 @@ fs.fsyncSync = function(fd) { return binding.fsync(fd); }; -fs.mkdir = function(path, mode, callback) { +fs.mkdir = safeWrap(0, function(path, mode, callback) { binding.mkdir(path, modeNum(mode), callback || noop); -}; +}); -fs.mkdirSync = function(path, mode) { +fs.mkdirSync = safeWrap(0, function(path, mode) { return binding.mkdir(path, modeNum(mode)); -}; +}); fs.sendfile = function(outFd, inFd, inOffset, length, callback) { binding.sendfile(outFd, inFd, inOffset, length, callback || noop); @@ -369,69 +369,69 @@ fs.sendfileSync = function(outFd, inFd, inOffset, length) { return binding.sendfile(outFd, inFd, inOffset, length); }; -fs.readdir = function(path, callback) { +fs.readdir = safeWrap(0, function(path, callback) { binding.readdir(path, callback || noop); -}; +}); -fs.readdirSync = function(path) { +fs.readdirSync = safeWrap(0, function(path) { return binding.readdir(path); -}; +}); fs.fstat = function(fd, callback) { binding.fstat(fd, callback || noop); }; -fs.lstat = function(path, callback) { +fs.lstat = safeWrap(0, function(path, callback) { binding.lstat(path, callback || noop); -}; +}); -fs.stat = function(path, callback) { +fs.stat = safeWrap(0, function(path, callback) { binding.stat(path, callback || noop); -}; +}); fs.fstatSync = function(fd) { return binding.fstat(fd); }; -fs.lstatSync = function(path) { +fs.lstatSync = safeWrap(0, function(path) { return binding.lstat(path); -}; +}); -fs.statSync = function(path) { +fs.statSync = safeWrap(0, function(path) { return binding.stat(path); -}; +}); -fs.readlink = function(path, callback) { +fs.readlink = safeWrap(0, function(path, callback) { binding.readlink(path, callback || noop); -}; +}); -fs.readlinkSync = function(path) { +fs.readlinkSync = safeWrap(0, function(path) { return binding.readlink(path); -}; +}); -fs.symlink = function(destination, path, callback) { +fs.symlink = safeWrap(0, 1, function(destination, path, callback) { binding.symlink(destination, path, callback || noop); -}; +}); -fs.symlinkSync = function(destination, path) { +fs.symlinkSync = safeWrap(0, 1, function(destination, path) { return binding.symlink(destination, path); -}; +}); -fs.link = function(srcpath, dstpath, callback) { +fs.link = safeWrap(0, 1, function(srcpath, dstpath, callback) { binding.link(srcpath, dstpath, callback || noop); -}; +}); -fs.linkSync = function(srcpath, dstpath) { +fs.linkSync = safeWrap(0, 1, function(srcpath, dstpath) { return binding.link(srcpath, dstpath); -}; +}); -fs.unlink = function(path, callback) { +fs.unlink = safeWrap(0, function(path, callback) { binding.unlink(path, callback || noop); -}; +}); -fs.unlinkSync = function(path) { +fs.unlinkSync = safeWrap(0, function(path) { return binding.unlink(path); -}; +}); fs.fchmod = function(fd, mode, callback) { binding.fchmod(fd, modeNum(mode), callback || noop); @@ -460,13 +460,13 @@ if (constants.hasOwnProperty('O_SYMLINK')) { } -fs.chmod = function(path, mode, callback) { +fs.chmod = safeWrap(0, function(path, mode, callback) { binding.chmod(path, modeNum(mode), callback || noop); -}; +}); -fs.chmodSync = function(path, mode) { +fs.chmodSync = safeWrap(0, function(path, mode) { return binding.chmod(path, modeNum(mode)); -}; +}); if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchown = function(path, uid, gid, callback) { @@ -494,13 +494,13 @@ fs.fchownSync = function(fd, uid, gid) { return binding.fchown(fd, uid, gid); }; -fs.chown = function(path, uid, gid, callback) { +fs.chown = safeWrap(0, function(path, uid, gid, callback) { binding.chown(path, uid, gid, callback || noop); -}; +}); -fs.chownSync = function(path, uid, gid) { +fs.chownSync = safeWrap(0, function(path, uid, gid) { return binding.chown(path, uid, gid); -}; +}); // converts Date or number to a fractional UNIX timestamp function toUnixTimestamp(time) { @@ -517,17 +517,17 @@ function toUnixTimestamp(time) { // exported for unit tests, not for public consumption fs._toUnixTimestamp = toUnixTimestamp; -fs.utimes = function(path, atime, mtime, callback) { +fs.utimes = safeWrap(0, function(path, atime, mtime, callback) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(path, atime, mtime, callback || noop); -}; +}); -fs.utimesSync = function(path, atime, mtime) { +fs.utimesSync = safeWrap(0, function(path, atime, mtime) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(path, atime, mtime); -}; +}); fs.futimes = function(fd, atime, mtime, callback) { atime = toUnixTimestamp(atime); @@ -603,9 +603,9 @@ function StatWatcher() { util.inherits(StatWatcher, EventEmitter); -StatWatcher.prototype.start = function(filename, persistent, interval) { +StatWatcher.prototype.start = safeWrap(0, function(filename, persistent, interval) { this._handle.start(filename, persistent, interval); -}; +}); StatWatcher.prototype.stop = function() { @@ -639,9 +639,9 @@ fs.watchFile = function(filename) { if (statWatchers[filename]) { stat = statWatchers[filename]; } else { - statWatchers[filename] = new StatWatcher(); - stat = statWatchers[filename]; + stat = new StatWatcher(); stat.start(filename, options.persistent, options.interval); + statWatchers[filename] = stat; } stat.addListener('change', listener); return stat; @@ -1253,6 +1253,37 @@ WriteStream.prototype.destroy = function(cb) { } }; +function safeWrap() { + var unsafeArgs = [].slice.call(arguments, 0, arguments.length-1); + var f = arguments[arguments.length-1]; + function fail(n) { + var err = new Error("fs function was called with a nullbyte in argument #"+n); + if (typeof arguments[arguments.length-1] === 'function') { + arguments[arguments.length-1](err); + } else { + throw err; + } + } + if (unsafeArgs.length === 1) { + var unsafeArg = unsafeArgs[0]; + return function() { + if (arguments[unsafeArg].indexOf('\0') !== -1) { + return fail(unsafeArg); + } + return f.apply(this, arguments); + }; + } else { + return function() { + for (var i=0; i