# safe-buffer 中文文档

规范地址：https://npmcn.com/package/safe-buffer/

版本：5\.2\.1
npm 元数据更新时间：2023-07-10T23:16:22.564Z
中文译文更新时间：2026-11-04T11:24:17.420Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/safe-buffer
原文对照：https://npmcn.com/package/safe-buffer/?lang=original
项目主页：https://github.com/feross/safe-buffer
源码仓库：https://github.com/feross/safe-buffer

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：32.1 kB，5 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- 首次发布：2016-01-13T04:36:59.750Z
- 最新版本发布：2020-05-10T16:37:30.776Z
- 近 30 天下载量：1319706407（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：11（近 12 个月 0 个）

## 中文简介

更安全的Node.js缓冲API

## 安装

```sh
npm install safe-buffer
```

也可以使用：`pnpm add safe-buffer`、`yarn add safe-buffer`、`bun add safe-buffer`

## README

# safe-buffer [![travis](https://img.shields.io/travis/feross/safe-buffer/master.svg)](https://travis-ci.org/feross/safe-buffer) [![npm](https://img.shields.io/npm/v/safe-buffer.svg)](https://npmjs.org/package/safe-buffer) [![downloads](https://img.shields.io/npm/dm/safe-buffer.svg)](https://npmjs.org/package/safe-buffer) [![javascript style guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com/)

#### 更安全的Node.js缓冲API

**使用新的Node.js Buffer api (`Buffer.from`， `Buffer.alloc`， `Buffer.allocUnsafe`， `Buffer.allocUnsafeSlow`)在所有版本的Node.js中。**

**在可用时使用内置实现。**

## 安装

```
npm install safe-buffer
```

## 用法

这个包的目标是为node.js提供一个安全的替代品 `Buffer`。

这是一个临时替代品 `Buffer`。加1就可以了 `require` 行 node.js模块的顶部：

```js
var Buffer = require('safe-buffer').Buffer

// Existing buffer code will continue to work without issues:

new Buffer('hey', 'utf8')
new Buffer([1, 2, 3], 'utf8')
new Buffer(obj)
new Buffer(16) // create an uninitialized buffer (potentially unsafe)

// But you can use these new explicit APIs to make clear what you want:

Buffer.from('hey', 'utf8') // convert from many types to a Buffer
Buffer.alloc(16) // create a zero-filled buffer (safe)
Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe)
```

## api

### 类方法：Buffer.from（array）

-   `array` {数组}

分配一个新的 `Buffer` 使用一个 `array` 八位字节。

```js
const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]);
  // creates a new Buffer containing ASCII bytes
  // ['b','u','f','f','e','r']
```

一个 `TypeError` 会被抛出 `array` 不是。 `Array`。

### 类方法：Buffer.from（arrayBuffer\[, byteOffset\[, length\]\]）

-   `arrayBuffer` {ArrayBuffer} `.buffer` a的性质 `TypedArray` 或 一个 `new ArrayBuffer()`
-   `byteOffset` {}数量默认值: `0`
-   `length` {}数量默认值: `arrayBuffer.length - byteOffset`

的引用 `.buffer` a的性质 `TypedArray` 实例, 新创建的 `Buffer` 将共享与 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>
```

可选 `byteOffset` 和 `length` 参数指定的内存范围 这个 `arrayBuffer` 这将由 `Buffer`。

```js
const ab = new ArrayBuffer(10);
const buf = Buffer.from(ab, 0, 2);
console.log(buf.length);
  // Prints: 2
