在 std::vector<unsigned char> 中将 std::wstring 编码为 UTF-16 的正确方法是什么?
What is the proper way to encode a std::wstring to UTF-16 in a std::vector<unsigned char>?
我正在尝试将 std::wstring
编码为 UTF-16,并将其传递给采用一对向量迭代器的函数。为此,我尝试了以下方法。
std::vector<unsigned char> HashAlgorithm::ComputeHash(std::wstring value)
{
std::wstring_convert<std::codecvt_utf16<wchar_t>> converter;
std::string encodedString = converter.to_bytes(value);
std::vector<unsigned char> encodedBytes(
reinterpret_cast<unsigned char const *>(encodedString.c_str()),
reinterpret_cast<unsigned char const *>(encodedString.c_str() + encodedString.size()));
std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(), encodedBytes.end());
return hashedBytes;
}
它在大多数情况下工作正常,除了我知道出了点问题,因为在调试模式下我在 hashedBytes
的 return 上看到以下断言,它闻起来像某种堆栈腐败。
是什么导致了这个错误,我该如何预防?
编辑 #1
下面是我正在使用的支持功能的内容。我一直试图将其分解以找出断言的来源和原因,但我还无法获得最小的复制品。
std::vector<unsigned char> HashAlgorithm::ComputeHash(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
this->Process(begin, end);
std::vector<unsigned char> hashedBytes = this->Complete();
return hashedBytes;
}
void HashAlgorithm::Process(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
NTSTATUS status = BCryptHashData(this->hash, const_cast<unsigned char *>(&(*begin)), std::distance(begin, end), 0);
}
std::vector<unsigned char> HashAlgorithm::Complete()
{
std::vector<unsigned char> result(this->outputSize);
NTSTATUS status = BCryptFinishHash(this->hash, result.data(), (ULONG)result.size(), 0);
return result;
}
为确保您不会丢失任何数据,您应该直接对字节进行哈希处理:
std::vector<unsigned char> myClass::ComputeHash(std::wstring value)
{
auto size_of_data = value.size()*sizeof(value[0]);
auto pointer_to_data = reinterpret_cast<unsigned char const *>(value.data());
std::vector<unsigned char> encodedBytes(pointer_to_data,pointer_to_data+size_of_data);
std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(),encodedBytes.end());
return hashedBytes;
}
尝试添加一个香蕉 (\U0001F34C) 以查看您的数据在逐步执行时发生了什么。例如std::wstring my_unicode_string{L"Test string \n"};
或 std::wstring wstr = L"z\u00df\u6c34\U0001F34C"; // L"zß水"
。如果您的 .cpp 文件未保存为 unicode 文本,第二个示例可能会更好。
您可能会遇到 to_bytes
抛出的异常,因为只有基本多语言平面中的代码点才能编码为单个 wchar
。如果它确实为您进行转换,它可能会将不同的更高代码点映射到相似的字节,这将导致不同字符串的相同散列。
Microsoft VC++ 2010 和 2015 之间的 std::wstring
不 向后兼容。
问题是库代码 (VS 2010) 和客户端代码 (VS 2015) 中的 std::wstring
大小相差 4 个字节。 std::wstring
的较新版本更大,有 32 个字节,而旧版本有 28 个字节。当按值传递这些变量时,堆栈损坏发生在较小 std::wstring
的前 4 个字节中,并触发用于防止基于堆栈的漏洞利用的堆栈金丝雀。
我正在尝试将 std::wstring
编码为 UTF-16,并将其传递给采用一对向量迭代器的函数。为此,我尝试了以下方法。
std::vector<unsigned char> HashAlgorithm::ComputeHash(std::wstring value)
{
std::wstring_convert<std::codecvt_utf16<wchar_t>> converter;
std::string encodedString = converter.to_bytes(value);
std::vector<unsigned char> encodedBytes(
reinterpret_cast<unsigned char const *>(encodedString.c_str()),
reinterpret_cast<unsigned char const *>(encodedString.c_str() + encodedString.size()));
std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(), encodedBytes.end());
return hashedBytes;
}
它在大多数情况下工作正常,除了我知道出了点问题,因为在调试模式下我在 hashedBytes
的 return 上看到以下断言,它闻起来像某种堆栈腐败。
是什么导致了这个错误,我该如何预防?
编辑 #1
下面是我正在使用的支持功能的内容。我一直试图将其分解以找出断言的来源和原因,但我还无法获得最小的复制品。
std::vector<unsigned char> HashAlgorithm::ComputeHash(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
this->Process(begin, end);
std::vector<unsigned char> hashedBytes = this->Complete();
return hashedBytes;
}
void HashAlgorithm::Process(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
NTSTATUS status = BCryptHashData(this->hash, const_cast<unsigned char *>(&(*begin)), std::distance(begin, end), 0);
}
std::vector<unsigned char> HashAlgorithm::Complete()
{
std::vector<unsigned char> result(this->outputSize);
NTSTATUS status = BCryptFinishHash(this->hash, result.data(), (ULONG)result.size(), 0);
return result;
}
为确保您不会丢失任何数据,您应该直接对字节进行哈希处理:
std::vector<unsigned char> myClass::ComputeHash(std::wstring value)
{
auto size_of_data = value.size()*sizeof(value[0]);
auto pointer_to_data = reinterpret_cast<unsigned char const *>(value.data());
std::vector<unsigned char> encodedBytes(pointer_to_data,pointer_to_data+size_of_data);
std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(),encodedBytes.end());
return hashedBytes;
}
尝试添加一个香蕉 (\U0001F34C) 以查看您的数据在逐步执行时发生了什么。例如std::wstring my_unicode_string{L"Test string \n"};
或 std::wstring wstr = L"z\u00df\u6c34\U0001F34C"; // L"zß水"
。如果您的 .cpp 文件未保存为 unicode 文本,第二个示例可能会更好。
您可能会遇到 to_bytes
抛出的异常,因为只有基本多语言平面中的代码点才能编码为单个 wchar
。如果它确实为您进行转换,它可能会将不同的更高代码点映射到相似的字节,这将导致不同字符串的相同散列。
std::wstring
不 向后兼容。
问题是库代码 (VS 2010) 和客户端代码 (VS 2015) 中的 std::wstring
大小相差 4 个字节。 std::wstring
的较新版本更大,有 32 个字节,而旧版本有 28 个字节。当按值传递这些变量时,堆栈损坏发生在较小 std::wstring
的前 4 个字节中,并触发用于防止基于堆栈的漏洞利用的堆栈金丝雀。