From c5a18e748d8e78417f6e639baab4085fc446cdc6 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Fri, 22 Jul 2016 16:37:54 -0700 Subject: [PATCH] Revert "fs: validate args of truncate functions in js" This reverts commit c86c1eeab56df8a627d3d8da27008221ee295d33. original commit message: This patch 1. moves the basic validation of arguments to `truncate` family of functions to the JavaScript layer from the C++ layer. 2. makes sure that the File Descriptors are validated strictly. PR-URL: #2498 Reviewed-By: Trevor Norris PR-URL: https://github.com/nodejs/node/pull/7950 Reviewed-By: Julien Gilli Reviewed-By: Rod Vagg Reviewed-By: Minwoo Jung Reviewed-By: James M Snell --- lib/fs.js | 107 +++++++++------------------ src/node_file.cc | 65 +++++++++++----- test/parallel/test-fs-truncate-fd.js | 76 ++++--------------- test/parallel/test-fs-truncate.js | 94 ----------------------- test/parallel/test-fs-utimes.js | 68 ++++------------- test/parallel/test-fs-write-no-fd.js | 9 +-- 6 files changed, 118 insertions(+), 301 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index e48b79e4403866..558e9ffa19f7ee 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -81,16 +81,6 @@ function throwOptionsError(options) { 'but got ' + typeof options + ' instead'); } -function isFD(fd) { - return Number.isInteger(fd) && fd >= 0 && fd <= 0xFFFFFFFF; -} - -function sanitizeFD(fd) { - if (!isFD(fd)) - throw new TypeError('file descriptor must be a unsigned 32-bit integer'); - return fd; -} - // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. @@ -122,6 +112,10 @@ function nullCheck(path, callback) { return true; } +function isFd(path) { + return (path >>> 0) === path; +} + // Static method to set the stats properties on a Stats object. fs.Stats = function( dev, @@ -263,7 +257,7 @@ fs.readFile = function(path, options, callback) { return; var context = new ReadFileContext(callback, encoding); - context.isUserFd = isFD(path); // file descriptor ownership + context.isUserFd = isFd(path); // file descriptor ownership var req = new FSReqWrap(); req.context = context; req.oncomplete = readFileAfterOpen; @@ -479,7 +473,7 @@ fs.readFileSync = function(path, options) { assertEncoding(encoding); var flag = options.flag || 'r'; - var isUserFd = isFD(path); // file descriptor ownership + var isUserFd = isFd(path); // file descriptor ownership var fd = isUserFd ? path : fs.openSync(path, flag, 0o666); var st = tryStatSync(fd, isUserFd); @@ -576,12 +570,12 @@ Object.defineProperty(exports, '_stringToFlags', { fs.close = function(fd, callback) { var req = new FSReqWrap(); - req.oncomplete = makeCallback(callback); - binding.close(sanitizeFD(fd), req); + req.oncomplete = makeCallback(arguments[arguments.length - 1]); + binding.close(fd, req); }; fs.closeSync = function(fd) { - return binding.close(sanitizeFD(fd)); + return binding.close(fd); }; function modeNum(m, def) { @@ -618,7 +612,6 @@ fs.openSync = function(path, flags, mode) { var readWarned = false; fs.read = function(fd, buffer, offset, length, position, callback) { callback = makeCallback(arguments[arguments.length - 1]); - fd = sanitizeFD(fd); if (!(buffer instanceof Buffer)) { // legacy string interface (fd, length, position, encoding, callback) readWarned = printDeprecation('fs.read\'s legacy String interface ' + @@ -679,7 +672,6 @@ fs.readSync = function(fd, buffer, offset, length, position) { var legacy = false; var encoding; - fd = sanitizeFD(fd); if (!(buffer instanceof Buffer)) { // legacy string interface (fd, length, position, encoding, callback) readSyncWarned = printDeprecation('fs.readSync\'s legacy String interface' + @@ -721,7 +713,6 @@ fs.readSync = function(fd, buffer, offset, length, position) { // fs.write(fd, string[, position[, encoding]], callback); fs.write = function(fd, buffer, offset, length, position, callback) { callback = makeCallback(arguments[arguments.length - 1]); - fd = sanitizeFD(fd); function wrapper(err, written) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, written || 0, buffer); @@ -757,7 +748,6 @@ fs.write = function(fd, buffer, offset, length, position, callback) { // OR // fs.writeSync(fd, string[, position[, encoding]]); fs.writeSync = function(fd, buffer, offset, length, position) { - fd = sanitizeFD(fd); if (buffer instanceof Buffer) { if (position === undefined) position = null; @@ -789,18 +779,14 @@ fs.renameSync = function(oldPath, newPath) { }; fs.truncate = function(path, len, callback) { - callback = makeCallback(arguments[arguments.length - 1]); - - if (isFD(path)) + if (typeof path === 'number') { return fs.ftruncate(path, len, callback); + } - if (typeof path !== 'string') - throw new TypeError('path must be a string'); + callback = makeCallback(arguments[arguments.length - 1]); - if (typeof len === 'function' || len == undefined) { + if (typeof len === 'function' || len === undefined) { len = 0; - } else if (!Number.isInteger(len) || len < 0) { - throw new TypeError('length must be a positive integer'); } fs.open(path, 'r+', function(er, fd) { @@ -816,18 +802,13 @@ fs.truncate = function(path, len, callback) { }; fs.truncateSync = function(path, len) { - if (isFD(path)) + if (typeof path === 'number') { + // legacy return fs.ftruncateSync(path, len); - - if (typeof path !== 'string') - throw new TypeError('path must be a string'); - - if (len === undefined || len === null) { + } + if (len === undefined) { len = 0; - } else if (!Number.isInteger(len) || len < 0) { - throw new TypeError('length must be a positive integer'); } - // allow error to be thrown, but still close fd. var fd = fs.openSync(path, 'r+'); var ret; @@ -841,30 +822,18 @@ fs.truncateSync = function(path, len) { }; fs.ftruncate = function(fd, len, callback) { - callback = makeCallback(arguments[arguments.length - 1]); - - fd = sanitizeFD(fd); - - if (typeof len === 'function' || len == undefined) { + if (typeof len === 'function' || len === undefined) { len = 0; - } else if (!Number.isInteger(len) || len < 0) { - throw new TypeError('length must be a positive integer'); } - var req = new FSReqWrap(); - req.oncomplete = callback; + req.oncomplete = makeCallback(arguments[arguments.length - 1]); binding.ftruncate(fd, len, req); }; fs.ftruncateSync = function(fd, len) { - fd = sanitizeFD(fd); - - if (len === undefined || len === null) { + if (len === undefined) { len = 0; - } else if (!Number.isInteger(len) || len < 0) { - throw new TypeError('length must be a positive integer'); } - return binding.ftruncate(fd, len); }; @@ -884,21 +853,21 @@ fs.rmdirSync = function(path) { fs.fdatasync = function(fd, callback) { var req = new FSReqWrap(); req.oncomplete = makeCallback(callback); - binding.fdatasync(sanitizeFD(fd), req); + binding.fdatasync(fd, req); }; fs.fdatasyncSync = function(fd) { - return binding.fdatasync(sanitizeFD(fd)); + return binding.fdatasync(fd); }; fs.fsync = function(fd, callback) { var req = new FSReqWrap(); - req.oncomplete = makeCallback(callback); - binding.fsync(sanitizeFD(fd), req); + req.oncomplete = makeCallback(arguments[arguments.length - 1]); + binding.fsync(fd, req); }; fs.fsyncSync = function(fd) { - return binding.fsync(sanitizeFD(fd)); + return binding.fsync(fd); }; fs.mkdir = function(path, mode, callback) { @@ -946,8 +915,8 @@ fs.readdirSync = function(path, options) { fs.fstat = function(fd, callback) { var req = new FSReqWrap(); - req.oncomplete = makeCallback(callback); - binding.fstat(sanitizeFD(fd), req); + req.oncomplete = makeCallback(arguments[arguments.length - 1]); + binding.fstat(fd, req); }; fs.lstat = function(path, callback) { @@ -967,7 +936,7 @@ fs.stat = function(path, callback) { }; fs.fstatSync = function(fd) { - return binding.fstat(sanitizeFD(fd)); + return binding.fstat(fd); }; fs.lstatSync = function(path) { @@ -1084,11 +1053,11 @@ fs.unlinkSync = function(path) { fs.fchmod = function(fd, mode, callback) { var req = new FSReqWrap(); req.oncomplete = makeCallback(arguments[arguments.length - 1]); - binding.fchmod(sanitizeFD(fd), modeNum(mode), req); + binding.fchmod(fd, modeNum(mode), req); }; fs.fchmodSync = function(fd, mode) { - return binding.fchmod(sanitizeFD(fd), modeNum(mode)); + return binding.fchmod(fd, modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { @@ -1167,11 +1136,11 @@ if (constants.hasOwnProperty('O_SYMLINK')) { fs.fchown = function(fd, uid, gid, callback) { var req = new FSReqWrap(); req.oncomplete = makeCallback(arguments[arguments.length - 1]); - binding.fchown(sanitizeFD(fd), uid, gid, req); + binding.fchown(fd, uid, gid, req); }; fs.fchownSync = function(fd, uid, gid) { - return binding.fchown(sanitizeFD(fd), uid, gid); + return binding.fchown(fd, uid, gid); }; fs.chown = function(path, uid, gid, callback) { @@ -1228,7 +1197,6 @@ fs.utimesSync = function(path, atime, mtime) { fs.futimes = function(fd, atime, mtime, callback) { callback = makeCallback(arguments[arguments.length - 1]); - fd = sanitizeFD(fd); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); var req = new FSReqWrap(); @@ -1237,7 +1205,6 @@ fs.futimes = function(fd, atime, mtime, callback) { }; fs.futimesSync = function(fd, atime, mtime) { - fd = sanitizeFD(fd); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime); @@ -1290,7 +1257,7 @@ fs.writeFile = function(path, data, options, callback) { var flag = options.flag || 'w'; - if (isFD(path)) { + if (isFd(path)) { writeFd(path, true); return; } @@ -1324,7 +1291,7 @@ fs.writeFileSync = function(path, data, options) { assertEncoding(options.encoding); var flag = options.flag || 'w'; - var isUserFd = isFD(path); // file descriptor ownership + var isUserFd = isFd(path); // file descriptor ownership var fd = isUserFd ? path : fs.openSync(path, flag, options.mode); if (!(data instanceof Buffer)) { @@ -1362,7 +1329,7 @@ fs.appendFile = function(path, data, options, callback) { options = util._extend({ flag: 'a' }, options); // force append behavior when using a supplied file descriptor - if (isFD(path)) + if (isFd(path)) options.flag = 'a'; fs.writeFile(path, data, options, callback); @@ -1381,7 +1348,7 @@ fs.appendFileSync = function(path, data, options) { options = util._extend({ flag: 'a' }, options); // force append behavior when using a supplied file descriptor - if (isFD(path)) + if (isFd(path)) options.flag = 'a'; fs.writeFileSync(path, data, options); @@ -1965,7 +1932,7 @@ function SyncWriteStream(fd, options) { options = options || {}; - this.fd = sanitizeFD(fd); + this.fd = fd; this.writable = true; this.readable = false; this.autoClose = options.autoClose === undefined ? true : options.autoClose; diff --git a/src/node_file.cc b/src/node_file.cc index a51bcabba3746f..1fdef68ca6129b 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -49,11 +49,6 @@ using v8::Value; #define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1) -static int SanitizeFD(Local fd) { - CHECK(fd->IsUint32() && "file descriptor must be a unsigned 32-bit integer"); - return fd->Uint32Value(); -} - class FSReqWrap: public ReqWrap { public: enum Ownership { COPY, MOVE }; @@ -411,8 +406,10 @@ static void Close(const FunctionCallbackInfo& args) { if (args.Length() < 1) return TYPE_ERROR("fd is required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { ASYNC_CALL(close, args[1], UTF8, fd) @@ -644,8 +641,10 @@ static void FStat(const FunctionCallbackInfo& args) { if (args.Length() < 1) return TYPE_ERROR("fd is required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { ASYNC_CALL(fstat, args[1], UTF8, fd) @@ -773,10 +772,21 @@ static void FTruncate(const FunctionCallbackInfo& args) { if (args.Length() < 2) return TYPE_ERROR("fd and length are required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); + // FIXME(bnoordhuis) It's questionable to reject non-ints here but still + // allow implicit coercion from null or undefined to zero. Probably best + // handled in lib/fs.js. Local len_v(args[1]); + if (!len_v->IsUndefined() && + !len_v->IsNull() && + !IsInt64(len_v->NumberValue())) { + return env->ThrowTypeError("Not an integer"); + } + const int64_t len = len_v->IntegerValue(); if (args[2]->IsObject()) { @@ -791,8 +801,10 @@ static void Fdatasync(const FunctionCallbackInfo& args) { if (args.Length() < 1) return TYPE_ERROR("fd is required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { ASYNC_CALL(fdatasync, args[1], UTF8, fd) @@ -806,8 +818,10 @@ static void Fsync(const FunctionCallbackInfo& args) { if (args.Length() < 1) return TYPE_ERROR("fd is required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { ASYNC_CALL(fsync, args[1], UTF8, fd) @@ -1010,8 +1024,12 @@ static void Open(const FunctionCallbackInfo& args) { static void WriteBuffer(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + if (!args[0]->IsInt32()) + return env->ThrowTypeError("First argument must be file descriptor"); + CHECK(Buffer::HasInstance(args[1])); - int fd = SanitizeFD(args[0]); + + int fd = args[0]->Int32Value(); Local obj = args[1].As(); const char* buf = Buffer::Data(obj); size_t buffer_length = Buffer::Length(obj); @@ -1053,8 +1071,10 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { static void WriteBuffers(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + CHECK(args[0]->IsInt32()); CHECK(args[1]->IsArray()); - int fd = SanitizeFD(args[0]); + + int fd = args[0]->Int32Value(); Local chunks = args[1].As(); int64_t pos = GET_OFFSET(args[2]); Local req = args[3]; @@ -1091,9 +1111,12 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { static void WriteString(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + if (!args[0]->IsInt32()) + return env->ThrowTypeError("First argument must be file descriptor"); + Local req; Local string = args[1]; - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); char* buf = nullptr; int64_t pos; size_t len; @@ -1168,10 +1191,12 @@ static void Read(const FunctionCallbackInfo& args) { if (args.Length() < 2) return TYPE_ERROR("fd and buffer are required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); if (!Buffer::HasInstance(args[1])) return TYPE_ERROR("Second argument needs to be a buffer"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); Local req; @@ -1242,10 +1267,12 @@ static void FChmod(const FunctionCallbackInfo& args) { if (args.Length() < 2) return TYPE_ERROR("fd and mode are required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be a file descriptor"); if (!args[1]->IsInt32()) return TYPE_ERROR("mode must be an integer"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsObject()) { @@ -1301,12 +1328,14 @@ static void FChown(const FunctionCallbackInfo& args) { return TYPE_ERROR("uid required"); if (len < 3) return TYPE_ERROR("gid required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be an int"); if (!args[1]->IsUint32()) return TYPE_ERROR("uid must be an unsigned int"); if (!args[2]->IsUint32()) return TYPE_ERROR("gid must be an unsigned int"); - int fd = SanitizeFD(args[0]); + int fd = args[0]->Int32Value(); uv_uid_t uid = static_cast(args[1]->Uint32Value()); uv_gid_t gid = static_cast(args[2]->Uint32Value()); @@ -1356,12 +1385,14 @@ static void FUTimes(const FunctionCallbackInfo& args) { return TYPE_ERROR("atime required"); if (len < 3) return TYPE_ERROR("mtime required"); + if (!args[0]->IsInt32()) + return TYPE_ERROR("fd must be an int"); if (!args[1]->IsNumber()) return TYPE_ERROR("atime must be a number"); if (!args[2]->IsNumber()) return TYPE_ERROR("mtime must be a number"); - const int fd = SanitizeFD(args[0]); + const int fd = args[0]->Int32Value(); const double atime = static_cast(args[1]->NumberValue()); const double mtime = static_cast(args[2]->NumberValue()); diff --git a/test/parallel/test-fs-truncate-fd.js b/test/parallel/test-fs-truncate-fd.js index 29b03284a2214f..2514b80f09892a 100644 --- a/test/parallel/test-fs-truncate-fd.js +++ b/test/parallel/test-fs-truncate-fd.js @@ -1,71 +1,21 @@ 'use strict'; -const common = require('../common'); -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); - +var common = require('../common'); +var assert = require('assert'); +var path = require('path'); +var fs = require('fs'); +var tmp = common.tmpDir; common.refreshTmpDir(); -const fds = []; +var filename = path.resolve(tmp, 'truncate-file.txt'); -const filename = path.resolve(common.tmpDir, 'truncate-file.txt'); fs.writeFileSync(filename, 'hello world', 'utf8'); -const fd = fs.openSync(filename, 'r+'); -fds.push(fd); +var fd = fs.openSync(filename, 'r+'); fs.truncate(fd, 5, common.mustCall(function(err) { - assert.ifError(err); + assert.ok(!err); assert.equal(fs.readFileSync(filename, 'utf8'), 'hello'); })); -{ - // test partial truncation of a file - const fileName = path.resolve(common.tmpDir, 'truncate-file-1.txt'); - console.log(fileName); - fs.writeFileSync(fileName, 'hello world', 'utf8'); - const fd = fs.openSync(fileName, 'r+'); - fds.push(fd); - - fs.truncate(fd, 5, common.mustCall(function(err) { - assert.ifError(err); - assert.strictEqual(fs.readFileSync(fileName, 'utf8'), 'hello'); - })); -} - -{ - // make sure numbers as strings are not treated as fds with sync version - const fileName = path.resolve(common.tmpDir, 'truncate-file-2.txt'); - console.log(fileName); - fs.writeFileSync(fileName, 'One'); - const fd = fs.openSync(fileName, 'r'); - fds.push(fd); - - const fdFileName = path.resolve(common.tmpDir, '' + fd); - fs.writeFileSync(fdFileName, 'Two'); - assert.strictEqual(fs.readFileSync(fileName).toString(), 'One'); - assert.strictEqual(fs.readFileSync(fdFileName).toString(), 'Two'); - - fs.truncateSync(fdFileName); - assert.strictEqual(fs.readFileSync(fileName).toString(), 'One'); - assert.strictEqual(fs.readFileSync(fdFileName).toString(), ''); -} - -{ - // make sure numbers as strings are not treated as fds with async version - const fileName = path.resolve(common.tmpDir, 'truncate-file-3.txt'); - console.log(fileName); - fs.writeFileSync(fileName, 'One'); - const fd = fs.openSync(fileName, 'r'); - fds.push(fd); - - const fdFileName = path.resolve(common.tmpDir, '' + fd); - fs.writeFileSync(fdFileName, 'Two'); - assert.strictEqual(fs.readFileSync(fileName).toString(), 'One'); - assert.strictEqual(fs.readFileSync(fdFileName).toString(), 'Two'); - - fs.truncate(fdFileName, common.mustCall(function(err) { - assert.ifError(err); - assert.strictEqual(fs.readFileSync(fileName).toString(), 'One'); - assert.strictEqual(fs.readFileSync(fdFileName).toString(), ''); - })); -} - -process.on('exit', () => fds.forEach((fd) => fs.closeSync(fd))); +process.on('exit', function() { + fs.closeSync(fd); + fs.unlinkSync(filename); + console.log('ok'); +}); diff --git a/test/parallel/test-fs-truncate.js b/test/parallel/test-fs-truncate.js index be986937b31f2f..ab0148a2461f70 100644 --- a/test/parallel/test-fs-truncate.js +++ b/test/parallel/test-fs-truncate.js @@ -24,55 +24,6 @@ fs.truncateSync(filename); stat = fs.statSync(filename); assert.equal(stat.size, 0); -// path must be a string -assert.throws(function() { - fs.truncateSync({}); -}, /path must be a string/); - -assert.throws(function() { - fs.truncateSync([]); -}, /path must be a string/); - -// Even invalid file descriptors are not allowed -assert.throws(function() { - fs.truncateSync(-1); -}, /path must be a string/); - -assert.throws(function() { - fs.truncateSync(NaN); -}, /path must be a string/); - -assert.throws(function() { - fs.truncateSync(Infinity); -}, /path must be a string/); - -// Invalid lengths will also fail -assert.throws(function() { - fs.truncateSync('', ''); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.truncateSync('', -1); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.truncateSync('', NaN); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.truncateSync('', Infinity); -}, /length must be a positive integer/); - -// null is a special case which will also be treated as zero length -fs.writeFileSync(filename, data); - -stat = fs.statSync(filename); -assert.equal(stat.size, 1024 * 16); - -fs.truncateSync(filename, null); -stat = fs.statSync(filename); -assert.equal(stat.size, 0); - // ftruncateSync fs.writeFileSync(filename, data); var fd = fs.openSync(filename, 'r+'); @@ -90,51 +41,6 @@ assert.equal(stat.size, 0); fs.closeSync(fd); -// file descriptor must be a unsigned 32-bit integer -assert.throws(function() { - fs.ftruncateSync({}); -}, /file descriptor must be a unsigned 32-bit integer/); - -// Even invalid file descriptors are not allowed -assert.throws(function() { - fs.ftruncateSync(-1); -}, /file descriptor must be a unsigned 32-bit integer/); - -assert.throws(function() { - fs.ftruncateSync(NaN); -}, /file descriptor must be a unsigned 32-bit integer/); - -assert.throws(function() { - fs.ftruncateSync(Infinity); -}, /file descriptor must be a unsigned 32-bit integer/); - -// Invalid lengths will also fail -assert.throws(function() { - fs.ftruncateSync(1, ''); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.ftruncateSync(1, -1); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.ftruncateSync(1, NaN); -}, /length must be a positive integer/); - -assert.throws(function() { - fs.ftruncateSync(1, Infinity); -}, /length must be a positive integer/); - -// null is a special case which will also be treated as zero length -fs.writeFileSync(filename, data); -fd = fs.openSync(filename, 'r+'); - -fs.ftruncateSync(fd, null); -stat = fs.statSync(filename); -assert.equal(stat.size, 0); - -fs.closeSync(fd); - // async tests testTruncate(common.mustCall(function(er) { if (er) throw er; diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index eecc56ee4d4e72..f245a7962da0f4 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -76,6 +76,15 @@ function runTest(atime, mtime, callback) { } expect_errno('utimesSync', 'foobarbaz', err, 'ENOENT'); tests_run++; + + err = undefined; + try { + fs.futimesSync(-1, atime, mtime); + } catch (ex) { + err = ex; + } + expect_errno('futimesSync', -1, err, 'EBADF'); + tests_run++; } // @@ -96,8 +105,13 @@ function runTest(atime, mtime, callback) { fs.futimes(fd, atime, mtime, function(err) { expect_ok('futimes', fd, err, atime, mtime); - syncTests(); - callback(); + + fs.futimes(-1, atime, mtime, function(err) { + expect_errno('futimes', -1, err, 'EBADF'); + syncTests(); + callback(); + }); + tests_run++; }); tests_run++; }); @@ -123,56 +137,6 @@ runTest(new Date('1982-09-10 13:37'), new Date('1982-09-10 13:37'), function() { }); }); -// validate if the file descriptors are in the valid range -assert.throws(() => fs.futimes(-1, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(-1), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes('-1', () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync('-1'), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(0xFFFFFFFF + 1, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(0xFFFFFFFF + 1), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes('0x100000000', () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync('0x100000000'), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -// invalid file descriptors also should throw -assert.throws(() => fs.futimes(null, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(null), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(undefined, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(undefined), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(NaN, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(NaN), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes({}, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync({}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes([], () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync([]), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(() => true, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(() => true), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(() => /RegEx/, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(() => /RegEx/), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimes(() => 3.14, () => {}), - /TypeError: file descriptor must be a unsigned 32-bit integer/); -assert.throws(() => fs.futimesSync(() => 3.14), - /TypeError: file descriptor must be a unsigned 32-bit integer/); process.on('exit', function() { console.log('Tests run / ok:', tests_run, '/', tests_ok); diff --git a/test/parallel/test-fs-write-no-fd.js b/test/parallel/test-fs-write-no-fd.js index eb59e46a8332e1..0aaec4b733356e 100644 --- a/test/parallel/test-fs-write-no-fd.js +++ b/test/parallel/test-fs-write-no-fd.js @@ -1,13 +1,12 @@ 'use strict'; - require('../common'); const fs = require('fs'); const assert = require('assert'); assert.throws(function() { - fs.write(null, Buffer.allocUnsafe(1), 0, 1, () => {}); -}, /TypeError: file descriptor must be a unsigned 32-bit integer/); + fs.write(null, Buffer.allocUnsafe(1), 0, 1); +}, /TypeError/); assert.throws(function() { - fs.write(undefined, '1', 0, 1, () => {}); -}, /TypeError: file descriptor must be a unsigned 32-bit integer/); + fs.write(null, '1', 0, 1); +}, /TypeError/);