Skip to content

Conversation

thurstond
Copy link
Contributor

@thurstond thurstond commented Aug 28, 2025

MSan fails to catch this, because 0-byte allocations are converted into 1-byte allocations.

Bug originally reported by dvyukov

@llvmbot
Copy link
Member

llvmbot commented Aug 28, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Thurston Dang (thurstond)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/155934.diff

2 Files Affected:

  • (added) compiler-rt/test/msan/zero_alloc.cpp (+37)
  • (modified) llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (+3)
diff --git a/compiler-rt/test/msan/zero_alloc.cpp b/compiler-rt/test/msan/zero_alloc.cpp
new file mode 100644
index 0000000000000..4b60c161efb36
--- /dev/null
+++ b/compiler-rt/test/msan/zero_alloc.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_msan -Wno-alloc-size -fsanitize-recover=memory %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// XFAIL: *
+
+#include <malloc.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+  {
+     char* p1 = (char*)calloc(1, 0);
+     printf ("p1 is %p\n", p1);
+     printf ("Content of p1 is: %d\n", *p1);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p1);
+  }
+
+  {
+     char* p2 = (char*)calloc(0, 1);
+     printf ("p2 is %p\n", p2);
+     printf ("Content of p2 is: %d\n", *p2);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p2);
+  }
+
+  {
+     char* p3 = (char*)malloc(0);
+     printf ("p3 is %p\n", p3);
+     printf ("Content of p2 is: %d\n", *p3);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p3);
+  }
+
+  return 0;
+}
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index fc34d14259d1f..66cdbfcf998c6 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -1574,6 +1574,9 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
   if (F.empty())
     return;
 
+  if (F.isPresplitCoroutine())
+    return;
+
   NumTotalFuncs++;
 
   OptimizationRemarkEmitter &ORE =

@llvmbot
Copy link
Member

llvmbot commented Aug 28, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Thurston Dang (thurstond)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/155934.diff

2 Files Affected:

  • (added) compiler-rt/test/msan/zero_alloc.cpp (+37)
  • (modified) llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (+3)
diff --git a/compiler-rt/test/msan/zero_alloc.cpp b/compiler-rt/test/msan/zero_alloc.cpp
new file mode 100644
index 0000000000000..4b60c161efb36
--- /dev/null
+++ b/compiler-rt/test/msan/zero_alloc.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_msan -Wno-alloc-size -fsanitize-recover=memory %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// XFAIL: *
+
+#include <malloc.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+  {
+     char* p1 = (char*)calloc(1, 0);
+     printf ("p1 is %p\n", p1);
+     printf ("Content of p1 is: %d\n", *p1);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p1);
+  }
+
+  {
+     char* p2 = (char*)calloc(0, 1);
+     printf ("p2 is %p\n", p2);
+     printf ("Content of p2 is: %d\n", *p2);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p2);
+  }
+
+  {
+     char* p3 = (char*)malloc(0);
+     printf ("p3 is %p\n", p3);
+     printf ("Content of p2 is: %d\n", *p3);
+     // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+     // CHECK: {{#0 0x.* in main .*zero_alloc.cpp:}}[[@LINE-2]]
+     free(p3);
+  }
+
+  return 0;
+}
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index fc34d14259d1f..66cdbfcf998c6 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -1574,6 +1574,9 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
   if (F.empty())
     return;
 
+  if (F.isPresplitCoroutine())
+    return;
+
   NumTotalFuncs++;
 
   OptimizationRemarkEmitter &ORE =

@thurstond thurstond marked this pull request as draft August 28, 2025 22:17
MSan fails to catch this, because 0-byte allocations are converted into
1-byte allocations.

Bug originally reported by dvyukov
@thurstond thurstond force-pushed the msan_zero_alloc_test branch from 132129a to 793f472 Compare August 28, 2025 22:20
@thurstond thurstond marked this pull request as ready for review August 28, 2025 22:20
@thurstond thurstond changed the title Msan zero alloc test [msan] Add test for deferencing zero-sized malloc/calloc Aug 28, 2025
@thurstond thurstond merged commit 7450a00 into llvm:main Aug 28, 2025
9 checks passed
thurstond added a commit to thurstond/llvm-project that referenced this pull request Aug 28, 2025
When a zero-byte allocation is requested, MSan actually allocates 1-byte
for compatibility. This change poisons that byte, to detect
dereferences.

Also updates the test from llvm#155934
thurstond added a commit that referenced this pull request Aug 29, 2025
…155944)

When a zero-byte allocation is requested, MSan actually allocates 1-byte
for compatibility. This change poisons that byte, to detect
dereferences.

Also updates the test from #155934
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants