3

I'm running some updates through Undefined Behavior Sanitizer. The sanitizer is producing a message I don't quite understand:

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
              ^

The code in question attempts to make cache timing attacks harder by touching addresses within the range of a cache line. Line 1326 is the line with 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);

Why is the santizier claiming a uint32_t u does not have sufficient space to hold an uint32_t?

Or maybe, am I parsing the error message correctly? Is that what the sanitzier is complaining about? If I am parsing it incorrectly, then what is the sanitzer complaining about?


$ 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)
jww
  • 97,681
  • 90
  • 411
  • 885
  • I suspect it's complaining about `*reinterpret_cast(KalynaTab::S+i)`. – cdhowie May 08 '17 at 19:29
  • 6
    `KalynaTab::S+i` is the `i'th` `uint64_t[256]` array of the *dominant* dimension of your 4x256 table. In other words, as soon as `i` is >= 4 you're out of range and invoking *undefined behavior*. It's a pointer-arithmetic thing. – WhozCraig May 08 '17 at 19:30
  • Thanks @WhozCraig. I believe you are right. But does that explain the error message about insufficient space? Or put another way, wouldn't that produce a different finding (like an access out-of-bounds)? – jww May 08 '17 at 19:51
  • 1
    You seem to be assuming the complaint is about that load address of `u`. I somewhat question that assumption. Rather, your arithmetic is going so far off the deep it may well be reaching unpaged (with good reason) addresses. Regarding an out of bounds error, out of bounds of *what*? [`reinterpret_cast`](http://stackoverflow.com/a/332086/1322972) is a dangerous thing, and assumes you know *exactly* what you're doing. – WhozCraig May 08 '17 at 19:53

1 Answers1

4

The identifier S does not convert to a pointer of the type you think it does. As a result, your pointer arithmetic is throwing you way out of range of your data, and is best shown by example:

#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';
}

Output (obviously platform dependent)

0x1000020b0
0x1000028b0
0x1000030b0
0x1000038b0

0x1000020b0
0x1000020b8
0x1000020c0
0x1000020c8

Note the stride of the first sequence of numbers 0x800 per inferior row. That makes sense since each row is made up of 0x100 entries of 8 bytes each (the uint64_t elements). The type of the pointer being used in the pointer arithmetic is uint64_t (*)[256].

Now note the stride of the second sequence, which peers into only S[0]. The stride is 8 bytes, one for each slot. The type of the converted pointer in this calculation is uint64_t *.

In short, your pointer arithmetic is assuming S converts to uint64_t*, and it doesn't. Like all array-to-pointer conversions, it converts to a pointer-to-first-element, including the type of said-same. The element type in the array of arrays is uint64_t[256], so the converted pointer type is uint64_t (*)[256].

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thanks, you were right. I got my wires crossed on the size of the elements. Hopefully I've learned something new about the diagnostic and I'll recognize the message in the future. – jww May 08 '17 at 19:57