Javascript 将任意UTF8字节块解码为字符串是否安全?
将已被黑客攻击为任意字节块的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);
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);