diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2019-12-19 21:00:45 +0300 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2020-02-05 15:39:53 +0300 |
commit | fb6df3bfac8ca38a7012eabf0563d7a799ce1acc (patch) | |
tree | 20e1f8730686d2c50c130b89f0f95a2a60822aa0 /lib/internal/fs | |
parent | 2d8febceef35bdd52624028bdee2e0d58830ae7f (diff) |
fs: validate the input data to be of expected types
The input was not validated so far and that caused unwanted side
effects. E.g., `undefined` became the string `'undefined'`. It was
expected to fail or to end up as empty string.
Now all input is validated to be either some type of array buffer
view or a string. That way it's always clear what the user intents.
PR-URL: https://github.com/nodejs/node/pull/31030
Fixes: https://github.com/nodejs/node/issues/31025
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Diffstat (limited to 'lib/internal/fs')
-rw-r--r-- | lib/internal/fs/promises.js | 22 | ||||
-rw-r--r-- | lib/internal/fs/utils.js | 11 |
2 files changed, 23 insertions, 10 deletions
diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index e0c4e2ca4a4..6517a5ef4be 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -26,7 +26,7 @@ const { ERR_INVALID_ARG_VALUE, ERR_METHOD_NOT_IMPLEMENTED } = require('internal/errors').codes; -const { isUint8Array } = require('internal/util/types'); +const { isArrayBufferView } = require('internal/util/types'); const { rimrafPromises } = require('internal/fs/rimraf'); const { copyObject, @@ -44,6 +44,7 @@ const { validateOffsetLengthRead, validateOffsetLengthWrite, validateRmdirOptions, + validateStringAfterArrayBufferView, warnOnNonPortableTemplate } = require('internal/fs/utils'); const { opendir } = require('internal/fs/dir'); @@ -140,16 +141,18 @@ function validateFileHandle(handle) { } async function writeFileHandle(filehandle, data, options) { - let buffer = isUint8Array(data) ? - data : Buffer.from('' + data, options.encoding || 'utf8'); - let remaining = buffer.length; + if (!isArrayBufferView(data)) { + validateStringAfterArrayBufferView(data, 'data'); + data = Buffer.from(data, options.encoding || 'utf8'); + } + let remaining = data.length; if (remaining === 0) return; do { const { bytesWritten } = - await write(filehandle, buffer, 0, - MathMin(16384, buffer.length)); + await write(filehandle, data, 0, + MathMin(16384, data.length)); remaining -= bytesWritten; - buffer = buffer.slice(bytesWritten); + data = data.slice(bytesWritten); } while (remaining > 0); } @@ -260,7 +263,7 @@ async function write(handle, buffer, offset, length, position) { if (buffer.length === 0) return { bytesWritten: 0, buffer }; - if (isUint8Array(buffer)) { + if (isArrayBufferView(buffer)) { if (offset == null) { offset = 0; } else { @@ -277,8 +280,7 @@ async function write(handle, buffer, offset, length, position) { return { bytesWritten, buffer }; } - if (typeof buffer !== 'string') - buffer += ''; + validateStringAfterArrayBufferView(buffer, 'buffer'); const bytesWritten = (await binding.writeString(handle.fd, buffer, offset, length, kUsePromises)) || 0; return { bytesWritten, buffer }; diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 18d8e07d78e..763a940f6e9 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -651,6 +651,16 @@ const getValidMode = hideStackFrames((mode, type) => { 'mode', `an integer >= ${min} && <= ${max}`, mode); }); +const validateStringAfterArrayBufferView = hideStackFrames((buffer, name) => { + if (typeof buffer !== 'string') { + throw new ERR_INVALID_ARG_TYPE( + name, + ['string', 'Buffer', 'TypedArray', 'DataView'], + buffer + ); + } +}); + module.exports = { assertEncoding, BigIntStats, // for testing @@ -675,5 +685,6 @@ module.exports = { validateOffsetLengthWrite, validatePath, validateRmdirOptions, + validateStringAfterArrayBufferView, warnOnNonPortableTemplate }; |