1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23 24const { 25 Array, 26 ArrayIsArray, 27 Error, 28 MathFloor, 29 MathMin, 30 MathTrunc, 31 NumberIsNaN, 32 NumberMAX_SAFE_INTEGER, 33 NumberMIN_SAFE_INTEGER, 34 ObjectCreate, 35 ObjectDefineProperties, 36 ObjectDefineProperty, 37 ObjectGetOwnPropertyDescriptor, 38 ObjectGetPrototypeOf, 39 ObjectSetPrototypeOf, 40 SymbolSpecies, 41 SymbolToPrimitive, 42 Uint8Array, 43 Uint8ArrayPrototype, 44} = primordials; 45 46const { 47 byteLengthUtf8, 48 compare: _compare, 49 compareOffset, 50 createFromString, 51 fill: bindingFill, 52 indexOfBuffer, 53 indexOfNumber, 54 indexOfString, 55 swap16: _swap16, 56 swap32: _swap32, 57 swap64: _swap64, 58 kMaxLength, 59 kStringMaxLength, 60 zeroFill: bindingZeroFill 61} = internalBinding('buffer'); 62const { 63 getOwnNonIndexProperties, 64 propertyFilter: { 65 ALL_PROPERTIES, 66 ONLY_ENUMERABLE 67 }, 68} = internalBinding('util'); 69const { 70 customInspectSymbol, 71 isInsideNodeModules, 72 normalizeEncoding, 73 kIsEncodingSymbol 74} = require('internal/util'); 75const { 76 isAnyArrayBuffer, 77 isArrayBufferView, 78 isUint8Array 79} = require('internal/util/types'); 80const { 81 inspect: utilInspect 82} = require('internal/util/inspect'); 83const { encodings } = internalBinding('string_decoder'); 84 85const { 86 codes: { 87 ERR_BUFFER_OUT_OF_BOUNDS, 88 ERR_INVALID_ARG_TYPE, 89 ERR_INVALID_ARG_VALUE, 90 ERR_INVALID_BUFFER_SIZE, 91 ERR_INVALID_OPT_VALUE, 92 ERR_OUT_OF_RANGE, 93 ERR_UNKNOWN_ENCODING 94 }, 95 hideStackFrames 96} = require('internal/errors'); 97const { 98 validateBuffer, 99 validateInt32, 100 validateString 101} = require('internal/validators'); 102 103const { 104 FastBuffer, 105 markAsUntransferable, 106 addBufferPrototypeMethods 107} = require('internal/buffer'); 108 109const TypedArrayPrototype = ObjectGetPrototypeOf(Uint8ArrayPrototype); 110 111const TypedArrayProto_byteLength = 112 ObjectGetOwnPropertyDescriptor(TypedArrayPrototype, 113 'byteLength').get; 114const TypedArrayFill = TypedArrayPrototype.fill; 115 116FastBuffer.prototype.constructor = Buffer; 117Buffer.prototype = FastBuffer.prototype; 118addBufferPrototypeMethods(Buffer.prototype); 119 120const constants = ObjectDefineProperties({}, { 121 MAX_LENGTH: { 122 value: kMaxLength, 123 writable: false, 124 enumerable: true 125 }, 126 MAX_STRING_LENGTH: { 127 value: kStringMaxLength, 128 writable: false, 129 enumerable: true 130 } 131}); 132 133Buffer.poolSize = 8 * 1024; 134let poolSize, poolOffset, allocPool; 135 136// A toggle used to access the zero fill setting of the array buffer allocator 137// in C++. 138// |zeroFill| can be undefined when running inside an isolate where we 139// do not own the ArrayBuffer allocator. Zero fill is always on in that case. 140const zeroFill = bindingZeroFill || [0]; 141 142const encodingsMap = ObjectCreate(null); 143for (let i = 0; i < encodings.length; ++i) 144 encodingsMap[encodings[i]] = i; 145 146function createUnsafeBuffer(size) { 147 zeroFill[0] = 0; 148 try { 149 return new FastBuffer(size); 150 } finally { 151 zeroFill[0] = 1; 152 } 153} 154 155function createPool() { 156 poolSize = Buffer.poolSize; 157 allocPool = createUnsafeBuffer(poolSize).buffer; 158 markAsUntransferable(allocPool); 159 poolOffset = 0; 160} 161createPool(); 162 163function alignPool() { 164 // Ensure aligned slices 165 if (poolOffset & 0x7) { 166 poolOffset |= 0x7; 167 poolOffset++; 168 } 169} 170 171let bufferWarningAlreadyEmitted = false; 172let nodeModulesCheckCounter = 0; 173const bufferWarning = 'Buffer() is deprecated due to security and usability ' + 174 'issues. Please use the Buffer.alloc(), ' + 175 'Buffer.allocUnsafe(), or Buffer.from() methods instead.'; 176 177function showFlaggedDeprecation() { 178 if (bufferWarningAlreadyEmitted || 179 ++nodeModulesCheckCounter > 10000 || 180 (!require('internal/options').getOptionValue('--pending-deprecation') && 181 isInsideNodeModules())) { 182 // We don't emit a warning, because we either: 183 // - Already did so, or 184 // - Already checked too many times whether a call is coming 185 // from node_modules and want to stop slowing down things, or 186 // - We aren't running with `--pending-deprecation` enabled, 187 // and the code is inside `node_modules`. 188 return; 189 } 190 191 process.emitWarning(bufferWarning, 'DeprecationWarning', 'DEP0005'); 192 bufferWarningAlreadyEmitted = true; 193} 194 195function toInteger(n, defaultVal) { 196 n = +n; 197 if (!NumberIsNaN(n) && 198 n >= NumberMIN_SAFE_INTEGER && 199 n <= NumberMAX_SAFE_INTEGER) { 200 return ((n % 1) === 0 ? n : MathFloor(n)); 201 } 202 return defaultVal; 203} 204 205function _copy(source, target, targetStart, sourceStart, sourceEnd) { 206 if (!isUint8Array(source)) 207 throw new ERR_INVALID_ARG_TYPE('source', ['Buffer', 'Uint8Array'], source); 208 if (!isUint8Array(target)) 209 throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); 210 211 if (targetStart === undefined) { 212 targetStart = 0; 213 } else { 214 targetStart = toInteger(targetStart, 0); 215 if (targetStart < 0) 216 throw new ERR_OUT_OF_RANGE('targetStart', '>= 0', targetStart); 217 } 218 219 if (sourceStart === undefined) { 220 sourceStart = 0; 221 } else { 222 sourceStart = toInteger(sourceStart, 0); 223 if (sourceStart < 0) 224 throw new ERR_OUT_OF_RANGE('sourceStart', '>= 0', sourceStart); 225 } 226 227 if (sourceEnd === undefined) { 228 sourceEnd = source.length; 229 } else { 230 sourceEnd = toInteger(sourceEnd, 0); 231 if (sourceEnd < 0) 232 throw new ERR_OUT_OF_RANGE('sourceEnd', '>= 0', sourceEnd); 233 } 234 235 if (targetStart >= target.length || sourceStart >= sourceEnd) 236 return 0; 237 238 if (sourceStart > source.length) { 239 throw new ERR_OUT_OF_RANGE('sourceStart', 240 `<= ${source.length}`, 241 sourceStart); 242 } 243 244 return _copyActual(source, target, targetStart, sourceStart, sourceEnd); 245} 246 247function _copyActual(source, target, targetStart, sourceStart, sourceEnd) { 248 if (sourceEnd - sourceStart > target.length - targetStart) 249 sourceEnd = sourceStart + target.length - targetStart; 250 251 let nb = sourceEnd - sourceStart; 252 const targetLen = target.length - targetStart; 253 const sourceLen = source.length - sourceStart; 254 if (nb > targetLen) 255 nb = targetLen; 256 if (nb > sourceLen) 257 nb = sourceLen; 258 259 if (sourceStart !== 0 || sourceEnd < source.length) 260 source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb); 261 262 target.set(source, targetStart); 263 264 return nb; 265} 266 267/** 268 * The Buffer() constructor is deprecated in documentation and should not be 269 * used moving forward. Rather, developers should use one of the three new 270 * factory APIs: Buffer.from(), Buffer.allocUnsafe() or Buffer.alloc() based on 271 * their specific needs. There is no runtime deprecation because of the extent 272 * to which the Buffer constructor is used in the ecosystem currently -- a 273 * runtime deprecation would introduce too much breakage at this time. It's not 274 * likely that the Buffer constructors would ever actually be removed. 275 * Deprecation Code: DEP0005 276 */ 277function Buffer(arg, encodingOrOffset, length) { 278 showFlaggedDeprecation(); 279 // Common case. 280 if (typeof arg === 'number') { 281 if (typeof encodingOrOffset === 'string') { 282 throw new ERR_INVALID_ARG_TYPE('string', 'string', arg); 283 } 284 return Buffer.alloc(arg); 285 } 286 return Buffer.from(arg, encodingOrOffset, length); 287} 288 289ObjectDefineProperty(Buffer, SymbolSpecies, { 290 enumerable: false, 291 configurable: true, 292 get() { return FastBuffer; } 293}); 294 295/** 296 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError 297 * if value is a number. 298 * Buffer.from(str[, encoding]) 299 * Buffer.from(array) 300 * Buffer.from(buffer) 301 * Buffer.from(arrayBuffer[, byteOffset[, length]]) 302 */ 303Buffer.from = function from(value, encodingOrOffset, length) { 304 if (typeof value === 'string') 305 return fromString(value, encodingOrOffset); 306 307 if (typeof value === 'object' && value !== null) { 308 if (isAnyArrayBuffer(value)) 309 return fromArrayBuffer(value, encodingOrOffset, length); 310 311 const valueOf = value.valueOf && value.valueOf(); 312 if (valueOf != null && 313 valueOf !== value && 314 (typeof valueOf === 'string' || typeof valueOf === 'object')) { 315 return from(valueOf, encodingOrOffset, length); 316 } 317 318 const b = fromObject(value); 319 if (b) 320 return b; 321 322 if (typeof value[SymbolToPrimitive] === 'function') { 323 const primitive = value[SymbolToPrimitive]('string'); 324 if (typeof primitive === 'string') { 325 return fromString(primitive, encodingOrOffset); 326 } 327 } 328 } 329 330 throw new ERR_INVALID_ARG_TYPE( 331 'first argument', 332 ['string', 'Buffer', 'ArrayBuffer', 'Array', 'Array-like Object'], 333 value 334 ); 335}; 336 337// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated 338// Buffer() constructor. Must use arrow function syntax to avoid automatically 339// adding a `prototype` property and making the function a constructor. 340// 341// Refs: https://tc39.github.io/ecma262/#sec-%typedarray%.of 342// Refs: https://esdiscuss.org/topic/isconstructor#content-11 343const of = (...items) => { 344 const newObj = createUnsafeBuffer(items.length); 345 for (let k = 0; k < items.length; k++) 346 newObj[k] = items[k]; 347 return newObj; 348}; 349Buffer.of = of; 350 351ObjectSetPrototypeOf(Buffer, Uint8Array); 352 353// The 'assertSize' method will remove itself from the callstack when an error 354// occurs. This is done simply to keep the internal details of the 355// implementation from bleeding out to users. 356const assertSize = hideStackFrames((size) => { 357 if (typeof size !== 'number') { 358 throw new ERR_INVALID_ARG_TYPE('size', 'number', size); 359 } 360 if (!(size >= 0 && size <= kMaxLength)) { 361 throw new ERR_INVALID_OPT_VALUE.RangeError('size', size); 362 } 363}); 364 365/** 366 * Creates a new filled Buffer instance. 367 * alloc(size[, fill[, encoding]]) 368 */ 369Buffer.alloc = function alloc(size, fill, encoding) { 370 assertSize(size); 371 if (fill !== undefined && fill !== 0 && size > 0) { 372 const buf = createUnsafeBuffer(size); 373 return _fill(buf, fill, 0, buf.length, encoding); 374 } 375 return new FastBuffer(size); 376}; 377 378/** 379 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer 380 * instance. If `--zero-fill-buffers` is set, will zero-fill the buffer. 381 */ 382Buffer.allocUnsafe = function allocUnsafe(size) { 383 assertSize(size); 384 return allocate(size); 385}; 386 387/** 388 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled 389 * Buffer instance that is not allocated off the pre-initialized pool. 390 * If `--zero-fill-buffers` is set, will zero-fill the buffer. 391 */ 392Buffer.allocUnsafeSlow = function allocUnsafeSlow(size) { 393 assertSize(size); 394 return createUnsafeBuffer(size); 395}; 396 397// If --zero-fill-buffers command line argument is set, a zero-filled 398// buffer is returned. 399function SlowBuffer(length) { 400 assertSize(length); 401 return createUnsafeBuffer(length); 402} 403 404ObjectSetPrototypeOf(SlowBuffer.prototype, Uint8ArrayPrototype); 405ObjectSetPrototypeOf(SlowBuffer, Uint8Array); 406 407function allocate(size) { 408 if (size <= 0) { 409 return new FastBuffer(); 410 } 411 if (size < (Buffer.poolSize >>> 1)) { 412 if (size > (poolSize - poolOffset)) 413 createPool(); 414 const b = new FastBuffer(allocPool, poolOffset, size); 415 poolOffset += size; 416 alignPool(); 417 return b; 418 } 419 return createUnsafeBuffer(size); 420} 421 422function fromStringFast(string, ops) { 423 const length = ops.byteLength(string); 424 425 if (length >= (Buffer.poolSize >>> 1)) 426 return createFromString(string, ops.encodingVal); 427 428 if (length > (poolSize - poolOffset)) 429 createPool(); 430 let b = new FastBuffer(allocPool, poolOffset, length); 431 const actual = ops.write(b, string, 0, length); 432 if (actual !== length) { 433 // byteLength() may overestimate. That's a rare case, though. 434 b = new FastBuffer(allocPool, poolOffset, actual); 435 } 436 poolOffset += actual; 437 alignPool(); 438 return b; 439} 440 441function fromString(string, encoding) { 442 let ops; 443 if (typeof encoding !== 'string' || encoding.length === 0) { 444 if (string.length === 0) 445 return new FastBuffer(); 446 ops = encodingOps.utf8; 447 encoding = undefined; 448 } else { 449 ops = getEncodingOps(encoding); 450 if (ops === undefined) 451 throw new ERR_UNKNOWN_ENCODING(encoding); 452 if (string.length === 0) 453 return new FastBuffer(); 454 } 455 return fromStringFast(string, ops); 456} 457 458function fromArrayBuffer(obj, byteOffset, length) { 459 // Convert byteOffset to integer 460 if (byteOffset === undefined) { 461 byteOffset = 0; 462 } else { 463 byteOffset = +byteOffset; 464 if (NumberIsNaN(byteOffset)) 465 byteOffset = 0; 466 } 467 468 const maxLength = obj.byteLength - byteOffset; 469 470 if (maxLength < 0) 471 throw new ERR_BUFFER_OUT_OF_BOUNDS('offset'); 472 473 if (length === undefined) { 474 length = maxLength; 475 } else { 476 // Convert length to non-negative integer. 477 length = +length; 478 if (length > 0) { 479 if (length > maxLength) 480 throw new ERR_BUFFER_OUT_OF_BOUNDS('length'); 481 } else { 482 length = 0; 483 } 484 } 485 486 return new FastBuffer(obj, byteOffset, length); 487} 488 489function fromArrayLike(obj) { 490 if (obj.length <= 0) 491 return new FastBuffer(); 492 if (obj.length < (Buffer.poolSize >>> 1)) { 493 if (obj.length > (poolSize - poolOffset)) 494 createPool(); 495 const b = new FastBuffer(allocPool, poolOffset, obj.length); 496 b.set(obj, 0); 497 poolOffset += obj.length; 498 alignPool(); 499 return b; 500 } 501 return new FastBuffer(obj); 502} 503 504function fromObject(obj) { 505 if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) { 506 if (typeof obj.length !== 'number') { 507 return new FastBuffer(); 508 } 509 return fromArrayLike(obj); 510 } 511 512 if (obj.type === 'Buffer' && ArrayIsArray(obj.data)) { 513 return fromArrayLike(obj.data); 514 } 515} 516 517// Static methods 518 519Buffer.isBuffer = function isBuffer(b) { 520 return b instanceof Buffer; 521}; 522 523Buffer.compare = function compare(buf1, buf2) { 524 if (!isUint8Array(buf1)) { 525 throw new ERR_INVALID_ARG_TYPE('buf1', ['Buffer', 'Uint8Array'], buf1); 526 } 527 528 if (!isUint8Array(buf2)) { 529 throw new ERR_INVALID_ARG_TYPE('buf2', ['Buffer', 'Uint8Array'], buf2); 530 } 531 532 if (buf1 === buf2) { 533 return 0; 534 } 535 536 return _compare(buf1, buf2); 537}; 538 539Buffer.isEncoding = function isEncoding(encoding) { 540 return typeof encoding === 'string' && encoding.length !== 0 && 541 normalizeEncoding(encoding) !== undefined; 542}; 543Buffer[kIsEncodingSymbol] = Buffer.isEncoding; 544 545Buffer.concat = function concat(list, length) { 546 if (!ArrayIsArray(list)) { 547 throw new ERR_INVALID_ARG_TYPE('list', 'Array', list); 548 } 549 550 if (list.length === 0) 551 return new FastBuffer(); 552 553 if (length === undefined) { 554 length = 0; 555 for (let i = 0; i < list.length; i++) { 556 if (list[i].length) { 557 length += list[i].length; 558 } 559 } 560 } else { 561 validateInt32(length, 'length', 0); 562 } 563 564 const buffer = Buffer.allocUnsafe(length); 565 let pos = 0; 566 for (let i = 0; i < list.length; i++) { 567 const buf = list[i]; 568 if (!isUint8Array(buf)) { 569 // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. 570 // Instead, find the proper error code for this. 571 throw new ERR_INVALID_ARG_TYPE( 572 `list[${i}]`, ['Buffer', 'Uint8Array'], list[i]); 573 } 574 pos += _copyActual(buf, buffer, pos, 0, buf.length); 575 } 576 577 // Note: `length` is always equal to `buffer.length` at this point 578 if (pos < length) { 579 // Zero-fill the remaining bytes if the specified `length` was more than 580 // the actual total length, i.e. if we have some remaining allocated bytes 581 // there were not initialized. 582 TypedArrayFill.call(buffer, 0, pos, length); 583 } 584 585 return buffer; 586}; 587 588function base64ByteLength(str, bytes) { 589 // Handle padding 590 if (str.charCodeAt(bytes - 1) === 0x3D) 591 bytes--; 592 if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3D) 593 bytes--; 594 595 // Base64 ratio: 3/4 596 return (bytes * 3) >>> 2; 597} 598 599const encodingOps = { 600 utf8: { 601 encoding: 'utf8', 602 encodingVal: encodingsMap.utf8, 603 byteLength: byteLengthUtf8, 604 write: (buf, string, offset, len) => buf.utf8Write(string, offset, len), 605 slice: (buf, start, end) => buf.utf8Slice(start, end), 606 indexOf: (buf, val, byteOffset, dir) => 607 indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir) 608 }, 609 ucs2: { 610 encoding: 'ucs2', 611 encodingVal: encodingsMap.utf16le, 612 byteLength: (string) => string.length * 2, 613 write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 614 slice: (buf, start, end) => buf.ucs2Slice(start, end), 615 indexOf: (buf, val, byteOffset, dir) => 616 indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 617 }, 618 utf16le: { 619 encoding: 'utf16le', 620 encodingVal: encodingsMap.utf16le, 621 byteLength: (string) => string.length * 2, 622 write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 623 slice: (buf, start, end) => buf.ucs2Slice(start, end), 624 indexOf: (buf, val, byteOffset, dir) => 625 indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 626 }, 627 latin1: { 628 encoding: 'latin1', 629 encodingVal: encodingsMap.latin1, 630 byteLength: (string) => string.length, 631 write: (buf, string, offset, len) => buf.latin1Write(string, offset, len), 632 slice: (buf, start, end) => buf.latin1Slice(start, end), 633 indexOf: (buf, val, byteOffset, dir) => 634 indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir) 635 }, 636 ascii: { 637 encoding: 'ascii', 638 encodingVal: encodingsMap.ascii, 639 byteLength: (string) => string.length, 640 write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len), 641 slice: (buf, start, end) => buf.asciiSlice(start, end), 642 indexOf: (buf, val, byteOffset, dir) => 643 indexOfBuffer(buf, 644 fromStringFast(val, encodingOps.ascii), 645 byteOffset, 646 encodingsMap.ascii, 647 dir) 648 }, 649 base64: { 650 encoding: 'base64', 651 encodingVal: encodingsMap.base64, 652 byteLength: (string) => base64ByteLength(string, string.length), 653 write: (buf, string, offset, len) => buf.base64Write(string, offset, len), 654 slice: (buf, start, end) => buf.base64Slice(start, end), 655 indexOf: (buf, val, byteOffset, dir) => 656 indexOfBuffer(buf, 657 fromStringFast(val, encodingOps.base64), 658 byteOffset, 659 encodingsMap.base64, 660 dir) 661 }, 662 hex: { 663 encoding: 'hex', 664 encodingVal: encodingsMap.hex, 665 byteLength: (string) => string.length >>> 1, 666 write: (buf, string, offset, len) => buf.hexWrite(string, offset, len), 667 slice: (buf, start, end) => buf.hexSlice(start, end), 668 indexOf: (buf, val, byteOffset, dir) => 669 indexOfBuffer(buf, 670 fromStringFast(val, encodingOps.hex), 671 byteOffset, 672 encodingsMap.hex, 673 dir) 674 } 675}; 676function getEncodingOps(encoding) { 677 encoding += ''; 678 switch (encoding.length) { 679 case 4: 680 if (encoding === 'utf8') return encodingOps.utf8; 681 if (encoding === 'ucs2') return encodingOps.ucs2; 682 encoding = encoding.toLowerCase(); 683 if (encoding === 'utf8') return encodingOps.utf8; 684 if (encoding === 'ucs2') return encodingOps.ucs2; 685 break; 686 case 5: 687 if (encoding === 'utf-8') return encodingOps.utf8; 688 if (encoding === 'ascii') return encodingOps.ascii; 689 if (encoding === 'ucs-2') return encodingOps.ucs2; 690 encoding = encoding.toLowerCase(); 691 if (encoding === 'utf-8') return encodingOps.utf8; 692 if (encoding === 'ascii') return encodingOps.ascii; 693 if (encoding === 'ucs-2') return encodingOps.ucs2; 694 break; 695 case 7: 696 if (encoding === 'utf16le' || encoding.toLowerCase() === 'utf16le') 697 return encodingOps.utf16le; 698 break; 699 case 8: 700 if (encoding === 'utf-16le' || encoding.toLowerCase() === 'utf-16le') 701 return encodingOps.utf16le; 702 break; 703 case 6: 704 if (encoding === 'latin1' || encoding === 'binary') 705 return encodingOps.latin1; 706 if (encoding === 'base64') return encodingOps.base64; 707 encoding = encoding.toLowerCase(); 708 if (encoding === 'latin1' || encoding === 'binary') 709 return encodingOps.latin1; 710 if (encoding === 'base64') return encodingOps.base64; 711 break; 712 case 3: 713 if (encoding === 'hex' || encoding.toLowerCase() === 'hex') 714 return encodingOps.hex; 715 break; 716 } 717} 718 719function byteLength(string, encoding) { 720 if (typeof string !== 'string') { 721 if (isArrayBufferView(string) || isAnyArrayBuffer(string)) { 722 return string.byteLength; 723 } 724 725 throw new ERR_INVALID_ARG_TYPE( 726 'string', ['string', 'Buffer', 'ArrayBuffer'], string 727 ); 728 } 729 730 const len = string.length; 731 const mustMatch = (arguments.length > 2 && arguments[2] === true); 732 if (!mustMatch && len === 0) 733 return 0; 734 735 if (!encoding) 736 return (mustMatch ? -1 : byteLengthUtf8(string)); 737 738 const ops = getEncodingOps(encoding); 739 if (ops === undefined) 740 return (mustMatch ? -1 : byteLengthUtf8(string)); 741 return ops.byteLength(string); 742} 743 744Buffer.byteLength = byteLength; 745 746// For backwards compatibility. 747ObjectDefineProperty(Buffer.prototype, 'parent', { 748 enumerable: true, 749 get() { 750 if (!(this instanceof Buffer)) 751 return undefined; 752 return this.buffer; 753 } 754}); 755ObjectDefineProperty(Buffer.prototype, 'offset', { 756 enumerable: true, 757 get() { 758 if (!(this instanceof Buffer)) 759 return undefined; 760 return this.byteOffset; 761 } 762}); 763 764Buffer.prototype.copy = 765 function copy(target, targetStart, sourceStart, sourceEnd) { 766 return _copy(this, target, targetStart, sourceStart, sourceEnd); 767 }; 768 769// No need to verify that "buf.length <= MAX_UINT32" since it's a read-only 770// property of a typed array. 771// This behaves neither like String nor Uint8Array in that we set start/end 772// to their upper/lower bounds if the value passed is out of range. 773Buffer.prototype.toString = function toString(encoding, start, end) { 774 if (arguments.length === 0) { 775 return this.utf8Slice(0, this.length); 776 } 777 778 const len = this.length; 779 780 if (start <= 0) 781 start = 0; 782 else if (start >= len) 783 return ''; 784 else 785 start |= 0; 786 787 if (end === undefined || end > len) 788 end = len; 789 else 790 end |= 0; 791 792 if (end <= start) 793 return ''; 794 795 if (encoding === undefined) 796 return this.utf8Slice(start, end); 797 798 const ops = getEncodingOps(encoding); 799 if (ops === undefined) 800 throw new ERR_UNKNOWN_ENCODING(encoding); 801 802 return ops.slice(this, start, end); 803}; 804 805Buffer.prototype.equals = function equals(otherBuffer) { 806 if (!isUint8Array(otherBuffer)) { 807 throw new ERR_INVALID_ARG_TYPE( 808 'otherBuffer', ['Buffer', 'Uint8Array'], otherBuffer); 809 } 810 811 if (this === otherBuffer) 812 return true; 813 814 if (this.byteLength !== otherBuffer.byteLength) 815 return false; 816 817 return this.byteLength === 0 || _compare(this, otherBuffer) === 0; 818}; 819 820let INSPECT_MAX_BYTES = 50; 821// Override how buffers are presented by util.inspect(). 822Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { 823 const max = INSPECT_MAX_BYTES; 824 const actualMax = MathMin(max, this.length); 825 const remaining = this.length - max; 826 let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim(); 827 if (remaining > 0) 828 str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`; 829 // Inspect special properties as well, if possible. 830 if (ctx) { 831 let extras = false; 832 const filter = ctx.showHidden ? ALL_PROPERTIES : ONLY_ENUMERABLE; 833 const obj = getOwnNonIndexProperties(this, filter).reduce((obj, key) => { 834 extras = true; 835 obj[key] = this[key]; 836 return obj; 837 }, ObjectCreate(null)); 838 if (extras) { 839 if (this.length !== 0) 840 str += ', '; 841 // '[Object: null prototype] {'.length === 26 842 // This is guarded with a test. 843 str += utilInspect(obj, { 844 ...ctx, 845 breakLength: Infinity, 846 compact: true 847 }).slice(27, -2); 848 } 849 } 850 return `<${this.constructor.name} ${str}>`; 851}; 852Buffer.prototype.inspect = Buffer.prototype[customInspectSymbol]; 853 854Buffer.prototype.compare = function compare(target, 855 targetStart, 856 targetEnd, 857 sourceStart, 858 sourceEnd) { 859 if (!isUint8Array(target)) { 860 throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); 861 } 862 if (arguments.length === 1) 863 return _compare(this, target); 864 865 if (targetStart === undefined) 866 targetStart = 0; 867 else 868 validateInt32(targetStart, 'targetStart', 0); 869 870 if (targetEnd === undefined) 871 targetEnd = target.length; 872 else 873 validateInt32(targetEnd, 'targetEnd', 0, target.length); 874 875 if (sourceStart === undefined) 876 sourceStart = 0; 877 else 878 validateInt32(sourceStart, 'sourceStart', 0); 879 880 if (sourceEnd === undefined) 881 sourceEnd = this.length; 882 else 883 validateInt32(sourceEnd, 'sourceEnd', 0, this.length); 884 885 if (sourceStart >= sourceEnd) 886 return (targetStart >= targetEnd ? 0 : -1); 887 if (targetStart >= targetEnd) 888 return 1; 889 890 return compareOffset(this, target, targetStart, sourceStart, targetEnd, 891 sourceEnd); 892}; 893 894// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, 895// OR the last index of `val` in `buffer` at offset <= `byteOffset`. 896// 897// Arguments: 898// - buffer - a Buffer to search 899// - val - a string, Buffer, or number 900// - byteOffset - an index into `buffer`; will be clamped to an int32 901// - encoding - an optional encoding, relevant if val is a string 902// - dir - true for indexOf, false for lastIndexOf 903function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { 904 validateBuffer(buffer); 905 906 if (typeof byteOffset === 'string') { 907 encoding = byteOffset; 908 byteOffset = undefined; 909 } else if (byteOffset > 0x7fffffff) { 910 byteOffset = 0x7fffffff; 911 } else if (byteOffset < -0x80000000) { 912 byteOffset = -0x80000000; 913 } 914 // Coerce to Number. Values like null and [] become 0. 915 byteOffset = +byteOffset; 916 // If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer. 917 if (NumberIsNaN(byteOffset)) { 918 byteOffset = dir ? 0 : (buffer.length || buffer.byteLength); 919 } 920 dir = !!dir; // Cast to bool. 921 922 if (typeof val === 'number') 923 return indexOfNumber(buffer, val >>> 0, byteOffset, dir); 924 925 let ops; 926 if (encoding === undefined) 927 ops = encodingOps.utf8; 928 else 929 ops = getEncodingOps(encoding); 930 931 if (typeof val === 'string') { 932 if (ops === undefined) 933 throw new ERR_UNKNOWN_ENCODING(encoding); 934 return ops.indexOf(buffer, val, byteOffset, dir); 935 } 936 937 if (isUint8Array(val)) { 938 const encodingVal = 939 (ops === undefined ? encodingsMap.utf8 : ops.encodingVal); 940 return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir); 941 } 942 943 throw new ERR_INVALID_ARG_TYPE( 944 'value', ['number', 'string', 'Buffer', 'Uint8Array'], val 945 ); 946} 947 948Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { 949 return bidirectionalIndexOf(this, val, byteOffset, encoding, true); 950}; 951 952Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { 953 return bidirectionalIndexOf(this, val, byteOffset, encoding, false); 954}; 955 956Buffer.prototype.includes = function includes(val, byteOffset, encoding) { 957 return this.indexOf(val, byteOffset, encoding) !== -1; 958}; 959 960// Usage: 961// buffer.fill(number[, offset[, end]]) 962// buffer.fill(buffer[, offset[, end]]) 963// buffer.fill(string[, offset[, end]][, encoding]) 964Buffer.prototype.fill = function fill(value, offset, end, encoding) { 965 return _fill(this, value, offset, end, encoding); 966}; 967 968function _fill(buf, value, offset, end, encoding) { 969 if (typeof value === 'string') { 970 if (offset === undefined || typeof offset === 'string') { 971 encoding = offset; 972 offset = 0; 973 end = buf.length; 974 } else if (typeof end === 'string') { 975 encoding = end; 976 end = buf.length; 977 } 978 979 const normalizedEncoding = normalizeEncoding(encoding); 980 if (normalizedEncoding === undefined) { 981 validateString(encoding, 'encoding'); 982 throw new ERR_UNKNOWN_ENCODING(encoding); 983 } 984 985 if (value.length === 0) { 986 // If value === '' default to zero. 987 value = 0; 988 } else if (value.length === 1) { 989 // Fast path: If `value` fits into a single byte, use that numeric value. 990 if (normalizedEncoding === 'utf8') { 991 const code = value.charCodeAt(0); 992 if (code < 128) { 993 value = code; 994 } 995 } else if (normalizedEncoding === 'latin1') { 996 value = value.charCodeAt(0); 997 } 998 } 999 } else { 1000 encoding = undefined; 1001 } 1002 1003 if (offset === undefined) { 1004 offset = 0; 1005 end = buf.length; 1006 } else { 1007 validateInt32(offset, 'offset', 0); 1008 // Invalid ranges are not set to a default, so can range check early. 1009 if (end === undefined) { 1010 end = buf.length; 1011 } else { 1012 validateInt32(end, 'end', 0, buf.length); 1013 } 1014 if (offset >= end) 1015 return buf; 1016 } 1017 1018 1019 if (typeof value === 'number') { 1020 // OOB check 1021 const byteLen = TypedArrayProto_byteLength.call(buf); 1022 const fillLength = end - offset; 1023 if (offset > end || fillLength + offset > byteLen) 1024 throw new ERR_BUFFER_OUT_OF_BOUNDS(); 1025 1026 TypedArrayFill.call(buf, value, offset, end); 1027 } else { 1028 const res = bindingFill(buf, value, offset, end, encoding); 1029 if (res < 0) { 1030 if (res === -1) 1031 throw new ERR_INVALID_ARG_VALUE('value', value); 1032 throw new ERR_BUFFER_OUT_OF_BOUNDS(); 1033 } 1034 } 1035 1036 return buf; 1037} 1038 1039Buffer.prototype.write = function write(string, offset, length, encoding) { 1040 // Buffer#write(string); 1041 if (offset === undefined) { 1042 return this.utf8Write(string, 0, this.length); 1043 } 1044 // Buffer#write(string, encoding) 1045 if (length === undefined && typeof offset === 'string') { 1046 encoding = offset; 1047 length = this.length; 1048 offset = 0; 1049 1050 // Buffer#write(string, offset[, length][, encoding]) 1051 } else { 1052 validateInt32(offset, 'offset', 0, this.length); 1053 1054 const remaining = this.length - offset; 1055 1056 if (length === undefined) { 1057 length = remaining; 1058 } else if (typeof length === 'string') { 1059 encoding = length; 1060 length = remaining; 1061 } else { 1062 validateInt32(length, 'length', 0, this.length); 1063 if (length > remaining) 1064 length = remaining; 1065 } 1066 } 1067 1068 if (!encoding) 1069 return this.utf8Write(string, offset, length); 1070 1071 const ops = getEncodingOps(encoding); 1072 if (ops === undefined) 1073 throw new ERR_UNKNOWN_ENCODING(encoding); 1074 return ops.write(this, string, offset, length); 1075}; 1076 1077Buffer.prototype.toJSON = function toJSON() { 1078 if (this.length > 0) { 1079 const data = new Array(this.length); 1080 for (let i = 0; i < this.length; ++i) 1081 data[i] = this[i]; 1082 return { type: 'Buffer', data }; 1083 } 1084 return { type: 'Buffer', data: [] }; 1085}; 1086 1087function adjustOffset(offset, length) { 1088 // Use Math.trunc() to convert offset to an integer value that can be larger 1089 // than an Int32. Hence, don't use offset | 0 or similar techniques. 1090 offset = MathTrunc(offset); 1091 if (offset === 0) { 1092 return 0; 1093 } 1094 if (offset < 0) { 1095 offset += length; 1096 return offset > 0 ? offset : 0; 1097 } 1098 if (offset < length) { 1099 return offset; 1100 } 1101 return NumberIsNaN(offset) ? 0 : length; 1102} 1103 1104Buffer.prototype.slice = function slice(start, end) { 1105 const srcLength = this.length; 1106 start = adjustOffset(start, srcLength); 1107 end = end !== undefined ? adjustOffset(end, srcLength) : srcLength; 1108 const newLength = end > start ? end - start : 0; 1109 return new FastBuffer(this.buffer, this.byteOffset + start, newLength); 1110}; 1111 1112function swap(b, n, m) { 1113 const i = b[n]; 1114 b[n] = b[m]; 1115 b[m] = i; 1116} 1117 1118Buffer.prototype.swap16 = function swap16() { 1119 // For Buffer.length < 128, it's generally faster to 1120 // do the swap in javascript. For larger buffers, 1121 // dropping down to the native code is faster. 1122 const len = this.length; 1123 if (len % 2 !== 0) 1124 throw new ERR_INVALID_BUFFER_SIZE('16-bits'); 1125 if (len < 128) { 1126 for (let i = 0; i < len; i += 2) 1127 swap(this, i, i + 1); 1128 return this; 1129 } 1130 return _swap16(this); 1131}; 1132 1133Buffer.prototype.swap32 = function swap32() { 1134 // For Buffer.length < 192, it's generally faster to 1135 // do the swap in javascript. For larger buffers, 1136 // dropping down to the native code is faster. 1137 const len = this.length; 1138 if (len % 4 !== 0) 1139 throw new ERR_INVALID_BUFFER_SIZE('32-bits'); 1140 if (len < 192) { 1141 for (let i = 0; i < len; i += 4) { 1142 swap(this, i, i + 3); 1143 swap(this, i + 1, i + 2); 1144 } 1145 return this; 1146 } 1147 return _swap32(this); 1148}; 1149 1150Buffer.prototype.swap64 = function swap64() { 1151 // For Buffer.length < 192, it's generally faster to 1152 // do the swap in javascript. For larger buffers, 1153 // dropping down to the native code is faster. 1154 const len = this.length; 1155 if (len % 8 !== 0) 1156 throw new ERR_INVALID_BUFFER_SIZE('64-bits'); 1157 if (len < 192) { 1158 for (let i = 0; i < len; i += 8) { 1159 swap(this, i, i + 7); 1160 swap(this, i + 1, i + 6); 1161 swap(this, i + 2, i + 5); 1162 swap(this, i + 3, i + 4); 1163 } 1164 return this; 1165 } 1166 return _swap64(this); 1167}; 1168 1169Buffer.prototype.toLocaleString = Buffer.prototype.toString; 1170 1171let transcode; 1172if (internalBinding('config').hasIntl) { 1173 const { 1174 icuErrName, 1175 transcode: _transcode 1176 } = internalBinding('icu'); 1177 1178 // Transcodes the Buffer from one encoding to another, returning a new 1179 // Buffer instance. 1180 transcode = function transcode(source, fromEncoding, toEncoding) { 1181 if (!isUint8Array(source)) { 1182 throw new ERR_INVALID_ARG_TYPE('source', 1183 ['Buffer', 'Uint8Array'], source); 1184 } 1185 if (source.length === 0) return Buffer.alloc(0); 1186 1187 fromEncoding = normalizeEncoding(fromEncoding) || fromEncoding; 1188 toEncoding = normalizeEncoding(toEncoding) || toEncoding; 1189 const result = _transcode(source, fromEncoding, toEncoding); 1190 if (typeof result !== 'number') 1191 return result; 1192 1193 const code = icuErrName(result); 1194 // eslint-disable-next-line no-restricted-syntax 1195 const err = new Error(`Unable to transcode Buffer [${code}]`); 1196 err.code = code; 1197 err.errno = result; 1198 throw err; 1199 }; 1200} 1201 1202module.exports = { 1203 Buffer, 1204 SlowBuffer, 1205 transcode, 1206 // Legacy 1207 kMaxLength, 1208 kStringMaxLength 1209}; 1210 1211ObjectDefineProperties(module.exports, { 1212 constants: { 1213 configurable: false, 1214 enumerable: true, 1215 value: constants 1216 }, 1217 INSPECT_MAX_BYTES: { 1218 configurable: true, 1219 enumerable: true, 1220 get() { return INSPECT_MAX_BYTES; }, 1221 set(val) { INSPECT_MAX_BYTES = val; } 1222 } 1223}); 1224