```

一个 `TypeError` 会被抛出 `arrayBuffer` 不是。 `ArrayBuffer`。

### 类方法：buffer .from（buffer）

-   `buffer` {缓冲}

复制传递的 `buffer` 数据放到新的 `Buffer` 实例。

```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)
```

一个 `TypeError` 会被抛出 `buffer` 不是。 `Buffer`。

### 类方法：Buffer.from（str\[, encoding\]）

-   `str` {String}要编码的字符串。
-   `encoding` {String}使用的编码，默认值： `'utf8'`

创建一个新的 `Buffer` 包含给定的JavaScript字符串 `str`。如果 提供, `encoding` 参数标识字符编码。 如未提供， `encoding` 默认为 `'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
```

一个 `TypeError` 会被抛出 `str` 不是字符串。

### 类方法：Buffer。Alloc （size\[, fill\[, encoding\]\]）

-   `size` {}数量
-   `fill` {}的值默认值: `undefined`
-   `encoding` {}字符串默认值: `utf8`

分配一个新的 `Buffer` 的 `size` 字节。如果 `fill` 是 `undefined`, `Buffer` 将 _zero-filled_。

```js
const buf = Buffer.alloc(5);
console.log(buf);
  // <Buffer 00 00 00 00 00>
```

这个 `size` 必须小于或等于 `require('buffer').kMaxLength` (在64位架构上， `kMaxLength` 是 `(2^31)-1`）. 否则，a \[`RangeError`\[\]被抛出。一个零长度的缓冲区可以 创建，如果 `size` 指定小于或等于0。

如果 `fill` ，则分配的 `Buffer` 将通过调用 `buf.fill(fill)`。参见\[`buf.fill()`\[\]获取更多信息。

```js
const buf = Buffer.alloc(5, 'a');
console.log(buf);
  // <Buffer 61 61 61 61 61>
```

如果两个 `fill` 和 `encoding` 指定，分配 `Buffer` 将 通过调用初始化 `buf.fill(fill, encoding)`。例如:

```js
const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
console.log(buf);
  // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
