You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Buffer.from处理字符串时越界读取是已知Bug吗?

拼接缓冲区时读取到额外变量内容的问题分析

问题现象

拼接缓冲区时,输出文件会包含作用域内其他变量的内容。使用Buffer.from转换字符串时出现该问题,替换为Buffer.alloc则恢复正常:

  • 预期输出文件内容:
    A a string
    
  • 实际输出文件内容:
    A <约200字节程序上下文内容> a string<约200字节程序上下文内容>
    

最小复现代码

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

问题根源

这不是Node.js的已知Bug,而是你的concatBuffers函数实现存在问题:

Node.js的Buffer是Uint8Array的子类,为了性能优化会使用内存池机制——Buffer.from创建的实例通常只是共享内存池中某一段区域的视图,它的底层buffer是一个更大的ArrayBuffer,而Buffer自身通过byteOffset和byteLength来限定有效数据范围。

你的concatBuffers函数直接通过new Uint8Array(a.buffer)读取整个底层ArrayBuffer,没有考虑byteOffset和byteLength,导致把内存池中其他变量的内容也一并读取进来,最终写入文件时包含了额外的上下文数据。

而Buffer.alloc会创建独立的、不共享内存池的Buffer实例,它的底层buffer刚好等于自身的有效数据范围,所以不会出现额外内容。

修复方案

修改concatBuffers函数,正确处理TypedArray的有效数据范围:

function concatBuffers(
    a: Uint8Array | Uint16Array | Uint32Array,
    b: Uint8Array | Uint16Array | Uint32Array
): Uint8Array {
    // 提取TypedArray的有效视图,而非整个底层buffer
    const aUint8 = 'byteOffset' in a 
        ? new Uint8Array(a.buffer, a.byteOffset, a.byteLength)
        : new Uint8Array(a);
    const bUint8 = 'byteOffset' in b
        ? new Uint8Array(b.buffer, b.byteOffset, b.byteLength)
        : new Uint8Array(b);
    return concatTypedArrays(aUint8, bUint8);
}

所有TypedArray(包括Buffer)都具备byteOffset和byteLength属性,用来标识它们在底层ArrayBuffer中的起始位置和有效长度。通过这两个属性创建新的Uint8Array,就能确保只读取目标数据的有效范围,避免混入额外内容。

内容的提问来源于stack exchange,提问作者Luctins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:07:01