From 25f2a24cdfe93897ba347e75506160c2acb0eb84 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Wed, 25 Jun 2014 13:13:55 -0400 Subject: [PATCH 1/2] Fix Issue #230: Error: Uncaught TypeError: undefined is not a function on .copy() --- src/filesystem/implementation.js | 39 ++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 5393e07..8010a68 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -56,6 +56,27 @@ function standard_check_result_cb(callback) { }; } +/** + * Coerce array-like data to Buffer so we can .copy(), etc. + * Allow null, a Buffer, or an object that can be dealt with + * by the Buffer constructor (e.g., Typed Array, Array, ...) + */ +function ensureBuffer(maybeBuffer) { + if(!maybeBuffer) { + return null; + } + + if(Buffer.isBuffer(maybeBuffer)) { + return maybeBuffer; + } + + try { + return new Buffer(maybeBuffer); + } catch(e) { + return null; + } +} + /** * Update node times. Only passed times are modified (undefined times are ignored) * and filesystem flags are examined in order to override update logic. @@ -753,7 +774,10 @@ function write_data(context, ofd, buffer, offset, length, position, callback) { if(error) { callback(error); } else { - fileData = result; + fileData = ensureBuffer(result); + if(!fileData) { + return callback(new Errors.EIO('Expected Buffer')); + } var _position = (!(undefined === position || null === position)) ? position : ofd.position; var newSize = Math.max(fileData.length, _position + length); var newData = new Buffer(newSize); @@ -793,7 +817,10 @@ function read_data(context, ofd, buffer, offset, length, position, callback) { if(error) { callback(error); } else { - fileData = result; + fileData = ensureBuffer(result); + if(!fileData) { + return callback(new Errors.EIO('Expected Buffer')); + } var _position = (!(undefined === position || null === position)) ? position : ofd.position; length = (_position + length > buffer.length) ? length - _position : length; fileData.copy(buffer, offset, _position, _position + length); @@ -1180,6 +1207,10 @@ function truncate_file(context, path, length, callback) { if (error) { callback(error); } else { + fileData = ensureBuffer(fileData); + if(!fileData) { + return callback(new Errors.EIO('Expected Buffer')); + } var data = new Buffer(length); data.fill(0); if(fileData) { @@ -1234,6 +1265,10 @@ function ftruncate_file(context, ofd, length, callback) { callback(error); } else { var data; + fileData = ensureBuffer(fileData); + if(!fileData) { + return callback(new Errors.EIO('Expected Buffer')); + } if(fileData) { data = fileData.slice(0, length); } else { From 76526caa3568fe94126a30b4c48b490169c24ee1 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Wed, 25 Jun 2014 13:51:07 -0400 Subject: [PATCH 2/2] Add a clarifying comment about not coercing buffers passed to read operations. --- src/filesystem/implementation.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 8010a68..4744428 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -60,6 +60,12 @@ function standard_check_result_cb(callback) { * Coerce array-like data to Buffer so we can .copy(), etc. * Allow null, a Buffer, or an object that can be dealt with * by the Buffer constructor (e.g., Typed Array, Array, ...) + * + * WARNING: be very careful not to call this on parameters of + * API methods that pass storage (like read). You don't want to + * overwrite a buffer that a caller is holding a reference to, + * and expects to be filled via the read. If the caller passes + * in a non-Buffer, we should throw instead of coerce. */ function ensureBuffer(maybeBuffer) { if(!maybeBuffer) {