2017-05-08 14 views
2

Undefined Behavior Sanitizer를 통해 일부 업데이트가 실행 중입니다. 새니 타이 내가 꽤 이해하지 못하는 메시지를 생산 :Y 유형의 오브젝트에 대해 공간이 충분하지 않은 주소 X의로드

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 uuint32_t을 유지하기에 충분한 공간이없는 주장

?

아니면 오류 메시지를 올바르게 구문 분석합니까? 그것은 sanitzier가 불평하고있는 것입니까? 제가 잘못 파싱한다면, sanitzer는 무엇에 대해 불평하고 있습니까?


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

'reinterpret_cast (KalynaTab :: S + i)'에 대해 불평하고있는 것 같습니다. – cdhowie

+6

'KalynaTab :: S + i'는 여러분의 4x256 테이블의 * dominant * 차원의'i'th'uint64_t [256] 배열입니다. 즉,'i'가> = 4이면 범위를 벗어나 정의되지 않은 동작 *을 호출합니다. 이것은 포인터 연산입니다. – WhozCraig

+0

감사합니다. @WhozCraig. 나는 네가 옳다고 믿는다. 하지만 공간 부족에 대한 오류 메시지가 설명되어 있습니까? 또는 다른 방법으로 말하자면, 접근 범위를 벗어나는 것과 같은 다른 결과를 산출하지 않습니까? – jww

답변

2

식별자 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의 첫 번째 시퀀스의 보폭 각 행은 8 바이트의 0x100 항목 (uint64_t 요소)으로 구성되므로 의미가 있습니다. 포인터 계산에 사용되는 포인터의 유형은 uint64_t (*)[256]입니다.

이제 S[0] 만 피어있는 두 번째 시퀀스의 보폭에 유의하십시오. 스트라이드는 각 슬롯 당 8 바이트입니다. 이 계산에서 변환 된 포인터의 유형은 uint64_t *입니다.

요약하면 포인터 계산은 Suint64_t*으로 변환된다고 가정하고 있습니다. 모든 배열에서 포인터로의 변환과 마찬가지로, 포인터는 first-to-first-element로 변환됩니다. 배열 배열의 요소 유형은 uint64_t[256]이므로 변환 된 포인터 유형은 uint64_t (*)[256]입니다.

+0

감사합니다. 당신이 옳았습니다. 나는 요소의 크기에 와이어를 낀다. 다행히도 나는 진단에 대해 새로운 것을 배웠으며 앞으로 메시지를 인식 할 것입니다. – jww