[libcxx-commits] [libcxx] [libc++] Fix bogus integer sanitizer warnings in hash helpers (PR #146715)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 4 11:39:09 PDT 2025


https://github.com/ldionne commented:

This makes sense to me. Just to make sure we're on the same page: the mathematical result of this left shift is indeed not representable in an `unsigned long`, but that's okay because we discard the bits that are shifted beyond the "end" of the integer. So we have:

```
__val << (64 - __shift)
```

where `__val = 17751278790833232267U` and `__shift = 43`, giving `17751278790833232267U << 21`. That number would be `37302001761581901365411840` which doesn't fit inside an `unsigned long`, but in reality what we get is just the lower 64 bits of that number, aka `5770268451330048`.

So the operation itself is valid and the UBSan warning is bogus. If I got that right, then I'm fine with this patch.

I do agree with @philnik777 that we should enable this in our sanitizer CI. This should be doable with something like this patch:

```diff
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index dffdd7a3c70a..9bbd64cce370 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -611,10 +611,10 @@ function(get_sanitizer_flags OUT_VAR  USE_SANITIZER)
         append_flags(SANITIZER_FLAGS "-fsanitize-memory-track-origins")
       endif()
     elseif (USE_SANITIZER STREQUAL "Undefined")
-      append_flags(SANITIZER_FLAGS "-fsanitize=undefined" "-fno-sanitize=vptr,function" "-fno-sanitize-recover=all")
+      append_flags(SANITIZER_FLAGS "-fsanitize=undefined,integer" "-fno-sanitize=vptr,function" "-fno-sanitize-recover=all")
     elseif (USE_SANITIZER STREQUAL "Address;Undefined" OR
             USE_SANITIZER STREQUAL "Undefined;Address")
-      append_flags(SANITIZER_FLAGS "-fsanitize=address,undefined" "-fno-sanitize=vptr,function" "-fno-sanitize-recover=all")
+      append_flags(SANITIZER_FLAGS "-fsanitize=address,undefined,integer" "-fno-sanitize=vptr,function" "-fno-sanitize-recover=all")
     elseif (USE_SANITIZER STREQUAL "Thread")
       append_flags(SANITIZER_FLAGS -fsanitize=thread)
     elseif (USE_SANITIZER STREQUAL "DataFlow")
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index fc34009d0a55..65715117e7dc 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -317,8 +317,8 @@ DEFAULT_PARAMETERS = [
             [
                 AddFlag("-g -fno-omit-frame-pointer") if sanitizer else None,
 
-                AddFlag("-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all") if sanitizer == "Undefined" else None,
-                AddFeature("ubsan")                                                                          if sanitizer == "Undefined" else None,
+                AddFlag("-fsanitize=undefined,integer -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all") if sanitizer == "Undefined" else None,
+                AddFeature("ubsan")                                                                                  if sanitizer == "Undefined" else None,
 
                 AddFlag("-fsanitize=address") if sanitizer == "Address" else None,
                 AddFeature("asan")            if sanitizer == "Address" else None,
```

That will bundle `-fsanitize=integer` into our existing ubsan checks, but I think that should be reasonable?

https://github.com/llvm/llvm-project/pull/146715


More information about the libcxx-commits mailing list