c++ - 为类型 Y 的对象加载空间不足的地址 X

标签 c++ gcc undefined-behavior ubsan

我正在通过 Undefined Behavior Sanitizer 运行一些更新。 sanitizer 正在产生一条我不太明白的消息:

kalyna.cpp:1326:61: runtime error: load of address 0x0000016262c0 with insufficient space for an object of type 'const uint32_t'
0x0000016262c0: note: pointer points here
 20 8b c1 1f  a9 f7 f9 5c 53 c4 cf d2  2f 3f 52 be 84 ed 96 1b  b8 7a b2 85 e0 96 7d 5d  70 ee 06 07
              ^

有问题的代码试图通过访问缓存行范围内的地址来使缓存定时攻击变得更加困难。第 1326 行是带有 reinterpret_cast 的行:

// In KalynaTab namespace
uint64_t S[4][256] = {
    ...
};
...

// In library's namespace
const int cacheLineSize = GetCacheLineSize();
volatile uint32_t _u = 0;
uint32_t u = _u;

for (unsigned int i=0; i<256; i+=cacheLineSize)
    u &= *reinterpret_cast<const uint32_t*>(KalynaTab::S+i);

为什么 santizier 声称 uint32_t u 没有足够的空间来容纳 uint32_t

或者,我是否正确解析了错误消息?这就是 sanitizer 所提示的吗?如果我解析不正确,那么 sanitizer 在提示什么?


$ lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch

$ gcc --version
gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)

最佳答案

标识符 S 不会转换为您认为的类型的指针。结果,您的指针算法使您方式超出了您的数据范围,最好通过示例来展示:

#include <iostream>
#include <cstdint>

uint64_t S[4][256];

int main()
{
    std::cout << static_cast<void*>(S+0) << '\n';
    std::cout << static_cast<void*>(S+1) << '\n';
    std::cout << static_cast<void*>(S+2) << '\n';
    std::cout << static_cast<void*>(S+3) << '\n';
    std::cout << '\n';

    std::cout << static_cast<void*>(*S+0) << '\n';
    std::cout << static_cast<void*>(*S+1) << '\n';
    std::cout << static_cast<void*>(*S+2) << '\n';
    std::cout << static_cast<void*>(*S+3) << '\n';
}

输出(显然依赖于平台)

0x1000020b0
0x1000028b0
0x1000030b0
0x1000038b0

0x1000020b0
0x1000020b8
0x1000020c0
0x1000020c8

注意每个下行的第一个数字序列 0x800 的步幅。这是有道理的,因为每一行都由 0x100 个条目组成,每个条目 8 个字节(uint64_t 元素)。指针算法中使用的指针类型是 uint64_t (*)[256]

现在请注意第二个序列的步幅,它只查看 S[0]。跨度为 8 个字节,每个插槽一个。本次计算转换后的指针类型为uint64_t *

简而言之,您的指针算法假设 S 转换为 uint64_t*,但事实并非如此。与所有数组到指针的转换一样,它转换为指向第一个元素的指针,包括 said-same 的类型。数组数组中的元素类型为uint64_t[256],所以转换后的指针类型为uint64_t(*)[256]

关于c++ - 为类型 Y 的对象加载空间不足的地址 X,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43855767/

相关文章:

C++容器容器的增长?

C++ 在内存中运行字节数组

c++ - 删除使用 const_iterator 的 vector 的元素

c++ - Makefile.am 的 EXTRA_DIST 重复目录名

c - 用于变量属性的 GCC 扩展 __attribute__ ((未使用))

c++ - 这些关于 GCC 优化的评论是否有效?

c++ - 如何让 clang 搜索 gcc 的头文件?

c - 为什么我在这个 STACK 程序中得到这个数字而不是值?

c - 是否有发现 UB 的规则?

c++ - 为什么 `printf("%llu\n", 1ull << n) ;` and ` printf ("%llu\n", 1ull << 64);` 的输出在 C++ 中不同?(n=64)