• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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