Buffer.from()、Buffer.alloc() 和 Buffer.allocUnsafe()


Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe()

在 Node.js 6.0.0 之前的版本中,Buffer 实例是使用 Buffer 构造函数创建的,该函数会根据提供的参数不同而以不同的方式分配返回的 Buffer

【In versions of Node.js prior to 6.0.0, Buffer instances were created using the Buffer constructor function, which allocates the returned Buffer differently based on what arguments are provided:】

  • 将一个数字作为 Buffer() 的第一个参数传入(例如 new Buffer(10))会分配一个指定大小的新 Buffer 对象。在 Node.js 8.0.0 之前,为此类 Buffer 实例分配的内存 不会 被初始化,并且 可能包含敏感数据。此类 Buffer 实例 必须 随后通过使用 buf.fill(0) 或在从 Buffer 读取数据之前写入整个 Buffer 来初始化。虽然这种行为是 有意的 以提高性能,但开发经验表明,需要更明确地区分创建快速但未初始化的 Buffer 与创建较慢但更安全的 Buffer。自 Node.js 8.0.0 起,Buffer(num)new Buffer(num) 会返回具有初始化内存的 Buffer
  • 将字符串、数组或 Buffer 作为第一个参数传入,会把传入对象的数据复制到 Buffer 中。
  • 传递一个 ArrayBufferSharedArrayBuffer 会返回一个与给定数组缓冲区共享已分配内存的 Buffer

由于 new Buffer() 的行为取决于第一个参数的类型,当没有进行参数验证或 Buffer 初始化时,可能会在应用中无意中引入安全性和可靠性问题。

【Because the behavior of new Buffer() is different depending on the type of the first argument, security and reliability issues can be inadvertently introduced into applications when argument validation or Buffer initialization is not performed.】

例如,如果攻击者能够让应用在期望接收字符串的地方收到一个数字,应用可能会调用 new Buffer(100) 而不是 new Buffer("100"),导致它分配一个 100 字节的缓冲区,而不是分配一个内容为 "100" 的 3 字节缓冲区。这通常可以通过 JSON API 调用实现。由于 JSON 区分数字和字符串类型,它允许在通常编写不够严格验证输入的应用中注入数字,而这些应用可能总是期望接收到字符串。在 Node.js 8.0.0 之前,这个 100 字节的缓冲区可能包含任意已有的内存数据,因此可能被用来向远程攻击者暴露内存中的机密信息。自 Node.js 8.0.0 以来,内存泄露已不再可能,因为数据会被填充为零。然而,其他攻击仍然可能,例如导致服务器分配非常大的缓冲区,从而导致性能下降或在内存耗尽时崩溃。

【For example, if an attacker can cause an application to receive a number where a string is expected, the application may call new Buffer(100) instead of new Buffer("100"), leading it to allocate a 100 byte buffer instead of allocating a 3 byte buffer with content "100". This is commonly possible using JSON API calls. Since JSON distinguishes between numeric and string types, it allows injection of numbers where a naively written application that does not validate its input sufficiently might expect to always receive a string. Before Node.js 8.0.0, the 100 byte buffer might contain arbitrary pre-existing in-memory data, so may be used to expose in-memory secrets to a remote attacker. Since Node.js 8.0.0, exposure of memory cannot occur because the data is zero-filled. However, other attacks are still possible, such as causing very large buffers to be allocated by the server, leading to performance degradation or crashing on memory exhaustion.】

为了使创建 Buffer 实例更可靠、减少错误,new Buffer() 构造函数的各种形式已被废弃,并被单独的 Buffer.from()Buffer.alloc()Buffer.allocUnsafe() 方法取代。

【To make the creation of Buffer instances more reliable and less error-prone, the various forms of the new Buffer() constructor have been deprecated and replaced by separate Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe() methods.】

开发者应该将所有现有的 new Buffer() 构造函数的使用迁移到这些新的 API 之一。

Developers should migrate all existing uses of the new Buffer() constructors to one of these new APIs.

Buffer.allocUnsafe()Buffer.from(array) 返回的 Buffer 实例 可能 会从共享的内部内存池中分配,如果 size 小于或等于 Buffer.poolSize 的一半。由 Buffer.allocUnsafeSlow() 返回的实例 从不 使用共享的内部内存池。