Clang 5.0 및 Undefined Behavior Sanitizer (UBsan)를 사용할 때 최근에 제거한 문제를 이해하려고합니다. 버퍼를 정방향 또는 역방향으로 처리하는 코드가 있습니다. 대소 문자는 similar to the code shown below입니다.Clang 5.0 및 UBsan에서 포인터가 추가되고 정수가 오버플로됩니까?
0-len
은 조금 이상하게 보일 수 있지만 초기 Microsoft .Net 컴파일러에 필요합니다. 연타 5.0 UBsan produced integer overflow findings :
adv-simd.h:1138:26: runtime error: addition of unsigned offset to 0x000003f78cf0 overflowed to 0x000003f78ce0
adv-simd.h:1140:26: runtime error: addition of unsigned offset to 0x000003f78ce0 overflowed to 0x000003f78cd0
adv-simd.h:1142:26: runtime error: addition of unsigned offset to 0x000003f78cd0 overflowed to 0x000003f78cc0
...
라인 1138, 1140, 1142 (친구가) 수도 걸음 뒤로 인해 0-len
의 증가이다.
ptr += inc;
(또한 C++에 대해 설명하는) Pointer comparisons in C. Are they signed or unsigned?에 따르면, 포인터는 어느 쪽도 서명되지도 서명한다. 우리의 오프셋은 부호가 없으며 역방향 보폭을 얻기 위해 부호없는 정수 랩에 의존했습니다.
코드는 GCC UBsan 및 Clang 4 및 이전 UBsan에서 유효합니다. 우리는 결국 Clang 5.0을 help with the LLVM devs으로 삭제했습니다. size_t
대신 ptrdiff_t
을 사용해야했습니다.
제 질문은, 공사에서 정수 오버플로/정의되지 않은 동작은 어디에 있습니까? ptr + <unsigned>
은 부호있는 정수가 오버플로되어 정의되지 않은 동작을 일으켰습니까?
여기 실제 코드를 반영하는 MSVC가 있습니다.
I의 서식을 유지하기 위해 여기에 이미지를 사용(이됩니다
#include <cstddef>
#include <cstdint>
using namespace std;
uint8_t buffer[64];
int main(int argc, char* argv[])
{
uint8_t * ptr = buffer;
size_t len = sizeof(buffer);
size_t inc = 16;
// This sets up processing the buffer in reverse.
// A flag controls it in the real code.
if (argc%2 == 1)
{
ptr += len - inc;
inc = 0-inc;
}
while (len > 16)
{
// process blocks
ptr += inc;
len -= 16;
}
return 0;
}
포인터 자체는 부호가 없거나 unsing되지 않습니다. 그러나 포인터가 배열 내부의 어딘가를 가리키고있을 때 포인터가 증가하거나 감소 할 수 있기 때문에 포인터 추가가 서명됩니다. [mcve]가 제공되지 않는 한 정의되지 않은 행동이 있는지 여부를 판단하기에는 부족하기 때문에이 질문의 정보를 바탕으로 더 이상 말할 수 없습니다. –
감사합니다. @ 샘. * "...하지만 포인터 추가가 서명되었습니다 ..."* - 그게 내가 놓치고있는 부분입니다. 부정적인 포인터는 나에게 의미가 없습니다. 나는 그들을 무신론자로 취급했지만 서명되지 않은 유형처럼 행동했습니다. 부정적인 포인터는 C++위원회에서 의미가 있다고 생각합니다. 서명 된 오버 플로우로 인해 어떻게 음의 포인터가 살아남습니까? – jww
배열의 세 번째 요소에 대한 포인터가있는 경우 -1을 추가하고 배열의 두 번째 요소에 대한 포인터로 끝낼 수 있습니다. 포인터 추가가 서명됩니다. –