将任意 UTF8 字节块解码为字符串是否安全?
Is it safe to decode an arbitrary UTF8-byte-chunk to string?
将被破解成任意字节块的 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
现在我想知道的是,考虑任意编码是否安全,这样做:
result = await reader.read();
// would this be safe ?
chunks.push(textDecoder.decode(result.value));
我所说的“安全”是指它会导致整个字符串被正确解码吗?
我猜不是,但我想我只是想让别人确认一下。
我想当我不得不等到最后合并分块数组时,我也可以调用
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 个代码点,我不记得确切的最低要求)。
显然代码点的排序,composing/decomposing 也有自己的安全问题,但这似乎不在你的问题之列,比如一些字符可能看起来像(或完全像)其他[非个性化]。
好的解码器应该检测 UTF8 中的无效字节 (0xC0)、UTF-8 的超长序列(使用更多字节来获取代码点)以及 Unicode 之外的代码点(因此超过 4 个字节,UCS 允许)。但是一些解码器更加宽松,所以程序应该能够处理它。还有无效序列,但这些是不可解码的,所以解码器通常会做正确的事情(但有些插入错误符号,有些只是丢弃无效字节,并尝试恢复。
将被破解成任意字节块的 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
现在我想知道的是,考虑任意编码是否安全,这样做:
result = await reader.read();
// would this be safe ?
chunks.push(textDecoder.decode(result.value));
我所说的“安全”是指它会导致整个字符串被正确解码吗?
我猜不是,但我想我只是想让别人确认一下。
我想当我不得不等到最后合并分块数组时,我也可以调用
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 个代码点,我不记得确切的最低要求)。
显然代码点的排序,composing/decomposing 也有自己的安全问题,但这似乎不在你的问题之列,比如一些字符可能看起来像(或完全像)其他[非个性化]。
好的解码器应该检测 UTF8 中的无效字节 (0xC0)、UTF-8 的超长序列(使用更多字节来获取代码点)以及 Unicode 之外的代码点(因此超过 4 个字节,UCS 允许)。但是一些解码器更加宽松,所以程序应该能够处理它。还有无效序列,但这些是不可解码的,所以解码器通常会做正确的事情(但有些插入错误符号,有些只是丢弃无效字节,并尝试恢复。