```

调用 `Buffer.alloc(size)` 会比另一种选择慢得多吗 `Buffer.allocUnsafe(size)` 但确保了新创建的 `Buffer` 实例 内容将 _不要包含敏感数据_。

一个 `TypeError` 会被抛出 `size` 不是一个数字。

### 类方法：Buffer.allocUnsafe（size）

-   `size` {}数量

分配一个新的 _non-zero-filled_ `Buffer` 的 `size` 字节。这个 `size` 必须 的值小于或等于 `require('buffer').kMaxLength` (在64位 架构, `kMaxLength` 是 `(2^31)-1`）. 否则，a \[`RangeError`\] \[\] 抛出。将创建一个零长度缓冲区 `size` 小于或等于 指定0。

的底层内存 `Buffer` 以这种方式创建的实例是 _不 初始化_。新创建的内容 `Buffer` 是未知的 _可能包含敏感数据_。使用\[`buf.fill(0)`\[\]初始化这样的 `Buffer` 实例归零。

```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>
```

一个 `TypeError` 会被抛出 `size` 不是一个数字。

请注意 `Buffer` 模块预分配一个内部的 `Buffer` 的实例 大小 `Buffer.poolSize` 它被用作快速分配new的池 `Buffer` 使用以下命令创建的实例 `Buffer.allocUnsafe(size)` (以及被弃用的 `new Buffer(size)` 构造函数)仅当 `size` 是小于还是等于 `Buffer.poolSize >> 1` (楼 `Buffer.poolSize` 除以2)。默认的 的价值 `Buffer.poolSize` 是 `8192` 但是可以修改。

使用这种预分配的内部内存池是两者之间的关键区别 调用 `Buffer.alloc(size, fill)` vs。 `Buffer.allocUnsafe(size).fill(fill)`。 具体地说, `Buffer.alloc(size, fill)` 将 _从来没有_ 使用内部缓冲区 池, `Buffer.allocUnsafe(size).fill(fill)` _将_ 使用内部 缓冲池 `size` 是小于还是等于1 / 2 `Buffer.poolSize`。这个 差异是微妙的，但当应用程序需要 额外的性能 `Buffer.allocUnsafe(size)` 提供了。

### 类方法：Buffer.allocUnsafeSlow（size）

-   `size` {}数量

分配一个新的 _non-zero-filled_ 要,没有缓冲的、生命期 `Buffer` 的 `size` 字节。这个 `size` 必须小于或等于 `require('buffer').kMaxLength` (在64位架构上， `kMaxLength` 是 `(2^31)-1`）. 否则，a \[`RangeError`\[\]被抛出。一个零长度的缓冲区可以 创建，如果 `size` 指定小于或等于0。

的底层内存 `Buffer` 以这种方式创建的实例是 _不 初始化_。新创建的内容 `Buffer` 是未知的 _可能包含敏感数据_。使用\[`buf.fill(0)`\[\]初始化这样的 `Buffer` 实例归零。

当使用 `Buffer.allocUnsafe()` 分配新的 `Buffer` 情况下, 默认情况下，4KB以下的分配是从单个预分配的分区中切片的 `Buffer`。这允许应用程序避免垃圾收集开销 创建许多单独分配的缓冲区。这种方法改进了 通过消除跟踪和清理的需要来提高性能和内存使用 许多 `Persistent` 对象。

然而，在开发人员可能需要保留一小块的情况下 从内存池中取出内存的时间不确定，这可能是合适的 来创建一个未池化的Buffer实例 `Buffer.allocUnsafeSlow()` 然后 把相关的部分抄下来。

```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);
});
```

使用 `Buffer.allocUnsafeSlow()` 应该作为最后的手段吗 _后_ 一个开发人员在他们的应用程序中发现了不适当的内存保留。

一个 `TypeError` 会被抛出 `size` 不是一个数字。

### 其他的

剩下的 `Buffer` API与node.js中的完全相同。 [请参阅文档](https://nodejs.org/api/buffer.html)。

## 相关链接

-   [Node.js问题：Buffer（number）不安全](https://github.com/nodejs/node/issues/4660)
-   [Node.js增强建议：Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer（）软弃用](https://github.com/nodejs/node-eps/pull/4)

## 为什么 `Buffer` 不安全吗?

今天，node.js `Buffer` 构造函数被重载以处理许多不同的参数 类型等 `String`， `Array`， `Object`， `TypedArrayView` （`Uint8Array`等), `ArrayBuffer`，而且 `Number`。

该API是为了方便而优化的：您可以向它抛出任何类型，它将尝试这样做 你想要什么。

因为Buffer构造函数非常强大，你经常会看到这样的代码：

```js
// Convert UTF-8 strings to hex
function toHex (str) {
  return new Buffer(str).toString('hex')
}
```

_**但是如果 `toHex` 是用 `Number` 论点吗?**_

### 远程内存公开

如果攻击者可以使您的程序调用 `Buffer` 的构造函数 `Number` 参数，然后他们可以让它从node.js进程中分配未初始化的内存。 这可能会泄露TLS私钥、用户数据或数据库密码。

当 `Buffer` 构造函数传递给 `Number` 参数时，它返回一个 **未初始化** 指定的内存块 `size`。当你创建 `Buffer` 就像 这个,你 **必须** 在将内容返回给用户之前覆盖它。

从 [node . js文件](https://nodejs.org/api/buffer.html#buffer_new_buffer_size)：

> `new Buffer(size)`
> 
> -   `size` 数量
> 
> 的底层内存 `Buffer` 以这种方式创建的实例不会初始化。 **新创建的内容 `Buffer` 是否未知且可能含有敏感物质 数据。** 使用 `buf.fill(0)` 将Buffer初始化为0。

（强调我们自己的观点。）

每当程序员打算创建一个未初始化的 `Buffer` 你经常会看到代码 是这样的:

```js
var buf = new Buffer(16)

// Immediately overwrite the uninitialized buffer with data from another buffer
for (var i = 0; i < buf.length; i++) {
  buf[i] = otherBuf[i]
}
```

### 这在实际代码中会成为问题吗？

是。在a中忘记检查变量的类型是非常常见的 动态类型语言，如JavaScript。

通常，假设错误的类型的后果是您的程序崩溃 未捕获异常。但是忘记检查参数类型的失败模式 这个 `Buffer` 构造函数更具灾难性。

下面是一个易受攻击的服务示例，该服务接受JSON有效负载并将其转换为 十六进制:

```js
// Take a JSON payload {str: "some string"} and convert it to hex
var server = http.createServer(function (req, res) {
  var data = ''
  req.setEncoding('utf8')
  req.on('data', function (chunk) {
    data += chunk
  })
  req.on('end', function () {
    var body = JSON.parse(data)
    res.end(new Buffer(body.str).toString('hex'))
  })
})

