From 641cfa2be3c5462c14e7d6d211e42d1efa79e0f3 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 29 Nov 2016 05:03:24 -0600 Subject: [PATCH] buffer: fix single-character string filling Fix the fast path for `buffer.fill()` with a single-character string. The fast path only works for strings that are equivalent to a single-byte buffer, but that condition was not checked properly for the `utf8` or `utf16le` encodings and is always true for the `latin1` encoding. This change fixes these problems. Fixes: https://github.com/nodejs/node/issues/9836 --- lib/buffer.js | 26 +++++++++++++++----------- test/parallel/test-buffer-fill.js | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index f4d16f41fc93dd..e97f366b4953e8 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -672,23 +672,27 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) { encoding = end; end = this.length; } - if (val.length === 1) { - var code = val.charCodeAt(0); - if (code < 256) - val = code; - } - if (val.length === 0) { - // Previously, if val === '', the Buffer would not fill, - // which is rather surprising. - val = 0; - } + if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string'); } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + var normalizedEncoding = internalUtil.normalizeEncoding(encoding); + if (normalizedEncoding === undefined) { throw new TypeError('Unknown encoding: ' + encoding); } + if (val.length === 0) { + // Previously, if val === '', the Buffer would not fill, + // which is rather surprising. + val = 0; + } else if (val.length === 1) { + var code = val.charCodeAt(0); + if ((normalizedEncoding === 'utf8' && code < 128) || + normalizedEncoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code; + } + } } else if (typeof val === 'number') { val = val & 255; } diff --git a/test/parallel/test-buffer-fill.js b/test/parallel/test-buffer-fill.js index c61ad59d7e9cfe..f613d1a31a9f55 100644 --- a/test/parallel/test-buffer-fill.js +++ b/test/parallel/test-buffer-fill.js @@ -390,3 +390,23 @@ assert.throws(() => { }); buf.fill(''); }); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), + 'aaaaaaaa'); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), + 'aaaaaaaaaaaaaaaa'); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), + 'aaaaaaaaaaaaaaaa'); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), + 'ЉЉЉЉЉЉЉЉ'); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), + '\t'.repeat(16)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), + 'ЉЉЉЉЉЉЉЉ');