safe-buffer
Advanced tools
Comparing version 3.0.0 to 4.0.0
58
index.js
module.exports = SafeBuffer | ||
module.exports.Buffer = SafeBuffer | ||
function SafeBuffer (value, encoding) { | ||
return Buffer(value, encoding) | ||
var SlowBuffer = require('buffer').SlowBuffer | ||
function SafeBuffer (arg, encodingOrOffset, length) { | ||
return Buffer(arg, encodingOrOffset, length) | ||
} | ||
// Copy static functions | ||
Object.keys(Buffer).forEach(function (prop) { | ||
@@ -12,23 +15,46 @@ SafeBuffer[prop] = Buffer[prop] | ||
SafeBuffer.from = function (value, encoding) { | ||
if (typeof value === 'number') { | ||
throw new TypeError('Argument must not be a number') | ||
if (!SafeBuffer.from) { | ||
SafeBuffer.from = function (arg, encodingOrOffset, length) { | ||
if (typeof value === 'number') { | ||
throw new TypeError('Argument must not be a number') | ||
} | ||
return Buffer(arg, encodingOrOffset, length) | ||
} | ||
return Buffer(value, encoding) | ||
} | ||
SafeBuffer.alloc = function (size) { | ||
if (typeof size !== 'number') { | ||
throw new TypeError('Argument must be a number') | ||
if (!SafeBuffer.alloc) { | ||
SafeBuffer.alloc = function (size, fill, encoding) { | ||
if (typeof size !== 'number') { | ||
throw new TypeError('Argument must be a number') | ||
} | ||
var buf = Buffer(size) | ||
if (fill !== undefined) { | ||
if (typeof encoding === 'string') { | ||
buf.fill(fill, encoding) | ||
} else { | ||
buf.fill(fill) | ||
} | ||
} else { | ||
buf.fill(0) | ||
} | ||
return buf | ||
} | ||
var buffer = Buffer(size) | ||
buffer.fill(0) | ||
return buffer | ||
} | ||
SafeBuffer.allocRaw = function (size) { | ||
if (typeof size !== 'number') { | ||
throw new TypeError('Argument must be a number') | ||
if (!SafeBuffer.allocUnsafe) { | ||
SafeBuffer.allocUnsafe = function (size) { | ||
if (typeof size !== 'number') { | ||
throw new TypeError('Argument must be a number') | ||
} | ||
return Buffer(size) | ||
} | ||
return Buffer(size) | ||
} | ||
if (!SafeBuffer.allocUnsafeSlow) { | ||
SafeBuffer.allocUnsafeSlow = function (size) { | ||
if (typeof size !== 'number') { | ||
throw new TypeError('Argument must be a number') | ||
} | ||
return SlowBuffer(size) | ||
} | ||
} |
{ | ||
"name": "safe-buffer", | ||
"description": "Safer Node.js Buffer API", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"author": { | ||
@@ -15,3 +15,3 @@ "name": "Feross Aboukhadijeh", | ||
"devDependencies": { | ||
"standard": "^5.0.0", | ||
"standard": "^7.0.0", | ||
"tape": "^4.0.0", | ||
@@ -18,0 +18,0 @@ "zuul": "^3.0.0" |
277
README.md
@@ -5,2 +5,7 @@ # safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][npm-url] | ||
**Use the new Node.js v6 Buffer APIs (`Buffer.from`, `Buffer.alloc`, | ||
`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in Node.js v0.10 and newer.** | ||
**Uses the built-in implementations when available.** | ||
[travis-image]: https://img.shields.io/travis/feross/safe-buffer.svg | ||
@@ -39,3 +44,3 @@ [travis-url]: https://travis-ci.org/feross/safe-buffer | ||
Buffer.alloc(16) // create a zero-filled buffer (safe) | ||
Buffer.allocRaw(16) // create an uninitialized buffer (potentially unsafe) | ||
Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe) | ||
``` | ||
@@ -45,21 +50,253 @@ | ||
### `Buffer.from(value, [encoding])` | ||
### Class Method: Buffer.from(array) | ||
<!-- YAML | ||
added: v3.0.0 | ||
--> | ||
Creates a new Buffer containing the given `value`. `value` can be an `Array`, `Buffer`, | ||
`ArrayBuffer`, `string`, or `TypedArrayView` (`Uint8Array`, etc.). If `value` is a string, | ||
an `encoding` parameter can also be provided to identify the string character encoding. | ||
* `array` {Array} | ||
### `Buffer.alloc(size)` | ||
Allocates a new `Buffer` using an `array` of octets. | ||
Allocate a zero-filled buffer with the given `size`. This is safe and recommended to use. | ||
```js | ||
const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]); | ||
// creates a new Buffer containing ASCII bytes | ||
// ['b','u','f','f','e','r'] | ||
``` | ||
### `Buffer.allocRaw(size)` | ||
A `TypeError` will be thrown if `array` is not an `Array`. | ||
Allocate an uninitialized buffer with the given `size`. This is potentially unsafe. The | ||
underlying memory for `Buffer` instances created in this way is not initialized. The | ||
contents are unknown and could contain sensitive data. The buffer must be overwritten | ||
before it's used. | ||
### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) | ||
<!-- YAML | ||
added: v5.10.0 | ||
--> | ||
### more methods | ||
* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or | ||
a `new ArrayBuffer()` | ||
* `byteOffset` {Number} Default: `0` | ||
* `length` {Number} Default: `arrayBuffer.length - byteOffset` | ||
When passed a reference to the `.buffer` property of a `TypedArray` instance, | ||
the newly created `Buffer` will share the same allocated memory as the | ||
TypedArray. | ||
```js | ||
const arr = new Uint16Array(2); | ||
arr[0] = 5000; | ||
arr[1] = 4000; | ||
const buf = Buffer.from(arr.buffer); // shares the memory with arr; | ||
console.log(buf); | ||
// Prints: <Buffer 88 13 a0 0f> | ||
// changing the TypedArray changes the Buffer also | ||
arr[1] = 6000; | ||
console.log(buf); | ||
// Prints: <Buffer 88 13 70 17> | ||
``` | ||
The optional `byteOffset` and `length` arguments specify a memory range within | ||
the `arrayBuffer` that will be shared by the `Buffer`. | ||
```js | ||
const ab = new ArrayBuffer(10); | ||
const buf = Buffer.from(ab, 0, 2); | ||
console.log(buf.length); | ||
// Prints: 2 | ||
``` | ||
A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`. | ||
### Class Method: Buffer.from(buffer) | ||
<!-- YAML | ||
added: v3.0.0 | ||
--> | ||
* `buffer` {Buffer} | ||
Copies the passed `buffer` data onto a new `Buffer` instance. | ||
```js | ||
const buf1 = Buffer.from('buffer'); | ||
const buf2 = Buffer.from(buf1); | ||
buf1[0] = 0x61; | ||
console.log(buf1.toString()); | ||
// 'auffer' | ||
console.log(buf2.toString()); | ||
// 'buffer' (copy is not changed) | ||
``` | ||
A `TypeError` will be thrown if `buffer` is not a `Buffer`. | ||
### Class Method: Buffer.from(str[, encoding]) | ||
<!-- YAML | ||
added: v5.10.0 | ||
--> | ||
* `str` {String} String to encode. | ||
* `encoding` {String} Encoding to use, Default: `'utf8'` | ||
Creates a new `Buffer` containing the given JavaScript string `str`. If | ||
provided, the `encoding` parameter identifies the character encoding. | ||
If not provided, `encoding` defaults to `'utf8'`. | ||
```js | ||
const buf1 = Buffer.from('this is a tést'); | ||
console.log(buf1.toString()); | ||
// prints: this is a tést | ||
console.log(buf1.toString('ascii')); | ||
// prints: this is a tC)st | ||
const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); | ||
console.log(buf2.toString()); | ||
// prints: this is a tést | ||
``` | ||
A `TypeError` will be thrown if `str` is not a string. | ||
### Class Method: Buffer.alloc(size[, fill[, encoding]]) | ||
<!-- YAML | ||
added: v5.10.0 | ||
--> | ||
* `size` {Number} | ||
* `fill` {Value} Default: `undefined` | ||
* `encoding` {String} Default: `utf8` | ||
Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the | ||
`Buffer` will be *zero-filled*. | ||
```js | ||
const buf = Buffer.alloc(5); | ||
console.log(buf); | ||
// <Buffer 00 00 00 00 00> | ||
``` | ||
The `size` must be less than or equal to the value of | ||
`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is | ||
`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will | ||
be created if a `size` less than or equal to 0 is specified. | ||
If `fill` is specified, the allocated `Buffer` will be initialized by calling | ||
`buf.fill(fill)`. See [`buf.fill()`][] for more information. | ||
```js | ||
const buf = Buffer.alloc(5, 'a'); | ||
console.log(buf); | ||
// <Buffer 61 61 61 61 61> | ||
``` | ||
If both `fill` and `encoding` are specified, the allocated `Buffer` will be | ||
initialized by calling `buf.fill(fill, encoding)`. For example: | ||
```js | ||
const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); | ||
console.log(buf); | ||
// <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64> | ||
``` | ||
Calling `Buffer.alloc(size)` can be significantly slower than the alternative | ||
`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance | ||
contents will *never contain sensitive data*. | ||
A `TypeError` will be thrown if `size` is not a number. | ||
### Class Method: Buffer.allocUnsafe(size) | ||
<!-- YAML | ||
added: v5.10.0 | ||
--> | ||
* `size` {Number} | ||
Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must | ||
be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit | ||
architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is | ||
thrown. A zero-length Buffer will be created if a `size` less than or equal to | ||
0 is specified. | ||
The underlying memory for `Buffer` instances created in this way is *not | ||
initialized*. The contents of the newly created `Buffer` are unknown and | ||
*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such | ||
`Buffer` instances to zeroes. | ||
```js | ||
const buf = Buffer.allocUnsafe(5); | ||
console.log(buf); | ||
// <Buffer 78 e0 82 02 01> | ||
// (octets will be different, every time) | ||
buf.fill(0); | ||
console.log(buf); | ||
// <Buffer 00 00 00 00 00> | ||
``` | ||
A `TypeError` will be thrown if `size` is not a number. | ||
Note that the `Buffer` module pre-allocates an internal `Buffer` instance of | ||
size `Buffer.poolSize` that is used as a pool for the fast allocation of new | ||
`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated | ||
`new Buffer(size)` constructor) only when `size` is less than or equal to | ||
`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default | ||
value of `Buffer.poolSize` is `8192` but can be modified. | ||
Use of this pre-allocated internal memory pool is a key difference between | ||
calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. | ||
Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer | ||
pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal | ||
Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The | ||
difference is subtle but can be important when an application requires the | ||
additional performance that `Buffer.allocUnsafe(size)` provides. | ||
### Class Method: Buffer.allocUnsafeSlow(size) | ||
<!-- YAML | ||
added: v5.10.0 | ||
--> | ||
* `size` {Number} | ||
Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The | ||
`size` must be less than or equal to the value of | ||
`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is | ||
`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will | ||
be created if a `size` less than or equal to 0 is specified. | ||
The underlying memory for `Buffer` instances created in this way is *not | ||
initialized*. The contents of the newly created `Buffer` are unknown and | ||
*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such | ||
`Buffer` instances to zeroes. | ||
When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, | ||
allocations under 4KB are, by default, sliced from a single pre-allocated | ||
`Buffer`. This allows applications to avoid the garbage collection overhead of | ||
creating many individually allocated Buffers. This approach improves both | ||
performance and memory usage by eliminating the need to track and cleanup as | ||
many `Persistent` objects. | ||
However, in the case where a developer may need to retain a small chunk of | ||
memory from a pool for an indeterminate amount of time, it may be appropriate | ||
to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then | ||
copy out the relevant bits. | ||
```js | ||
// need to keep around a few small chunks of memory | ||
const store = []; | ||
socket.on('readable', () => { | ||
const data = socket.read(); | ||
// allocate for retained data | ||
const sb = Buffer.allocUnsafeSlow(10); | ||
// copy the data into the new allocation | ||
data.copy(sb, 0, 0, 10); | ||
store.push(sb); | ||
}); | ||
``` | ||
Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after* | ||
a developer has observed undue memory retention in their applications. | ||
A `TypeError` will be thrown if `size` is not a number. | ||
### All the Rest | ||
The rest of the `Buffer` API is exactly the same as in node.js. | ||
@@ -239,10 +476,10 @@ [See the docs](https://nodejs.org/api/buffer.html). | ||
#### A new API: `Buffer.allocRaw(number)` | ||
#### A new API: `Buffer.allocUnsafe(number)` | ||
The functionality of creating buffers with uninitialized memory should be part of another | ||
API. We propose `Buffer.allocRaw(number)`. This way, it's not part of an API that | ||
API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that | ||
frequently gets user input of all sorts of different types passed into it. | ||
```js | ||
var buf = Buffer.allocRaw(16) // careful, uninitialized memory! | ||
var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory! | ||
@@ -277,3 +514,3 @@ // Immediately overwrite the uninitialized buffer with data from another buffer | ||
We could deprecate and remove `new Buffer(number)` and use `Buffer.allocRaw(number)` when | ||
We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when | ||
we need uninitialized memory. But that would break 1000s of packages. | ||
@@ -285,3 +522,3 @@ | ||
~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocRaw(number)`~~ | ||
~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~ | ||
@@ -294,3 +531,3 @@ #### Update | ||
- `Buffer.alloc(size)` - create a zero-filled buffer | ||
- `Buffer.allocRaw(size)` - create an uninitialized buffer with given size | ||
- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size | ||
@@ -302,3 +539,3 @@ This solves the core problem that affected `ws` and `bittorrent-dht` which is | ||
minimal. Over time, npm maintainers can migrate performance-critical code to use | ||
`Buffer.allocRaw(number)` instead of `new Buffer(number)`. | ||
`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`. | ||
@@ -305,0 +542,0 @@ |
14
test.js
@@ -42,4 +42,4 @@ var test = require('tape') | ||
test('SafeBuffer.allocRaw(number)', function (t) { | ||
var buf = SafeBuffer.allocRaw(100) // unitialized memory | ||
test('SafeBuffer.allocUnsafe(number)', function (t) { | ||
var buf = SafeBuffer.allocUnsafe(100) // unitialized memory | ||
t.equal(buf.length, 100) | ||
@@ -51,15 +51,15 @@ t.equal(SafeBuffer.isBuffer(buf), true) | ||
test('SafeBuffer.allocRaw() throws with non-number types', function (t) { | ||
test('SafeBuffer.allocUnsafe() throws with non-number types', function (t) { | ||
t.plan(4) | ||
t.throws(function () { | ||
SafeBuffer.allocRaw('hey') | ||
SafeBuffer.allocUnsafe('hey') | ||
}) | ||
t.throws(function () { | ||
SafeBuffer.allocRaw('hey', 'utf8') | ||
SafeBuffer.allocUnsafe('hey', 'utf8') | ||
}) | ||
t.throws(function () { | ||
SafeBuffer.allocRaw([1, 2, 3]) | ||
SafeBuffer.allocUnsafe([1, 2, 3]) | ||
}) | ||
t.throws(function () { | ||
SafeBuffer.allocRaw({}) | ||
SafeBuffer.allocUnsafe({}) | ||
}) | ||
@@ -66,0 +66,0 @@ }) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25109
122
582