1// Flags: --expose-internals 2'use strict'; 3const common = require('../common'); 4const assert = require('assert'); 5const { codes: { ERR_OUT_OF_RANGE } } = require('internal/errors'); 6const { internalBinding } = require('internal/test/binding'); 7const SIZE = 28; 8 9const buf1 = Buffer.allocUnsafe(SIZE); 10const buf2 = Buffer.allocUnsafe(SIZE); 11 12// Default encoding 13testBufs('abc'); 14testBufs('\u0222aa'); 15testBufs('a\u0234b\u0235c\u0236'); 16testBufs('abc', 4); 17testBufs('abc', 5); 18testBufs('abc', SIZE); 19testBufs('\u0222aa', 2); 20testBufs('\u0222aa', 8); 21testBufs('a\u0234b\u0235c\u0236', 4); 22testBufs('a\u0234b\u0235c\u0236', 12); 23testBufs('abc', 4, 1); 24testBufs('abc', 5, 1); 25testBufs('\u0222aa', 8, 1); 26testBufs('a\u0234b\u0235c\u0236', 4, 1); 27testBufs('a\u0234b\u0235c\u0236', 12, 1); 28 29// UTF8 30testBufs('abc', 'utf8'); 31testBufs('\u0222aa', 'utf8'); 32testBufs('a\u0234b\u0235c\u0236', 'utf8'); 33testBufs('abc', 4, 'utf8'); 34testBufs('abc', 5, 'utf8'); 35testBufs('abc', SIZE, 'utf8'); 36testBufs('\u0222aa', 2, 'utf8'); 37testBufs('\u0222aa', 8, 'utf8'); 38testBufs('a\u0234b\u0235c\u0236', 4, 'utf8'); 39testBufs('a\u0234b\u0235c\u0236', 12, 'utf8'); 40testBufs('abc', 4, 1, 'utf8'); 41testBufs('abc', 5, 1, 'utf8'); 42testBufs('\u0222aa', 8, 1, 'utf8'); 43testBufs('a\u0234b\u0235c\u0236', 4, 1, 'utf8'); 44testBufs('a\u0234b\u0235c\u0236', 12, 1, 'utf8'); 45assert.strictEqual(Buffer.allocUnsafe(1).fill(0).fill('\u0222')[0], 0xc8); 46 47// BINARY 48testBufs('abc', 'binary'); 49testBufs('\u0222aa', 'binary'); 50testBufs('a\u0234b\u0235c\u0236', 'binary'); 51testBufs('abc', 4, 'binary'); 52testBufs('abc', 5, 'binary'); 53testBufs('abc', SIZE, 'binary'); 54testBufs('\u0222aa', 2, 'binary'); 55testBufs('\u0222aa', 8, 'binary'); 56testBufs('a\u0234b\u0235c\u0236', 4, 'binary'); 57testBufs('a\u0234b\u0235c\u0236', 12, 'binary'); 58testBufs('abc', 4, 1, 'binary'); 59testBufs('abc', 5, 1, 'binary'); 60testBufs('\u0222aa', 8, 1, 'binary'); 61testBufs('a\u0234b\u0235c\u0236', 4, 1, 'binary'); 62testBufs('a\u0234b\u0235c\u0236', 12, 1, 'binary'); 63 64// LATIN1 65testBufs('abc', 'latin1'); 66testBufs('\u0222aa', 'latin1'); 67testBufs('a\u0234b\u0235c\u0236', 'latin1'); 68testBufs('abc', 4, 'latin1'); 69testBufs('abc', 5, 'latin1'); 70testBufs('abc', SIZE, 'latin1'); 71testBufs('\u0222aa', 2, 'latin1'); 72testBufs('\u0222aa', 8, 'latin1'); 73testBufs('a\u0234b\u0235c\u0236', 4, 'latin1'); 74testBufs('a\u0234b\u0235c\u0236', 12, 'latin1'); 75testBufs('abc', 4, 1, 'latin1'); 76testBufs('abc', 5, 1, 'latin1'); 77testBufs('\u0222aa', 8, 1, 'latin1'); 78testBufs('a\u0234b\u0235c\u0236', 4, 1, 'latin1'); 79testBufs('a\u0234b\u0235c\u0236', 12, 1, 'latin1'); 80 81// UCS2 82testBufs('abc', 'ucs2'); 83testBufs('\u0222aa', 'ucs2'); 84testBufs('a\u0234b\u0235c\u0236', 'ucs2'); 85testBufs('abc', 4, 'ucs2'); 86testBufs('abc', SIZE, 'ucs2'); 87testBufs('\u0222aa', 2, 'ucs2'); 88testBufs('\u0222aa', 8, 'ucs2'); 89testBufs('a\u0234b\u0235c\u0236', 4, 'ucs2'); 90testBufs('a\u0234b\u0235c\u0236', 12, 'ucs2'); 91testBufs('abc', 4, 1, 'ucs2'); 92testBufs('abc', 5, 1, 'ucs2'); 93testBufs('\u0222aa', 8, 1, 'ucs2'); 94testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2'); 95testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2'); 96assert.strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], 0x22); 97 98// HEX 99testBufs('616263', 'hex'); 100testBufs('c8a26161', 'hex'); 101testBufs('61c8b462c8b563c8b6', 'hex'); 102testBufs('616263', 4, 'hex'); 103testBufs('616263', 5, 'hex'); 104testBufs('616263', SIZE, 'hex'); 105testBufs('c8a26161', 2, 'hex'); 106testBufs('c8a26161', 8, 'hex'); 107testBufs('61c8b462c8b563c8b6', 4, 'hex'); 108testBufs('61c8b462c8b563c8b6', 12, 'hex'); 109testBufs('616263', 4, 1, 'hex'); 110testBufs('616263', 5, 1, 'hex'); 111testBufs('c8a26161', 8, 1, 'hex'); 112testBufs('61c8b462c8b563c8b6', 4, 1, 'hex'); 113testBufs('61c8b462c8b563c8b6', 12, 1, 'hex'); 114 115assert.throws(() => { 116 const buf = Buffer.allocUnsafe(SIZE); 117 118 buf.fill('yKJh', 'hex'); 119}, { 120 code: 'ERR_INVALID_ARG_VALUE', 121 name: 'TypeError' 122}); 123 124assert.throws(() => { 125 const buf = Buffer.allocUnsafe(SIZE); 126 127 buf.fill('\u0222', 'hex'); 128}, { 129 code: 'ERR_INVALID_ARG_VALUE', 130 name: 'TypeError' 131}); 132 133// BASE64 134testBufs('YWJj', 'base64'); 135testBufs('yKJhYQ==', 'base64'); 136testBufs('Yci0Ysi1Y8i2', 'base64'); 137testBufs('YWJj', 4, 'base64'); 138testBufs('YWJj', SIZE, 'base64'); 139testBufs('yKJhYQ==', 2, 'base64'); 140testBufs('yKJhYQ==', 8, 'base64'); 141testBufs('Yci0Ysi1Y8i2', 4, 'base64'); 142testBufs('Yci0Ysi1Y8i2', 12, 'base64'); 143testBufs('YWJj', 4, 1, 'base64'); 144testBufs('YWJj', 5, 1, 'base64'); 145testBufs('yKJhYQ==', 8, 1, 'base64'); 146testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64'); 147testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64'); 148 149// BASE64URL 150testBufs('YWJj', 'base64url'); 151testBufs('yKJhYQ', 'base64url'); 152testBufs('Yci0Ysi1Y8i2', 'base64url'); 153testBufs('YWJj', 4, 'base64url'); 154testBufs('YWJj', SIZE, 'base64url'); 155testBufs('yKJhYQ', 2, 'base64url'); 156testBufs('yKJhYQ', 8, 'base64url'); 157testBufs('Yci0Ysi1Y8i2', 4, 'base64url'); 158testBufs('Yci0Ysi1Y8i2', 12, 'base64url'); 159testBufs('YWJj', 4, 1, 'base64url'); 160testBufs('YWJj', 5, 1, 'base64url'); 161testBufs('yKJhYQ', 8, 1, 'base64url'); 162testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64url'); 163testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64url'); 164 165// Buffer 166function deepStrictEqualValues(buf, arr) { 167 for (const [index, value] of buf.entries()) { 168 assert.deepStrictEqual(value, arr[index]); 169 } 170} 171 172const buf2Fill = Buffer.allocUnsafe(1).fill(2); 173deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); 174deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); 175deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); 176deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); 177const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill('0102', 'hex'); 178deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); 179deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); 180deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); 181deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); 182 183// Check exceptions 184[ 185 [0, -1], 186 [0, 0, buf1.length + 1], 187 ['', -1], 188 ['', 0, buf1.length + 1], 189 ['', 1, -1], 190].forEach((args) => { 191 assert.throws( 192 () => buf1.fill(...args), 193 { code: 'ERR_OUT_OF_RANGE' } 194 ); 195}); 196 197assert.throws( 198 () => buf1.fill('a', 0, buf1.length, 'node rocks!'), 199 { 200 code: 'ERR_UNKNOWN_ENCODING', 201 name: 'TypeError', 202 message: 'Unknown encoding: node rocks!' 203 } 204); 205 206[ 207 ['a', 0, 0, NaN], 208 ['a', 0, 0, false], 209].forEach((args) => { 210 assert.throws( 211 () => buf1.fill(...args), 212 { 213 code: 'ERR_INVALID_ARG_TYPE', 214 message: 'The "encoding" argument must be of type ' + 215 `string.${common.invalidArgTypeHelper(args[3])}` 216 } 217 ); 218}); 219 220assert.throws( 221 () => buf1.fill('a', 0, 0, 'foo'), 222 { 223 code: 'ERR_UNKNOWN_ENCODING', 224 name: 'TypeError', 225 message: 'Unknown encoding: foo' 226 } 227); 228 229function genBuffer(size, args) { 230 const b = Buffer.allocUnsafe(size); 231 return b.fill(0).fill.apply(b, args); 232} 233 234function bufReset() { 235 buf1.fill(0); 236 buf2.fill(0); 237} 238 239// This is mostly accurate. Except write() won't write partial bytes to the 240// string while fill() blindly copies bytes into memory. To account for that an 241// error will be thrown if not all the data can be written, and the SIZE has 242// been massaged to work with the input characters. 243function writeToFill(string, offset, end, encoding) { 244 if (typeof offset === 'string') { 245 encoding = offset; 246 offset = 0; 247 end = buf2.length; 248 } else if (typeof end === 'string') { 249 encoding = end; 250 end = buf2.length; 251 } else if (end === undefined) { 252 end = buf2.length; 253 } 254 255 // Should never be reached. 256 if (offset < 0 || end > buf2.length) 257 throw new ERR_OUT_OF_RANGE(); 258 259 if (end <= offset) 260 return buf2; 261 262 offset >>>= 0; 263 end >>>= 0; 264 assert(offset <= buf2.length); 265 266 // Convert "end" to "length" (which write understands). 267 const length = end - offset < 0 ? 0 : end - offset; 268 269 let wasZero = false; 270 do { 271 const written = buf2.write(string, offset, length, encoding); 272 offset += written; 273 // Safety check in case write falls into infinite loop. 274 if (written === 0) { 275 if (wasZero) 276 throw new Error('Could not write all data to Buffer'); 277 else 278 wasZero = true; 279 } 280 } while (offset < buf2.length); 281 282 return buf2; 283} 284 285function testBufs(string, offset, length, encoding) { 286 bufReset(); 287 buf1.fill.apply(buf1, arguments); 288 // Swap bytes on BE archs for ucs2 encoding. 289 assert.deepStrictEqual(buf1.fill.apply(buf1, arguments), 290 writeToFill.apply(null, arguments)); 291} 292 293// Make sure these throw. 294assert.throws( 295 () => Buffer.allocUnsafe(8).fill('a', -1), 296 { code: 'ERR_OUT_OF_RANGE' }); 297assert.throws( 298 () => Buffer.allocUnsafe(8).fill('a', 0, 9), 299 { code: 'ERR_OUT_OF_RANGE' }); 300 301// Make sure this doesn't hang indefinitely. 302Buffer.allocUnsafe(8).fill(''); 303Buffer.alloc(8, ''); 304 305{ 306 const buf = Buffer.alloc(64, 10); 307 for (let i = 0; i < buf.length; i++) 308 assert.strictEqual(buf[i], 10); 309 310 buf.fill(11, 0, buf.length >> 1); 311 for (let i = 0; i < buf.length >> 1; i++) 312 assert.strictEqual(buf[i], 11); 313 for (let i = (buf.length >> 1) + 1; i < buf.length; i++) 314 assert.strictEqual(buf[i], 10); 315 316 buf.fill('h'); 317 for (let i = 0; i < buf.length; i++) 318 assert.strictEqual(buf[i], 'h'.charCodeAt(0)); 319 320 buf.fill(0); 321 for (let i = 0; i < buf.length; i++) 322 assert.strictEqual(buf[i], 0); 323 324 buf.fill(null); 325 for (let i = 0; i < buf.length; i++) 326 assert.strictEqual(buf[i], 0); 327 328 buf.fill(1, 16, 32); 329 for (let i = 0; i < 16; i++) 330 assert.strictEqual(buf[i], 0); 331 for (let i = 16; i < 32; i++) 332 assert.strictEqual(buf[i], 1); 333 for (let i = 32; i < buf.length; i++) 334 assert.strictEqual(buf[i], 0); 335} 336 337{ 338 const buf = Buffer.alloc(10, 'abc'); 339 assert.strictEqual(buf.toString(), 'abcabcabca'); 340 buf.fill('է'); 341 assert.strictEqual(buf.toString(), 'էէէէէ'); 342} 343 344// Testing process.binding. Make sure "start" is properly checked for range 345// errors. 346assert.throws( 347 () => { internalBinding('buffer').fill(Buffer.alloc(1), 1, -1, 0, 1); }, 348 { code: 'ERR_OUT_OF_RANGE' } 349); 350 351// Make sure "end" is properly checked, even if it's magically mangled using 352// Symbol.toPrimitive. 353{ 354 assert.throws(() => { 355 const end = { 356 [Symbol.toPrimitive]() { 357 return 1; 358 } 359 }; 360 Buffer.alloc(1).fill(Buffer.alloc(1), 0, end); 361 }, { 362 code: 'ERR_INVALID_ARG_TYPE', 363 message: 'The "end" argument must be of type number. Received an ' + 364 'instance of Object' 365 }); 366} 367 368// Testing process.binding. Make sure "end" is properly checked for range 369// errors. 370assert.throws( 371 () => { internalBinding('buffer').fill(Buffer.alloc(1), 1, 1, -2, 1); }, 372 { code: 'ERR_OUT_OF_RANGE' } 373); 374 375// Test that bypassing 'length' won't cause an abort. 376assert.throws(() => { 377 const buf = Buffer.from('w00t'); 378 Object.defineProperty(buf, 'length', { 379 value: 1337, 380 enumerable: true 381 }); 382 buf.fill(''); 383}, { 384 code: 'ERR_BUFFER_OUT_OF_BOUNDS', 385 name: 'RangeError', 386 message: 'Attempt to access memory outside buffer bounds' 387}); 388 389assert.deepStrictEqual( 390 Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), 391 Buffer.from('61006200610062006100620061006200', 'hex')); 392 393assert.deepStrictEqual( 394 Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'), 395 Buffer.from('610062006100620061006200610062', 'hex')); 396 397assert.deepStrictEqual( 398 Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), 399 Buffer.from('61006200610062006100620061006200', 'hex')); 400assert.deepStrictEqual( 401 Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'), 402 Buffer.from('61006100610061006100610061006100', 'hex')); 403 404assert.strictEqual( 405 Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), 406 'a'.repeat(8)); 407assert.strictEqual( 408 Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), 409 'a'.repeat(16)); 410assert.strictEqual( 411 Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), 412 'a'.repeat(16)); 413 414assert.strictEqual( 415 Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), 416 'Љ'.repeat(8)); 417assert.strictEqual( 418 Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), 419 '\t'.repeat(16)); 420assert.strictEqual( 421 Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), 422 'Љ'.repeat(8)); 423 424assert.throws(() => { 425 const buf = Buffer.from('a'.repeat(1000)); 426 427 buf.fill('This is not correctly encoded', 'hex'); 428}, { 429 code: 'ERR_INVALID_ARG_VALUE', 430 name: 'TypeError' 431}); 432 433 434{ 435 const bufEmptyString = Buffer.alloc(5, ''); 436 assert.strictEqual(bufEmptyString.toString(), '\x00\x00\x00\x00\x00'); 437 438 const bufEmptyArray = Buffer.alloc(5, []); 439 assert.strictEqual(bufEmptyArray.toString(), '\x00\x00\x00\x00\x00'); 440 441 const bufEmptyBuffer = Buffer.alloc(5, Buffer.alloc(5)); 442 assert.strictEqual(bufEmptyBuffer.toString(), '\x00\x00\x00\x00\x00'); 443 444 const bufZero = Buffer.alloc(5, 0); 445 assert.strictEqual(bufZero.toString(), '\x00\x00\x00\x00\x00'); 446} 447