From de95b66d2baed193f5112e1c5066c6f40c82bef0 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Sat, 23 Jul 2016 15:08:14 +1000 Subject: [PATCH 1/3] fs: return undefined on module read uv fs error PR-URL: https://github.com/nodejs/node/pull/8277 --- src/node_file.cc | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index 77d11756a2dbe5..7244644fa354f2 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -538,6 +538,7 @@ static void InternalModuleReadFile(const FunctionCallbackInfo& args) { std::vector chars; int64_t offset = 0; + ssize_t numchars; for (;;) { const size_t kBlockSize = 32 << 10; const size_t start = chars.size(); @@ -548,11 +549,13 @@ static void InternalModuleReadFile(const FunctionCallbackInfo& args) { buf.len = kBlockSize; uv_fs_t read_req; - const ssize_t numchars = - uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr); + numchars = uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr); uv_fs_req_cleanup(&read_req); - CHECK_GE(numchars, 0); + if (numchars < 0) { + break; + } + if (static_cast(numchars) < kBlockSize) { chars.resize(start + numchars); } @@ -566,17 +569,21 @@ static void InternalModuleReadFile(const FunctionCallbackInfo& args) { CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr)); uv_fs_req_cleanup(&close_req); - size_t start = 0; - if (chars.size() >= 3 && 0 == memcmp(&chars[0], "\xEF\xBB\xBF", 3)) { - start = 3; // Skip UTF-8 BOM. - } + if (numchars < 0) { + args.GetReturnValue().Set(Undefined(env->isolate())); + } else { + size_t start = 0; + if (chars.size() >= 3 && 0 == memcmp(&chars[0], "\xEF\xBB\xBF", 3)) { + start = 3; // Skip UTF-8 BOM. + } - Local chars_string = - String::NewFromUtf8(env->isolate(), - &chars[start], - String::kNormalString, - chars.size() - start); - args.GetReturnValue().Set(chars_string); + Local chars_string = + String::NewFromUtf8(env->isolate(), + &chars[start], + String::kNormalString, + chars.size() - start); + args.GetReturnValue().Set(chars_string); + } } // Used to speed up module loading. Returns 0 if the path refers to From 39db98ca5e20b1c28b5058c7b049747324d955bd Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Sat, 23 Jul 2016 15:29:14 +1000 Subject: [PATCH 2/3] module: apply null bytes check to module read path PR-URL: https://github.com/nodejs/node/pull/8277 --- lib/fs.js | 3 + lib/module.js | 18 ++++++ test/parallel/test-fs-null-bytes.js | 86 +++++++++++++++++------------ 3 files changed, 73 insertions(+), 34 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 2fc22b1bddecc0..78cb73167b1dbc 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -130,6 +130,9 @@ function assertEncoding(encoding) { } } +// This is duplicated in module.js and needs to be moved to internal/fs.js +// once it is OK again to include internal/ resources in fs.js. +// See: https://github.com/nodejs/node/pull/6413 function nullCheck(path, callback) { if (('' + path).indexOf('\u0000') !== -1) { var er = new Error('Path must be a string without null bytes'); diff --git a/lib/module.js b/lib/module.js index fe9700f7a673ae..9a2b65f4f6da7d 100644 --- a/lib/module.js +++ b/lib/module.js @@ -34,6 +34,22 @@ function stat(filename) { stat.cache = null; +// This is duplicated from fs.js and needs to be moved to internal/fs.js +// once it is OK again to include internal/ resources in fs.js. +// See: https://github.com/nodejs/node/pull/6413 +function nullCheck(path, callback) { + if (('' + path).indexOf('\u0000') !== -1) { + var er = new Error('Path must be a string without null bytes'); + er.code = 'ENOENT'; + if (typeof callback !== 'function') + throw er; + process.nextTick(callback, er); + return false; + } + return true; +} + + function Module(id, parent) { this.id = id; this.exports = {}; @@ -135,6 +151,8 @@ function tryExtensions(p, exts, isMain) { var warned = false; Module._findPath = function(request, paths, isMain) { + nullCheck(request); + if (path.isAbsolute(request)) { paths = ['']; } else if (!paths || paths.length === 0) { diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js index 3c70d2953ca0f4..a2bc427d77e02c 100644 --- a/test/parallel/test-fs-null-bytes.js +++ b/test/parallel/test-fs-null-bytes.js @@ -2,52 +2,54 @@ var common = require('../common'); var assert = require('assert'); var fs = require('fs'); +var expectedError = /Path must be a string without null bytes/; function check(async, sync) { - var expected = /Path must be a string without null bytes/; var argsSync = Array.prototype.slice.call(arguments, 2); var argsAsync = argsSync.concat(function(er) { - assert(er && er.message.match(expected)); + assert(er && er.message.match(expectedError)); assert.equal(er.code, 'ENOENT'); }); if (sync) assert.throws(function() { - console.error(sync.name, argsSync); - sync.apply(null, argsSync); - }, expected); + console.error(`fs.${sync}()`, argsSync); + fs[sync].apply(null, argsSync); + }, expectedError); - if (async) - async.apply(null, argsAsync); + if (async) { + console.error(`fs.${async}()`, argsAsync); + fs[async].apply(null, argsAsync); + } } -check(fs.access, fs.accessSync, 'foo\u0000bar'); -check(fs.access, fs.accessSync, 'foo\u0000bar', fs.F_OK); -check(fs.appendFile, fs.appendFileSync, 'foo\u0000bar'); -check(fs.chmod, fs.chmodSync, 'foo\u0000bar', '0644'); -check(fs.chown, fs.chownSync, 'foo\u0000bar', 12, 34); -check(fs.link, fs.linkSync, 'foo\u0000bar', 'foobar'); -check(fs.link, fs.linkSync, 'foobar', 'foo\u0000bar'); -check(fs.lstat, fs.lstatSync, 'foo\u0000bar'); -check(fs.mkdir, fs.mkdirSync, 'foo\u0000bar', '0755'); -check(fs.open, fs.openSync, 'foo\u0000bar', 'r'); -check(fs.readFile, fs.readFileSync, 'foo\u0000bar'); -check(fs.readdir, fs.readdirSync, 'foo\u0000bar'); -check(fs.readlink, fs.readlinkSync, 'foo\u0000bar'); -check(fs.realpath, fs.realpathSync, 'foo\u0000bar'); -check(fs.rename, fs.renameSync, 'foo\u0000bar', 'foobar'); -check(fs.rename, fs.renameSync, 'foobar', 'foo\u0000bar'); -check(fs.rmdir, fs.rmdirSync, 'foo\u0000bar'); -check(fs.stat, fs.statSync, 'foo\u0000bar'); -check(fs.symlink, fs.symlinkSync, 'foo\u0000bar', 'foobar'); -check(fs.symlink, fs.symlinkSync, 'foobar', 'foo\u0000bar'); -check(fs.truncate, fs.truncateSync, 'foo\u0000bar'); -check(fs.unlink, fs.unlinkSync, 'foo\u0000bar'); -check(null, fs.unwatchFile, 'foo\u0000bar', common.fail); -check(fs.utimes, fs.utimesSync, 'foo\u0000bar', 0, 0); -check(null, fs.watch, 'foo\u0000bar', common.fail); -check(null, fs.watchFile, 'foo\u0000bar', common.fail); -check(fs.writeFile, fs.writeFileSync, 'foo\u0000bar'); +check('access', 'accessSync', 'foo\u0000bar'); +check('access', 'accessSync', 'foo\u0000bar', 'F_OK'); +check('appendFile', 'appendFileSync', 'foo\u0000bar'); +check('chmod', 'chmodSync', 'foo\u0000bar', '0644'); +check('chown', 'chownSync', 'foo\u0000bar', 12, 34); +check('link', 'linkSync', 'foo\u0000bar', 'foobar'); +check('link', 'linkSync', 'foobar', 'foo\u0000bar'); +check('lstat', 'lstatSync', 'foo\u0000bar'); +check('mkdir', 'mkdirSync', 'foo\u0000bar', '0755'); +check('open', 'openSync', 'foo\u0000bar', 'r'); +check('readFile', 'readFileSync', 'foo\u0000bar'); +check('readdir', 'readdirSync', 'foo\u0000bar'); +check('readlink', 'readlinkSync', 'foo\u0000bar'); +check('realpath', 'realpathSync', 'foo\u0000bar'); +check('rename', 'renameSync', 'foo\u0000bar', 'foobar'); +check('rename', 'renameSync', 'foobar', 'foo\u0000bar'); +check('rmdir', 'rmdirSync', 'foo\u0000bar'); +check('stat', 'statSync', 'foo\u0000bar'); +check('symlink', 'symlinkSync', 'foo\u0000bar', 'foobar'); +check('symlink', 'symlinkSync', 'foobar', 'foo\u0000bar'); +check('truncate', 'truncateSync', 'foo\u0000bar'); +check('unlink', 'unlinkSync', 'foo\u0000bar'); +check(null, 'unwatchFile', 'foo\u0000bar', common.fail); +check('utimes', 'utimesSync', 'foo\u0000bar', 0, 0); +check(null, 'watch', 'foo\u0000bar', common.fail); +check(null, 'watchFile', 'foo\u0000bar', common.fail); +check('writeFile', 'writeFileSync', 'foo\u0000bar'); // an 'error' for exists means that it doesn't exist. // one of many reasons why this file is the absolute worst. @@ -55,3 +57,19 @@ fs.exists('foo\u0000bar', function(exists) { assert(!exists); }); assert(!fs.existsSync('foo\u0000bar')); + +function checkRequire(arg) { + assert.throws(function() { + console.error(`require(${JSON.stringify(arg)})`); + require(arg); + }, expectedError); +} + +checkRequire('\u0000'); +checkRequire('foo\u0000bar'); +checkRequire('foo\u0000'); +checkRequire('foo/\u0000'); +checkRequire('foo/\u0000.js'); +checkRequire('\u0000/foo'); +checkRequire('./foo/\u0000'); +checkRequire('./\u0000/foo'); From 507b3eee622526b7ad32f5dbc78f489aa4c9083c Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Sat, 27 Aug 2016 14:02:32 +1000 Subject: [PATCH 3/3] fs: move nullCheck to internal/fs.js to dedupe --- lib/fs.js | 112 ++++++++++++++++++++------------------------- lib/internal/fs.js | 14 ++++++ lib/module.js | 19 +------- node.gyp | 1 + 4 files changed, 66 insertions(+), 80 deletions(-) create mode 100644 lib/internal/fs.js diff --git a/lib/fs.js b/lib/fs.js index 78cb73167b1dbc..10d9e2270dbfec 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -6,6 +6,7 @@ const constants = process.binding('constants').fs; const util = require('util'); const pathModule = require('path'); +const internalFs = require('internal/fs'); const binding = process.binding('fs'); const fs = exports; @@ -130,21 +131,6 @@ function assertEncoding(encoding) { } } -// This is duplicated in module.js and needs to be moved to internal/fs.js -// once it is OK again to include internal/ resources in fs.js. -// See: https://github.com/nodejs/node/pull/6413 -function nullCheck(path, callback) { - if (('' + path).indexOf('\u0000') !== -1) { - var er = new Error('Path must be a string without null bytes'); - er.code = 'ENOENT'; - if (typeof callback !== 'function') - throw er; - process.nextTick(callback, er); - return false; - } - return true; -} - function isFd(path) { return (path >>> 0) === path; } @@ -231,7 +217,7 @@ fs.access = function(path, mode, callback) { throw new TypeError('"callback" argument must be a function'); } - if (!nullCheck(path, callback)) + if (!internalFs.nullCheck(path, callback)) return; mode = mode | 0; @@ -241,7 +227,7 @@ fs.access = function(path, mode, callback) { }; fs.accessSync = function(path, mode) { - nullCheck(path); + internalFs.nullCheck(path); if (mode === undefined) mode = fs.F_OK; @@ -252,7 +238,7 @@ fs.accessSync = function(path, mode) { }; fs.exists = function(path, callback) { - if (!nullCheck(path, cb)) return; + if (!internalFs.nullCheck(path, cb)) return; var req = new FSReqWrap(); req.oncomplete = cb; binding.stat(pathModule._makeLong(path), req); @@ -263,7 +249,7 @@ fs.exists = function(path, callback) { fs.existsSync = function(path) { try { - nullCheck(path); + internalFs.nullCheck(path); binding.stat(pathModule._makeLong(path)); return true; } catch (e) { @@ -287,7 +273,7 @@ fs.readFile = function(path, options, callback_) { var flag = options.flag || 'r'; - if (!nullCheck(path, callback)) + if (!internalFs.nullCheck(path, callback)) return; var context = new ReadFileContext(callback, encoding); @@ -626,7 +612,7 @@ fs.open = function(path, flags, mode, callback_) { var callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 0o666); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -639,7 +625,7 @@ fs.open = function(path, flags, mode, callback_) { fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 0o666); - nullCheck(path); + internalFs.nullCheck(path); return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); }; @@ -797,8 +783,8 @@ fs.writeSync = function(fd, buffer, offset, length, position) { fs.rename = function(oldPath, newPath, callback) { callback = makeCallback(callback); - if (!nullCheck(oldPath, callback)) return; - if (!nullCheck(newPath, callback)) return; + if (!internalFs.nullCheck(oldPath, callback)) return; + if (!internalFs.nullCheck(newPath, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.rename(pathModule._makeLong(oldPath), @@ -807,8 +793,8 @@ fs.rename = function(oldPath, newPath, callback) { }; fs.renameSync = function(oldPath, newPath) { - nullCheck(oldPath); - nullCheck(newPath); + internalFs.nullCheck(oldPath); + internalFs.nullCheck(newPath); return binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath)); }; @@ -878,14 +864,14 @@ fs.ftruncateSync = function(fd, len) { fs.rmdir = function(path, callback) { callback = maybeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.rmdir(pathModule._makeLong(path), req); }; fs.rmdirSync = function(path) { - nullCheck(path); + internalFs.nullCheck(path); return binding.rmdir(pathModule._makeLong(path)); }; @@ -912,7 +898,7 @@ fs.fsyncSync = function(fd) { fs.mkdir = function(path, mode, callback) { if (typeof mode === 'function') callback = mode; callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.mkdir(pathModule._makeLong(path), @@ -921,7 +907,7 @@ fs.mkdir = function(path, mode, callback) { }; fs.mkdirSync = function(path, mode) { - nullCheck(path); + internalFs.nullCheck(path); return binding.mkdir(pathModule._makeLong(path), modeNum(mode, 0o777)); }; @@ -938,7 +924,7 @@ fs.readdir = function(path, options, callback) { throw new TypeError('"options" must be a string or an object'); callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.readdir(pathModule._makeLong(path), options.encoding, req); @@ -950,7 +936,7 @@ fs.readdirSync = function(path, options) { options = {encoding: options}; if (typeof options !== 'object') throw new TypeError('"options" must be a string or an object'); - nullCheck(path); + internalFs.nullCheck(path); return binding.readdir(pathModule._makeLong(path), options.encoding); }; @@ -962,7 +948,7 @@ fs.fstat = function(fd, callback) { fs.lstat = function(path, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.lstat(pathModule._makeLong(path), req); @@ -970,7 +956,7 @@ fs.lstat = function(path, callback) { fs.stat = function(path, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.stat(pathModule._makeLong(path), req); @@ -981,12 +967,12 @@ fs.fstatSync = function(fd) { }; fs.lstatSync = function(path) { - nullCheck(path); + internalFs.nullCheck(path); return binding.lstat(pathModule._makeLong(path)); }; fs.statSync = function(path) { - nullCheck(path); + internalFs.nullCheck(path); return binding.stat(pathModule._makeLong(path)); }; @@ -1001,7 +987,7 @@ fs.readlink = function(path, options, callback) { if (typeof options !== 'object') throw new TypeError('"options" must be a string or an object'); callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.readlink(pathModule._makeLong(path), options.encoding, req); @@ -1013,7 +999,7 @@ fs.readlinkSync = function(path, options) { options = {encoding: options}; if (typeof options !== 'object') throw new TypeError('"options" must be a string or an object'); - nullCheck(path); + internalFs.nullCheck(path); return binding.readlink(pathModule._makeLong(path), options.encoding); }; @@ -1036,8 +1022,8 @@ fs.symlink = function(target, path, type_, callback_) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); - if (!nullCheck(target, callback)) return; - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(target, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -1051,8 +1037,8 @@ fs.symlink = function(target, path, type_, callback_) { fs.symlinkSync = function(target, path, type) { type = (typeof type === 'string' ? type : null); - nullCheck(target); - nullCheck(path); + internalFs.nullCheck(target); + internalFs.nullCheck(path); return binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule._makeLong(path), @@ -1061,8 +1047,8 @@ fs.symlinkSync = function(target, path, type) { fs.link = function(srcpath, dstpath, callback) { callback = makeCallback(callback); - if (!nullCheck(srcpath, callback)) return; - if (!nullCheck(dstpath, callback)) return; + if (!internalFs.nullCheck(srcpath, callback)) return; + if (!internalFs.nullCheck(dstpath, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -1073,22 +1059,22 @@ fs.link = function(srcpath, dstpath, callback) { }; fs.linkSync = function(srcpath, dstpath) { - nullCheck(srcpath); - nullCheck(dstpath); + internalFs.nullCheck(srcpath); + internalFs.nullCheck(dstpath); return binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath)); }; fs.unlink = function(path, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.unlink(pathModule._makeLong(path), req); }; fs.unlinkSync = function(path) { - nullCheck(path); + internalFs.nullCheck(path); return binding.unlink(pathModule._makeLong(path)); }; @@ -1144,7 +1130,7 @@ if (constants.hasOwnProperty('O_SYMLINK')) { fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.chmod(pathModule._makeLong(path), @@ -1153,7 +1139,7 @@ fs.chmod = function(path, mode, callback) { }; fs.chmodSync = function(path, mode) { - nullCheck(path); + internalFs.nullCheck(path); return binding.chmod(pathModule._makeLong(path), modeNum(mode)); }; @@ -1187,14 +1173,14 @@ fs.fchownSync = function(fd, uid, gid) { fs.chown = function(path, uid, gid, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.chown(pathModule._makeLong(path), uid, gid, req); }; fs.chownSync = function(path, uid, gid) { - nullCheck(path); + internalFs.nullCheck(path); return binding.chown(pathModule._makeLong(path), uid, gid); }; @@ -1221,7 +1207,7 @@ fs._toUnixTimestamp = toUnixTimestamp; fs.utimes = function(path, atime, mtime, callback) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; + if (!internalFs.nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; binding.utimes(pathModule._makeLong(path), @@ -1231,7 +1217,7 @@ fs.utimes = function(path, atime, mtime, callback) { }; fs.utimesSync = function(path, atime, mtime) { - nullCheck(path); + internalFs.nullCheck(path); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(pathModule._makeLong(path), atime, mtime); @@ -1422,7 +1408,7 @@ FSWatcher.prototype.start = function(filename, persistent, recursive, encoding) { - nullCheck(filename); + internalFs.nullCheck(filename); var err = this._handle.start(pathModule._makeLong(filename), persistent, recursive, @@ -1440,7 +1426,7 @@ FSWatcher.prototype.close = function() { }; fs.watch = function(filename, options, listener) { - nullCheck(filename); + internalFs.nullCheck(filename); options = options || {}; if (typeof options === 'function') { @@ -1498,7 +1484,7 @@ util.inherits(StatWatcher, EventEmitter); StatWatcher.prototype.start = function(filename, persistent, interval) { - nullCheck(filename); + internalFs.nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; @@ -1511,7 +1497,7 @@ StatWatcher.prototype.stop = function() { const statWatchers = new Map(); fs.watchFile = function(filename, options, listener) { - nullCheck(filename); + internalFs.nullCheck(filename); filename = pathModule.resolve(filename); var stat; @@ -1547,7 +1533,7 @@ fs.watchFile = function(filename, options, listener) { }; fs.unwatchFile = function(filename, listener) { - nullCheck(filename); + internalFs.nullCheck(filename); filename = pathModule.resolve(filename); var stat = statWatchers.get(filename); @@ -1595,7 +1581,7 @@ fs.realpathSync = function realpathSync(p, options) { options = {encoding: options}; else if (typeof options !== 'object') throw new TypeError('"options" must be a string or an object'); - nullCheck(p); + internalFs.nullCheck(p); p = p.toString('utf8'); p = pathModule.resolve(p); @@ -1694,7 +1680,7 @@ fs.realpath = function realpath(p, options, callback) { } else if (typeof options !== 'object') { throw new TypeError('"options" must be a string or an object'); } - if (!nullCheck(p, callback)) + if (!internalFs.nullCheck(p, callback)) return; p = p.toString('utf8'); @@ -1815,7 +1801,7 @@ fs.mkdtemp = function(prefix, options, callback) { throw new TypeError('"options" must be a string or an object'); callback = makeCallback(callback); - if (!nullCheck(prefix, callback)) { + if (!internalFs.nullCheck(prefix, callback)) { return; } @@ -1835,7 +1821,7 @@ fs.mkdtempSync = function(prefix, options) { options = {encoding: options}; if (typeof options !== 'object') throw new TypeError('"options" must be a string or an object'); - nullCheck(prefix); + internalFs.nullCheck(prefix); return binding.mkdtemp(prefix + 'XXXXXX', options.encoding); }; diff --git a/lib/internal/fs.js b/lib/internal/fs.js new file mode 100644 index 00000000000000..4d1f1434f43f9d --- /dev/null +++ b/lib/internal/fs.js @@ -0,0 +1,14 @@ +'use strict'; + +// Used by all fs.js primitive exports and require via module.js +exports.nullCheck = function nullCheck(path, callback) { + if (('' + path).indexOf('\u0000') !== -1) { + var er = new Error('Path must be a string without null bytes'); + er.code = 'ENOENT'; + if (typeof callback !== 'function') + throw er; + process.nextTick(callback, er); + return false; + } + return true; +}; diff --git a/lib/module.js b/lib/module.js index 9a2b65f4f6da7d..a88c8d2fc3eb4b 100644 --- a/lib/module.js +++ b/lib/module.js @@ -4,6 +4,7 @@ const NativeModule = require('native_module'); const util = require('util'); const internalModule = require('internal/module'); const internalUtil = require('internal/util'); +const internalFs = require('internal/fs'); const vm = require('vm'); const assert = require('assert').ok; const fs = require('fs'); @@ -34,22 +35,6 @@ function stat(filename) { stat.cache = null; -// This is duplicated from fs.js and needs to be moved to internal/fs.js -// once it is OK again to include internal/ resources in fs.js. -// See: https://github.com/nodejs/node/pull/6413 -function nullCheck(path, callback) { - if (('' + path).indexOf('\u0000') !== -1) { - var er = new Error('Path must be a string without null bytes'); - er.code = 'ENOENT'; - if (typeof callback !== 'function') - throw er; - process.nextTick(callback, er); - return false; - } - return true; -} - - function Module(id, parent) { this.id = id; this.exports = {}; @@ -151,7 +136,7 @@ function tryExtensions(p, exts, isMain) { var warned = false; Module._findPath = function(request, paths, isMain) { - nullCheck(request); + internalFs.nullCheck(request); if (path.isAbsolute(request)) { paths = ['']; diff --git a/node.gyp b/node.gyp index 1b619a6c5b2bc6..c359948b5c4b83 100644 --- a/node.gyp +++ b/node.gyp @@ -77,6 +77,7 @@ 'lib/internal/child_process.js', 'lib/internal/cluster.js', 'lib/internal/freelist.js', + 'lib/internal/fs.js', 'lib/internal/linkedlist.js', 'lib/internal/net.js', 'lib/internal/module.js',