Search code examples
c++undefined-behaviorsanitizer

Why does the clang sanitizer think this left shift of an unsigned number is undefined?


I know there are many similar questions on SO. Please read carefully before calling this a dup. If it is, I would be happy to get a reference to the relevant question.

It seems to me that the clang sanitizer is complaining about a perfectly valid left shift of an unsigned number.

int main()
{
    unsigned int x = 0x12345678;
    x = x << 12;
    return 15 & x;
}

Compiled thusly:

clang -fsanitize=undefined,integer shift-undefined.cpp -lubsan -lstdc++

Results in this error:

shift-undefined.cpp:4:11: runtime error: left shift of 305419896 by 12 places cannot be represented in type 'unsigned int'

I understand that some bits will be shifted off into oblivion, but I thought that was legal for unsigned numbers. What gives?


Solution

  • -fsanitize=address,integer
    

    The integer sanitizer turns on checking for "suspicious" overflows of unsigned integers too, which do not have undefined behavior.

    See "-fsanitize=unsigned-integer-overflow: Unsigned integer overflow, where the result of an unsigned integer computation cannot be represented in its type. Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. This sanitizer does not check for lossy implicit conversions performed before such a computation (see -fsanitize=implicit-conversion)."

    I'd remove that option and only concentrate on signed integer overflow:

    -fsanitize=address,signed-integer-overflow