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', 'ucs2'); 135testBufs('yKJhYQ==', 'ucs2'); 136testBufs('Yci0Ysi1Y8i2', 'ucs2'); 137testBufs('YWJj', 4, 'ucs2'); 138testBufs('YWJj', SIZE, 'ucs2'); 139testBufs('yKJhYQ==', 2, 'ucs2'); 140testBufs('yKJhYQ==', 8, 'ucs2'); 141testBufs('Yci0Ysi1Y8i2', 4, 'ucs2'); 142testBufs('Yci0Ysi1Y8i2', 12, 'ucs2'); 143testBufs('YWJj', 4, 1, 'ucs2'); 144testBufs('YWJj', 5, 1, 'ucs2'); 145testBufs('yKJhYQ==', 8, 1, 'ucs2'); 146testBufs('Yci0Ysi1Y8i2', 4, 1, 'ucs2'); 147testBufs('Yci0Ysi1Y8i2', 12, 1, 'ucs2'); 148 149// Buffer 150function deepStrictEqualValues(buf, arr) { 151 for (const [index, value] of buf.entries()) { 152 assert.deepStrictEqual(value, arr[index]); 153 } 154} 155 156const buf2Fill = Buffer.allocUnsafe(1).fill(2); 157deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); 158deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); 159deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); 160deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); 161const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill('0102', 'hex'); 162deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); 163deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); 164deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); 165deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); 166 167// Check exceptions 168[ 169 [0, -1], 170 [0, 0, buf1.length + 1], 171 ['', -1], 172 ['', 0, buf1.length + 1], 173 ['', 1, -1], 174].forEach((args) => { 175 assert.throws( 176 () => buf1.fill(...args), 177 { code: 'ERR_OUT_OF_RANGE' } 178 ); 179}); 180 181assert.throws( 182 () => buf1.fill('a', 0, buf1.length, 'node rocks!'), 183 { 184 code: 'ERR_UNKNOWN_ENCODING', 185 name: 'TypeError', 186 message: 'Unknown encoding: node rocks!' 187 } 188); 189 190[ 191 ['a', 0, 0, NaN], 192 ['a', 0, 0, false] 193].forEach((args) => { 194 assert.throws( 195 () => buf1.fill(...args), 196 { 197 code: 'ERR_INVALID_ARG_TYPE', 198 message: 'The "encoding" argument must be of type ' + 199 `string.${common.invalidArgTypeHelper(args[3])}` 200 } 201 ); 202}); 203 204assert.throws( 205 () => buf1.fill('a', 0, 0, 'foo'), 206 { 207 code: 'ERR_UNKNOWN_ENCODING', 208 name: 'TypeError', 209 message: 'Unknown encoding: foo' 210 } 211); 212 213function genBuffer(size, args) { 214 const b = Buffer.allocUnsafe(size); 215 return b.fill(0).fill.apply(b, args); 216} 217 218function bufReset() { 219 buf1.fill(0); 220 buf2.fill(0); 221} 222 223// This is mostly accurate. Except write() won't write partial bytes to the 224// string while fill() blindly copies bytes into memory. To account for that an 225// error will be thrown if not all the data can be written, and the SIZE has 226// been massaged to work with the input characters. 227function writeToFill(string, offset, end, encoding) { 228 if (typeof offset === 'string') { 229 encoding = offset; 230 offset = 0; 231 end = buf2.length; 232 } else if (typeof end === 'string') { 233 encoding = end; 234 end = buf2.length; 235 } else if (end === undefined) { 236 end = buf2.length; 237 } 238 239 // Should never be reached. 240 if (offset < 0 || end > buf2.length) 241 throw new ERR_OUT_OF_RANGE(); 242 243 if (end <= offset) 244 return buf2; 245 246 offset >>>= 0; 247 end >>>= 0; 248 assert(offset <= buf2.length); 249 250 // Convert "end" to "length" (which write understands). 251 const length = end - offset < 0 ? 0 : end - offset; 252 253 let wasZero = false; 254 do { 255 const written = buf2.write(string, offset, length, encoding); 256 offset += written; 257 // Safety check in case write falls into infinite loop. 258 if (written === 0) { 259 if (wasZero) 260 throw new Error('Could not write all data to Buffer'); 261 else 262 wasZero = true; 263 } 264 } while (offset < buf2.length); 265 266 return buf2; 267} 268 269function testBufs(string, offset, length, encoding) { 270 bufReset(); 271 buf1.fill.apply(buf1, arguments); 272 // Swap bytes on BE archs for ucs2 encoding. 273 assert.deepStrictEqual(buf1.fill.apply(buf1, arguments), 274 writeToFill.apply(null, arguments)); 275} 276 277// Make sure these throw. 278assert.throws( 279 () => Buffer.allocUnsafe(8).fill('a', -1), 280 { code: 'ERR_OUT_OF_RANGE' }); 281assert.throws( 282 () => Buffer.allocUnsafe(8).fill('a', 0, 9), 283 { code: 'ERR_OUT_OF_RANGE' }); 284 285// Make sure this doesn't hang indefinitely. 286Buffer.allocUnsafe(8).fill(''); 287Buffer.alloc(8, ''); 288 289{ 290 const buf = Buffer.alloc(64, 10); 291 for (let i = 0; i < buf.length; i++) 292 assert.strictEqual(buf[i], 10); 293 294 buf.fill(11, 0, buf.length >> 1); 295 for (let i = 0; i < buf.length >> 1; i++) 296 assert.strictEqual(buf[i], 11); 297 for (let i = (buf.length >> 1) + 1; i < buf.length; i++) 298 assert.strictEqual(buf[i], 10); 299 300 buf.fill('h'); 301 for (let i = 0; i < buf.length; i++) 302 assert.strictEqual('h'.charCodeAt(0), buf[i]); 303 304 buf.fill(0); 305 for (let i = 0; i < buf.length; i++) 306 assert.strictEqual(buf[i], 0); 307 308 buf.fill(null); 309 for (let i = 0; i < buf.length; i++) 310 assert.strictEqual(buf[i], 0); 311 312 buf.fill(1, 16, 32); 313 for (let i = 0; i < 16; i++) 314 assert.strictEqual(buf[i], 0); 315 for (let i = 16; i < 32; i++) 316 assert.strictEqual(buf[i], 1); 317 for (let i = 32; i < buf.length; i++) 318 assert.strictEqual(buf[i], 0); 319} 320 321{ 322 const buf = Buffer.alloc(10, 'abc'); 323 assert.strictEqual(buf.toString(), 'abcabcabca'); 324 buf.fill('է'); 325 assert.strictEqual(buf.toString(), 'էէէէէ'); 326} 327 328// Testing process.binding. Make sure "start" is properly checked for range 329// errors. 330assert.throws( 331 () => { internalBinding('buffer').fill(Buffer.alloc(1), 1, -1, 0, 1); }, 332 { code: 'ERR_OUT_OF_RANGE' } 333); 334 335// Make sure "end" is properly checked, even if it's magically mangled using 336// Symbol.toPrimitive. 337{ 338 assert.throws(() => { 339 const end = { 340 [Symbol.toPrimitive]() { 341 return 1; 342 } 343 }; 344 Buffer.alloc(1).fill(Buffer.alloc(1), 0, end); 345 }, { 346 code: 'ERR_INVALID_ARG_TYPE', 347 message: 'The "end" argument must be of type number. Received an ' + 348 'instance of Object' 349 }); 350} 351 352// Testing process.binding. Make sure "end" is properly checked for range 353// errors. 354assert.throws( 355 () => { internalBinding('buffer').fill(Buffer.alloc(1), 1, 1, -2, 1); }, 356 { code: 'ERR_OUT_OF_RANGE' } 357); 358 359// Test that bypassing 'length' won't cause an abort. 360assert.throws(() => { 361 const buf = Buffer.from('w00t'); 362 Object.defineProperty(buf, 'length', { 363 value: 1337, 364 enumerable: true 365 }); 366 buf.fill(''); 367}, { 368 code: 'ERR_BUFFER_OUT_OF_BOUNDS', 369 name: 'RangeError', 370 message: 'Attempt to access memory outside buffer bounds' 371}); 372 373assert.deepStrictEqual( 374 Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), 375 Buffer.from('61006200610062006100620061006200', 'hex')); 376 377assert.deepStrictEqual( 378 Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'), 379 Buffer.from('610062006100620061006200610062', 'hex')); 380 381assert.deepStrictEqual( 382 Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), 383 Buffer.from('61006200610062006100620061006200', 'hex')); 384assert.deepStrictEqual( 385 Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'), 386 Buffer.from('61006100610061006100610061006100', 'hex')); 387 388assert.strictEqual( 389 Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), 390 'a'.repeat(8)); 391assert.strictEqual( 392 Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), 393 'a'.repeat(16)); 394assert.strictEqual( 395 Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), 396 'a'.repeat(16)); 397 398assert.strictEqual( 399 Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), 400 'Љ'.repeat(8)); 401assert.strictEqual( 402 Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), 403 '\t'.repeat(16)); 404assert.strictEqual( 405 Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), 406 'Љ'.repeat(8)); 407 408assert.throws(() => { 409 const buf = Buffer.from('a'.repeat(1000)); 410 411 buf.fill('This is not correctly encoded', 'hex'); 412}, { 413 code: 'ERR_INVALID_ARG_VALUE', 414 name: 'TypeError' 415}); 416