server.listen(8080)
```

在这个例子中，http客户端只需要发送：

```json
{
  "str": 1000
}
```

它将从服务器获得1000字节未初始化的内存。

这是一个非常严重的错误。在严重程度上和 [心脏出血bug](http://heartbleed.com/) 允许公开OpenSSL进程 内存被远程攻击者攻击。

### 哪些真实世界的软件包是易受攻击的？

#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht)

[马赛厄斯我校](https://github.com/mafintosh) 和我 （[Feross Aboukhadijeh](http://feross.org/))在我们自己的一个软件包中发现了这个问题， [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht)。这个漏洞将允许 任何人在互联网上发送一系列的消息给用户 `bittorrent-dht` 并获得 它们每次显示来自node.js进程的未初始化内存的20个字节。

这是 [提交](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8) 这就解决了问题。我们发布了一个新的固定版本，创建了一个 [节点安全项目披露](https://nodesecurity.io/advisories/68)，弃用一切 NPM上的易受攻击版本，因此用户将收到升级到新版本的警告。

#### [`ws`](https://www.npmjs.com/package/ws)

这让我们怀疑是否还有其他易受攻击的软件包。果然，在短时间内 一段时间以来，我们发现了同样的问题 [`ws`](https://www.npmjs.com/package/ws), 在node.js中最流行的WebSocket实现。

如果调用了某些api `Number` 参数而不是 `String` 或 `Buffer` 作为 预期，那么未初始化的服务器内存将被公开给远程对等端。

这些是易受攻击的方法：

```js
socket.send(number)
socket.ping(number)
socket.pong(number)
```

下面是一个带有回显功能的易受攻击的套接字服务器：

```js
server.on('connection', function (socket) {
  socket.on('message', function (message) {
    message = JSON.parse(message)
    if (message.type === 'echo') {
      socket.send(message.data) // send back the user's message
    }
  })
})
```

`socket.send(number)` 在服务器上调用，将公开服务器内存。

这是 [释放](https://github.com/websockets/ws/releases/tag/1.0.1) 问题在哪里？ 是固定的，并有更详细的解释。道具 [Arnout Kazemier](https://github.com/3rd-Eden) 为了快速解决问题。这是 [节点安全项目披露](https://nodesecurity.io/advisories/67)。

### 解决办法是什么？

重要的是，node.js提供了一种快速获取内存的方法，否则对性能至关重要 应用程序将不必要地变得慢很多。

但我们需要更好的方法 _表明我们的意图_ 作为程序员。 **当我们需要的时候 未初始化的内存，我们应该显式请求它。**

敏感的功能不应该被打包到开发人员友好的API中 接受许多不同的类型。这种类型的API鼓励懒惰的传递实践 在没有仔细检查类型的情况下导入变量。

#### 一个新的API： `Buffer.allocUnsafe(number)`

使用未初始化内存创建缓冲区的功能应该是另一个功能的一部分 API。我们建议 `Buffer.allocUnsafe(number)`。这样，它就不是API的一部分 经常获取传递给它的各种不同类型的用户输入。

```js
var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory!

