对于类型为Y的对象,地址X的加载空间不足

时间:2017-05-08 19:24:33

标签: c++ gcc undefined-behavior ubsan

我通过Undefined Behavior 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);

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

或者,我是否正确解析了错误消息?这是sanitzier抱怨的吗?如果我解析不正确,那么赛泽尔抱怨的是什么?

$ 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)

1 个答案:

答案 0 :(得分:3)

标识符#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'; } 不会转换为您认为它所执行类型的指针。因此,您的指针算法会使 way 超出数据范围,最好通过示例显示:

0x1000020b0
0x1000028b0
0x1000030b0
0x1000038b0

0x1000020b0
0x1000020b8
0x1000020c0
0x1000020c8

输出(显然取决于平台)

uint64_t (*)[256]

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

现在请注意第二个序列的步幅,它只与uint64_t *对齐。步幅为8个字节,每个插槽一个。此计算中转换的指针的类型为S

简而言之,您的指针算术假定uint64_t*转换为uint64_t[256],而且它没有。与所有数组到指针的转换一样,它转换为指向第一个元素的指针,包括所述相同的类型。数组数组中的元素类型为uint64_t (*)[256],因此转换后的指针类型为div