[llvm] [TySan] Fix size type mismatch in instrumentMemInst for 32-bit targets (PR #191601)

Brian Cain via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 21:54:36 PDT 2026


https://github.com/androm3da created https://github.com/llvm/llvm-project/pull/191601

The outlined instrumentation path in instrumentMemInst passes Size directly to the __tysan_instrument_mem_inst runtime call, which declares its size parameter as uint64_t (i64). On 32-bit targets, Size is IntptrTy (i32) for allocas and byval arguments, causing an assertion:

  Calling a function with a bad signature!

Add CreateZExtOrTrunc to widen Size to U64Ty before the call. This is a no-op on 64-bit targets where IntptrTy is already i64.

>From 9b2804ec8d6a151871c026ed90ab06cfd165afc5 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Fri, 10 Apr 2026 21:49:48 -0700
Subject: [PATCH] [TySan] Fix size type mismatch in instrumentMemInst for
 32-bit targets

The outlined instrumentation path in instrumentMemInst passes Size
directly to the __tysan_instrument_mem_inst runtime call, which declares
its size parameter as uint64_t (i64). On 32-bit targets, Size is
IntptrTy (i32) for allocas and byval arguments, causing an assertion:

  Calling a function with a bad signature!

Add CreateZExtOrTrunc to widen Size to U64Ty before the call. This is
a no-op on 64-bit targets where IntptrTy is already i64.
---
 .../Instrumentation/TypeSanitizer.cpp         |  5 ++-
 .../TypeSanitizer/alloca-32bit.ll             | 39 +++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Instrumentation/TypeSanitizer/alloca-32bit.ll

diff --git a/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
index 98a8068cac946..cea6e9e316c1d 100644
--- a/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
@@ -900,9 +900,12 @@ bool TypeSanitizer::instrumentMemInst(Value *V, Instruction *ShadowBase,
     if (!Src)
       Src = ConstantPointerNull::get(IRB.getPtrTy());
 
+    // The runtime function expects a uint64_t size parameter. On 32-bit
+    // targets, Size may be IntptrTy (i32), so extend it to match.
+    Value *Size64 = IRB.CreateZExtOrTrunc(Size, U64Ty);
     IRB.CreateCall(
         TysanIntrumentMemInst,
-        {Dest, Src, Size, NeedsMemMove ? IRB.getTrue() : IRB.getFalse()});
+        {Dest, Src, Size64, NeedsMemMove ? IRB.getTrue() : IRB.getFalse()});
     return true;
   } else {
     if (!ShadowBase)
diff --git a/llvm/test/Instrumentation/TypeSanitizer/alloca-32bit.ll b/llvm/test/Instrumentation/TypeSanitizer/alloca-32bit.ll
new file mode 100644
index 0000000000000..2cde3a5b8d677
--- /dev/null
+++ b/llvm/test/Instrumentation/TypeSanitizer/alloca-32bit.ll
@@ -0,0 +1,39 @@
+; Test TySan outlined instrumentation on a 32-bit target.
+; The size argument to __tysan_instrument_mem_inst must be zero-extended
+; from i32 (IntptrTy) to i64 (the runtime function's uint64_t parameter).
+;
+; RUN: opt -passes='tysan' -S %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f64:64:64-f32:32:32-v64:64:64-v32:32:32-a:0-n16:32"
+
+declare void @use(ptr)
+
+; Fixed-size alloca: size is a constant i32 that must be zext'd to i64.
+define void @alloca_fixed() sanitize_type {
+; CHECK-LABEL: @alloca_fixed(
+; CHECK:         [[X:%.*]] = alloca [10 x i8], align 1
+; CHECK-NEXT:    call void @__tysan_instrument_mem_inst(ptr [[X]], ptr null, i64 10, i1 false)
+; CHECK-NEXT:    call void @use(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x = alloca [10 x i8], align 1
+  call void @use(ptr %x)
+  ret void
+}
+
+; Dynamic alloca: size is computed as i32 and must be zext'd to i64.
+define void @alloca_dynamic(i32 %n) sanitize_type {
+; CHECK-LABEL: @alloca_dynamic(
+; CHECK:         [[X:%.*]] = alloca i32, i32 [[N:%.*]], align 1
+; CHECK-NEXT:    [[SZ:%.*]] = mul i32 [[N]], 4
+; CHECK-NEXT:    [[SZ64:%.*]] = zext i32 [[SZ]] to i64
+; CHECK-NEXT:    call void @__tysan_instrument_mem_inst(ptr [[X]], ptr null, i64 [[SZ64]], i1 false)
+; CHECK-NEXT:    call void @use(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x = alloca i32, i32 %n, align 1
+  call void @use(ptr %x)
+  ret void
+}



More information about the llvm-commits mailing list