Javascript 将任意UTF8字节块解码为字符串是否安全?

Javascript 将任意UTF8字节块解码为字符串是否安全?,javascript,typescript,encoding,character-encoding,textdecoder,Javascript,Typescript,Encoding,Character Encoding,Textdecoder,将已被黑客攻击为任意字节块的UTF8字符串解码为字符串(按块)安全吗 还有,任意编码呢 上下文是指此方法: async getFileAsync(fileName: string, encoding: string):string { const textDecoder = new TextDecoder(encoding); const response = await fetch(fileName); console.log(response.ok);

将已被黑客攻击为任意字节块的UTF8字符串解码为字符串(按块)安全吗

还有,任意编码呢

上下文是指此方法:

async getFileAsync(fileName: string, encoding: string):string
{
    const textDecoder = new TextDecoder(encoding);
    const response = await fetch(fileName);
    
    console.log(response.ok);
    console.log(response.status);
    console.log(response.statusText);
    
    // let responseBuffer:ArrayBuffer = await response.arrayBuffer();
    // let text:string = textDecoder.decode(responseBuffer);
    
    // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader
    const reader = response.body.getReader();
    let result:ReadableStreamReadResult<Uint8Array>;
    let chunks:Uint8Array[] = [];
    
    // due to done, this is unlike C#:
    // byte[] buffer = new byte[32768];
    // int read;
    // while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    // {
    //     output.Write (buffer, 0, read);
    // }

    do
    {
        result = await reader.read();
        chunks.push(result.value);

        // would this be safe ? 
        let partN = textDecoder.decode(result.value);
        // chunks.push(partN);

        console.log("result: ", result.value, partN);
    } while(!result.done)

    let chunkLength:number = chunks.reduce(
        function(a, b)
        {
            return a + (b||[]).length;
        }
        , 0
    );
    
    let mergedArray = new Uint8Array(chunkLength);
    let currentPosition = 0;
    for(let i = 0; i < chunks.length; ++i)
    {
        mergedArray.set(chunks[i],currentPosition);
        currentPosition += (chunks[i]||[]).length;
    } // Next i 

    let file:string = textDecoder.decode(mergedArray);
    
    // let file:string = chunks.join('');
    return file;
} // End Function getFileAsync
我所说的“安全”是指它会导致整个字符串被正确解码吗

我猜不是,但我想我只是想有人确认一下

我想当我不得不等到最后才合并分块数组时,我也可以调用

let responseBuffer:ArrayBuffer = await response.arrayBuffer();
let text:string = textDecoder.decode(responseBuffer);

取而代之。

这取决于你说的安全是什么意思

您知道原始字符串的大小,因此您拥有解码字符串的最大大小。因此,这大大减少了一些现代的DoS(放大攻击)

算法很简单。但是在如何使用数据方面有很多安全隐患:UTF-8可能隐藏不必要的长序列。好的解码器应该丢弃它们,但可能在需要
U+0000
时(长编码有助于保持C字符串的愉快,但也可以使用所有Unicode字符(同样
U+0000
)。您应该对此进行测试。您不希望该字符串有一个
0x00
值,并且某些函数将使用一个长度的字符串,而另一些函数将使用另一个长度的字符串,从而导致可能的缓冲区溢出

UCS使用UTF-8的泛化,允许编码更多位(最多31位),但消耗更多字节。有些UTF-8解码器允许,有些则不允许。一般来说,这应该是一个错误,因为许多操作函数对超过当前Unicode限制的代码点不满意)

规范化有很多含义,例如删除不必要的代码点:Unicode(以及其他库)可能会遇到编码过多的字符的问题(超过16或32个代码点,我不记得确切的最低要求)

显然,代码点的排序和组合/分解也有自身的安全问题,但这似乎超出了您的问题范围,例如某些字符可能看起来像(或完全像)其他字符[模拟]

好的解码器应该检测UTF8中的无效字节(0xC0)、过长的UTF-8序列(使用更多字节获得代码点)和Unicode之外的代码点(因此UCS允许超过4个字节)。但有些解码器的权限要大得多,所以程序应该能够处理这个问题。也有无效的序列,但它们是不可解码的,所以解码器通常会做正确的事情(但有些插入错误符号,有些只是丢弃无效字节,然后尝试恢复)

let responseBuffer:ArrayBuffer = await response.arrayBuffer();
let text:string = textDecoder.decode(responseBuffer);