// Immediately overwrite the uninitialized buffer with data from another buffer
for (var i = 0; i < buf.length; i++) {
  buf[i] = otherBuf[i]
}
```

### 我们如何修复node.js核心？

我们发送 [一个PR到node.js核心](https://github.com/nodejs/node/pull/4514) (合并 `semver-major`)，就一个案件进行辩护；

```js
var str = 16
new Buffer(str, 'utf8')
```

在这种情况下，这意味着程序员希望第一个参数是a 字符串，因为它们传递了一个编码作为第二个参数。今天，node.js将分配 的情况下未初始化的内存 `new Buffer(number, encoding)`，这可能不是 程序员的意图。

但这只是部分解决方案，因为如果程序员这样做 `new Buffer(variable)` (没有一个 `encoding` 参数)，没有办法知道他们的意图。如果 `variable` 有时是一个数字，那么有时会返回未初始化的内存。

### 真正的长期解决方案是什么？

我们可以弃用和删除 `new Buffer(number)` 和使用 `Buffer.allocUnsafe(number)` 当 我们需要未初始化的内存。但这将破坏数千个包。

~我们认为最好的解决方案是：~

~1\. 改变 `new Buffer(number)` 返回安全的、归零的内存~

~2\. 创建一个用于创建未初始化缓冲区的新API。我们建议: `Buffer.allocUnsafe(number)`~

#### 更新

我们现在支持添加三个新的api：

-   `Buffer.from(value)` -从任何类型转换为缓冲区
-   `Buffer.alloc(size)` -创建一个零填充缓冲区
-   `Buffer.allocUnsafe(size)` -创建一个给定大小的未初始化缓冲区

这就解决了影响的核心问题 `ws` 和 `bittorrent-dht` 这是 `Buffer(variable)` 被骗接受一个数字参数。

通过这种方式，现有的代码可以继续工作，而对npm生态系统的影响将会减小 最小的。随着时间的推移，npm维护者可以将性能关键型代码迁移使用 `Buffer.allocUnsafe(number)` 而不是 `new Buffer(number)`。

### 结论

我们认为这是一个严重的设计问题 `Buffer` 今天的API。它 通过将高风险功能放入方便的API中来促进不安全的软件 友好的“开发者人体工程学”。

这不仅仅是一个理论练习，因为我们在一些 最流行的NPM包。

幸运的是，今天有一个简单的解决办法。使用 `safe-buffer` 代替 `buffer`。

```js
var Buffer = require('safe-buffer').Buffer
```

最终，我们希望node.js核心可以切换到这种新的、更安全的行为。我们相信 对生态系统的影响将是最小的，因为这不是一个突破性的变化。 维护良好的、流行的软件包将被更新以使用 `Buffer.alloc` 很快,而 旧的、不安全的包将神奇地从这种攻击向量中变得安全。

## 链接

-   [如果同时传递length和enc，则PR: buffer: throw](https://github.com/nodejs/node/pull/4514)
-   [节点安全项目披露 `ws`](https://nodesecurity.io/advisories/67)
-   [节点安全项目披露`bittorrent-dht`](https://nodesecurity.io/advisories/68)

## 信贷

最初的问题 `bittorrent-dht` （[信息披露](https://nodesecurity.io/advisories/68)), `ws` （[信息披露](https://nodesecurity.io/advisories/67))被 [马赛厄斯我校](https://github.com/mafintosh) 和 [Feross Aboukhadijeh](http://feross.org/)。

多亏了 [亚当·鲍德温](https://github.com/evilpacket) 帮助揭露这些问题 以及他的工作 [节点安全项目](https://nodesecurity.io/)。

多亏了 [约翰Hiesey](https://github.com/jhiesey) 校对本自述文件和 审核代码。

## 许可证

麻省理工学院。版权(C) [Feross Aboukhadijeh](http://feross.org/)

## 常见问题

### safe-buffer 是什么？

更安全的Node\.js缓冲API

### 如何安装 safe-buffer？

在项目目录运行 npm install safe-buffer，或使用 pnpm add / yarn add / bun add。

### safe-buffer 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### safe-buffer 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### safe-buffer 可以商用吗？

safe-buffer 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### safe-buffer 的下载量有多少？

根据 npm 官方下载统计，safe-buffer 在 2026/10/05 – 2026/11/03 这 30 天内被下载 1,319,706,407 次，日均约 43,990,214 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### safe-buffer 还在维护吗？

最新版本 5\.2\.1 发布于 2020/05/11（6 年前）；至今共发布 11 个版本，其中过去 12 个月发布了 0 个；首次发布于 2016/01/13。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

