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中。 - 传递一个
ArrayBuffer或SharedArrayBuffer会返回一个与给定数组缓冲区共享已分配内存的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.from(array)返回一个新的Buffer,其中包含所提供的八位字节的副本。Buffer.from(arrayBuffer[, byteOffset[, length]])返回一个新的Buffer,它 与给定的ArrayBuffer共享相同的已分配内存。Buffer.from(buffer)返回一个新的Buffer,其中 包含 给定Buffer内容的副本。Buffer.from(string[, encoding])返回一个新的Buffer,它_包含了提供的字符串的副本_。Buffer.alloc(size[, fill[, encoding]])返回一个指定大小的新初始化Buffer。该方法比Buffer.allocUnsafe(size)慢,但保证新创建的Buffer实例不会包含可能敏感的旧数据。如果size不是数字,将抛出TypeError。Buffer.allocUnsafe(size)和Buffer.allocUnsafeSlow(size)各自返回一个指定size的新未初始化Buffer。由于Buffer是未初始化的,分配的内存段可能包含旧数据,这些旧数据可能是敏感信息。
由 Buffer.allocUnsafe() 和 Buffer.from(array) 返回的 Buffer 实例 可能 会从共享的内部内存池中分配,如果 size 小于或等于 Buffer.poolSize 的一半。由 Buffer.allocUnsafeSlow() 返回的实例 从不 使用共享的内部内存池。