11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci[-1, 10].forEach((offset) => {
71cb0ef41Sopenharmony_ci  assert.throws(
81cb0ef41Sopenharmony_ci    () => Buffer.alloc(9).write('foo', offset),
91cb0ef41Sopenharmony_ci    {
101cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
111cb0ef41Sopenharmony_ci      name: 'RangeError',
121cb0ef41Sopenharmony_ci      message: 'The value of "offset" is out of range. ' +
131cb0ef41Sopenharmony_ci               `It must be >= 0 && <= 9. Received ${offset}`
141cb0ef41Sopenharmony_ci    }
151cb0ef41Sopenharmony_ci  );
161cb0ef41Sopenharmony_ci});
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciconst resultMap = new Map([
191cb0ef41Sopenharmony_ci  ['utf8', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
201cb0ef41Sopenharmony_ci  ['ucs2', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])],
211cb0ef41Sopenharmony_ci  ['ascii', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
221cb0ef41Sopenharmony_ci  ['latin1', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
231cb0ef41Sopenharmony_ci  ['binary', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
241cb0ef41Sopenharmony_ci  ['utf16le', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])],
251cb0ef41Sopenharmony_ci  ['base64', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
261cb0ef41Sopenharmony_ci  ['base64url', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
271cb0ef41Sopenharmony_ci  ['hex', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
281cb0ef41Sopenharmony_ci]);
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// utf8, ucs2, ascii, latin1, utf16le
311cb0ef41Sopenharmony_ciconst encodings = ['utf8', 'utf-8', 'ucs2', 'ucs-2', 'ascii', 'latin1',
321cb0ef41Sopenharmony_ci                   'binary', 'utf16le', 'utf-16le'];
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciencodings
351cb0ef41Sopenharmony_ci  .reduce((es, e) => es.concat(e, e.toUpperCase()), [])
361cb0ef41Sopenharmony_ci  .forEach((encoding) => {
371cb0ef41Sopenharmony_ci    const buf = Buffer.alloc(9);
381cb0ef41Sopenharmony_ci    const len = Buffer.byteLength('foo', encoding);
391cb0ef41Sopenharmony_ci    assert.strictEqual(buf.write('foo', 0, len, encoding), len);
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    if (encoding.includes('-'))
421cb0ef41Sopenharmony_ci      encoding = encoding.replace('-', '');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci    assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
451cb0ef41Sopenharmony_ci  });
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci// base64
481cb0ef41Sopenharmony_ci['base64', 'BASE64', 'base64url', 'BASE64URL'].forEach((encoding) => {
491cb0ef41Sopenharmony_ci  const buf = Buffer.alloc(9);
501cb0ef41Sopenharmony_ci  const len = Buffer.byteLength('Zm9v', encoding);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  assert.strictEqual(buf.write('Zm9v', 0, len, encoding), len);
531cb0ef41Sopenharmony_ci  assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
541cb0ef41Sopenharmony_ci});
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci// hex
571cb0ef41Sopenharmony_ci['hex', 'HEX'].forEach((encoding) => {
581cb0ef41Sopenharmony_ci  const buf = Buffer.alloc(9);
591cb0ef41Sopenharmony_ci  const len = Buffer.byteLength('666f6f', encoding);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  assert.strictEqual(buf.write('666f6f', 0, len, encoding), len);
621cb0ef41Sopenharmony_ci  assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
631cb0ef41Sopenharmony_ci});
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci// Invalid encodings
661cb0ef41Sopenharmony_cifor (let i = 1; i < 10; i++) {
671cb0ef41Sopenharmony_ci  const encoding = String(i).repeat(i);
681cb0ef41Sopenharmony_ci  const error = common.expectsError({
691cb0ef41Sopenharmony_ci    code: 'ERR_UNKNOWN_ENCODING',
701cb0ef41Sopenharmony_ci    name: 'TypeError',
711cb0ef41Sopenharmony_ci    message: `Unknown encoding: ${encoding}`
721cb0ef41Sopenharmony_ci  });
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  assert.ok(!Buffer.isEncoding(encoding));
751cb0ef41Sopenharmony_ci  assert.throws(() => Buffer.alloc(9).write('foo', encoding), error);
761cb0ef41Sopenharmony_ci}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci// UCS-2 overflow CVE-2018-12115
791cb0ef41Sopenharmony_cifor (let i = 1; i < 4; i++) {
801cb0ef41Sopenharmony_ci  // Allocate two Buffers sequentially off the pool. Run more than once in case
811cb0ef41Sopenharmony_ci  // we hit the end of the pool and don't get sequential allocations
821cb0ef41Sopenharmony_ci  const x = Buffer.allocUnsafe(4).fill(0);
831cb0ef41Sopenharmony_ci  const y = Buffer.allocUnsafe(4).fill(1);
841cb0ef41Sopenharmony_ci  // Should not write anything, pos 3 doesn't have enough room for a 16-bit char
851cb0ef41Sopenharmony_ci  assert.strictEqual(x.write('ыыыыыы', 3, 'ucs2'), 0);
861cb0ef41Sopenharmony_ci  // CVE-2018-12115 experienced via buffer overrun to next block in the pool
871cb0ef41Sopenharmony_ci  assert.strictEqual(Buffer.compare(y, Buffer.alloc(4, 1)), 0);
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci// Should not write any data when there is no space for 16-bit chars
911cb0ef41Sopenharmony_ciconst z = Buffer.alloc(4, 0);
921cb0ef41Sopenharmony_ciassert.strictEqual(z.write('\u0001', 3, 'ucs2'), 0);
931cb0ef41Sopenharmony_ciassert.strictEqual(Buffer.compare(z, Buffer.alloc(4, 0)), 0);
941cb0ef41Sopenharmony_ci// Make sure longer strings are written up to the buffer end.
951cb0ef41Sopenharmony_ciassert.strictEqual(z.write('abcd', 2), 2);
961cb0ef41Sopenharmony_ciassert.deepStrictEqual([...z], [0, 0, 0x61, 0x62]);
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci// Large overrun could corrupt the process
991cb0ef41Sopenharmony_ciassert.strictEqual(Buffer.alloc(4)
1001cb0ef41Sopenharmony_ci  .write('ыыыыыы'.repeat(100), 3, 'utf16le'), 0);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci{
1031cb0ef41Sopenharmony_ci  // .write() does not affect the byte after the written-to slice of the Buffer.
1041cb0ef41Sopenharmony_ci  // Refs: https://github.com/nodejs/node/issues/26422
1051cb0ef41Sopenharmony_ci  const buf = Buffer.alloc(8);
1061cb0ef41Sopenharmony_ci  assert.strictEqual(buf.write('ыы', 1, 'utf16le'), 4);
1071cb0ef41Sopenharmony_ci  assert.deepStrictEqual([...buf], [0, 0x4b, 0x04, 0x4b, 0x04, 0, 0, 0]);
1081cb0ef41Sopenharmony_ci}
109