Why is bitset::set() triggering undefined behavior

68 Views Asked by At

If I compile this code

#include <bitset>

int
main(int argc, char** argv) {
    std::bitset<96> mask;
    mask.set();
    return 0;
}

with clang++ -fsanitize=integer test_bitset.cpp and run the result, I get

.../include/c++/12/bitset:657:46: runtime error: left shift of 18446744073709551615 by 32 places cannot be represented in type 'std::_Sanitize::_WordT' (aka 'unsigned long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior .../include/c++/12/bitset:657:46 in 

This looks a little bit like Why does the clang sanitizer think this left shift of an unsigned number is undefined? but if I try to disable the check using

clang++ -fsanitize=integer -fno-sanitize=unsigned-integer-overflow test_bitset.cpp

the undefined behavior persists. To add to the confusion, if I enable "all" integer checks manually (as mentioned in the docs)

clang++ -fsanitize=signed-integer-overflow,unsigned-integer-overflow,shift,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change test_bitset.cpp 

the undefined behavior is gone. So apparently -fsanitize=integer does more than that?

I can silence the error using a blacklist on bitset but I really want to know whether it is a bug in the stdlib or can be ignored safely.

I tried this with clang 14 and clang 15 on a standard ubuntu 22.04. Any hints are appreciated.

1

There are 1 best solutions below

0
Michael On

As @user17732522 pointed out correctly it is just a bug in the clang docs. The correct call to avoid the check is clang++ -fsanitize=integer -fno-sanitize=unsigned-shift-base test_bitset.cpp and the check is just oversensitive it is not an undefined behavior.