Nodejs Buffer.from leaks程序上下文

fzwojiic  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(86)

Buffer.from()与字符串一起使用时,它会读取变量边界之外的内容,这是一个已知的错误吗?
我在我的后端有 * 非常奇怪 * 的行为,当我连接2个缓冲区时,它会读取变量的内容和它后面的东西,就像其他变量的内容一样。
打字脚本MWE是:

import fs = require("fs");

function concatTypedArrays(a: Uint8Array, b: Uint8Array): Uint8Array {
    const c = new Uint8Array(a.length + b.length);
    c.set(a, 0);
    c.set(b, a.length);
    return c;
}

function concatBuffers(
    a: Uint8Array | Uint16Array | Uint32Array,
    b: Uint8Array | Uint16Array | Uint32Array
): Uint8Array {
    return concatTypedArrays(
        new Uint8Array(a.buffer || a),
        new Uint8Array(b.buffer || b)
    );
}

const test_var = "this is a long string: 6caD764D996ceB0B6217a01C3ec29DDEc760286C97c28FCBFFdF0dc41CD2AE5A0BdcF36a7Cd29cfc99E118Ef0Be71b4Ba4c1dfdE5CeEAaafee3b93ea4eb20ED5ab99bd0aABd2BFd9bdAc1FdA962813D7CD558c9a0AAD4dD81988eaF6c1481bA8AAa731A87AF7DC0B90cB303CBB16122f8778a1c62F38f19Ff599c147c133fC9a9ba0e272de1bA9eD8b6DcC3bD84Ea8d8d0033CdE1d56aa8bcfb4d7dBFd3cF7e354642c026f6EbFb0f1D28Bb6778Ba4CCaaB15eD66fF6Bd428a3cf6C8dD1dBAb3bAbbA3FF7B1ce784473daD21eF45f7a08Eff4FF1Beae9ce4F69DdB1351Bb1d348A7b4aE2F21c9dF3DeAaA2bECF646e34Dbc7F18C3c28fcccAafbA5ACA9C3d8D240adB5C18Df99DcefbEdE1b27C7bd867364abB983eEa7cDC25B401df91ba8A8E776AD0f3a8Faa06bc1ECaF5B0dA0f633f9bf85B24A33c6cAFfF0eEc4BD68B99eBdc8Af258F90ebB049Eb8e9daD3AcbdA47a5Cd2BFFD4d3cbd26BA";

console.log(`test_var: ${test_var}`);

let blob = new Uint8Array(0);

const test_str = "a string";

blob = concatBuffers(blob, new Uint8Array([0x41, 0x20]));

blob = concatBuffers(blob, Buffer.from(test_str));
// blob = concatBuffers(blob, Buffer.alloc(test_str.length, test_str));

fs.writeFileSync("./test_f.bin", blob);

(完成项目here
Buffer.from更改为Buffer.alloc解决了这个问题。否则,输出文件将包含作用域中其他变量的内容。从我的Angular 来看(我通常做嵌入式和系统编程),我没有看到这种行为的明确原因。
预期的输出文件内容为:

A a string

但我得到了:

A <around 200 bytes from the program's context> a string<around 200 bytes from the program's context>

这是一个已知的bug,还是我的实现有问题?(或完全不同)

kadbb459

kadbb4591#

问题就在这里:

return concatTypedArrays(
    new Uint8Array(a.buffer || a),
    new Uint8Array(b.buffer || b)
);

当你像在blob = concatBuffers(blob, Buffer.from(test_str));调用中那样传递一个Buffer时,你直接使用该缓冲区的buffer属性(它的底层数组),而不考虑它的byteOffsetlength。但是缓冲区的内容不能从基础数组的开头开始,也不能完全填满它。byteOffset文档:
Buffer.from(ArrayBuffer, byteOffset, length)中设置byteOffset时,或者**有时在分配小于Buffer.poolSize**的Buffer时,缓冲区不会从底层ArrayBuffer上的零偏移开始。

**当直接使用buf.buffer访问底层ArrayBuffer时,这可能会导致问题,因为ArrayBuffer的其他部分可能与Buffer对象本身无关。

  • (我的重点,两个地方)*

例如,在我的系统中,底层数组是8192字节,缓冲区数据从偏移量16开始。尽管test_str只有8个字符长。因此,您使用的是缓冲区底层数组中的垃圾数据。
相反,您只需要使用Buffer实际使用的Buffer底层数组的一部分,这是通过尊重byteOffsetlength来实现的。

相关问题