Issue 133497
Summary UBSan should not warn on integer overflow with downcast or bitwise-AND mask
Labels new issue
Assignees
Reporter Explorer09
    ### Test code

```c
#include <stdint.h>
#include <stdio.h>

static inline unsigned int popCount8(uint8_t x) {
   // Formula borrowed from https://github.com/llvm/llvm-project/issues/79823
   uint32_t n = (uint32_t)(x * 0x08040201U);
   n = ((((n >> 3) & 0x11111111U) * 0x11111111U) & 0xF0000000U) >> 28;
   return n;
}

int main(void) {
 volatile uint8_t x;
   x = 0xFF;
   // Expected output: 8
 printf("%u\n", popCount8(x));
   return 0;
}
```

Compile with: `clang -fsanitize=integer -o test test.c`
Then run with `./test`

### Actual behavior

```
test1.c:6:30: runtime error: unsigned integer overflow: 255 * 134480385 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test1.c:6:30 in 
test1.c:7:35: runtime error: unsigned integer overflow: 286331153 * 286331153 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test1.c:7:44 in 
```

### Expected behavior

No errors and no warnings.

The compiler and UndefinedBehaviorSanitizer should not warn about both overflow cases as I have made downcasts and bitwise-AND masks to tell that the "overflows" are intentional.

* `(uint32_t)(x * 0x08040201U)`
* `((x * 0x11111111U) & 0xF0000000U)`

While I can workaround the bug by adding a upcast like this...

* `(uint32_t)((uint64_t)x * 0x08040201U)`
* `(((uint64_t)x * 0x11111111U) & 0xF0000000U)`

... I would rather like conciseness and not needing such casts.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to