[MSan] Fix calling pointers to varargs functions on SystemZ
authorIlya Leoshkevich <iii@linux.ibm.com>
Mon, 6 Feb 2023 22:28:06 +0000 (23:28 +0100)
committerIlya Leoshkevich <iii@linux.ibm.com>
Mon, 6 Feb 2023 22:35:13 +0000 (23:35 +0100)
VarArgSystemZHelper.visitCallBase() checks whether the callee has the
"use-soft-float" attribute, but if the callee is a function pointer, a
null pointer dereference happens.

Fix by checking this attribute on the current function. Alternatively,
one could try the callee first, but this is pointless, since one should
not be mixing hardfloat and softfloat code anyway.

Reviewed By: uweigand

Differential Revision: https://reviews.llvm.org/D143296

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll
llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll

index fe8b8ce..1b7e9d0 100644 (file)
@@ -5416,6 +5416,7 @@ struct VarArgSystemZHelper : public VarArgHelper {
   Function &F;
   MemorySanitizer &MS;
   MemorySanitizerVisitor &MSV;
+  bool IsSoftFloatABI;
   Value *VAArgTLSCopy = nullptr;
   Value *VAArgTLSOriginCopy = nullptr;
   Value *VAArgOverflowSize = nullptr;
@@ -5434,9 +5435,10 @@ struct VarArgSystemZHelper : public VarArgHelper {
 
   VarArgSystemZHelper(Function &F, MemorySanitizer &MS,
                       MemorySanitizerVisitor &MSV)
-      : F(F), MS(MS), MSV(MSV) {}
+      : F(F), MS(MS), MSV(MSV),
+        IsSoftFloatABI(F.getFnAttribute("use-soft-float").getValueAsBool()) {}
 
-  ArgKind classifyArgument(Type *T, bool IsSoftFloatABI) {
+  ArgKind classifyArgument(Type *T) {
     // T is a SystemZABIInfo::classifyArgumentType() output, and there are
     // only a few possibilities of what it can be. In particular, enums, single
     // element structs and large types have already been taken care of.
@@ -5474,9 +5476,6 @@ struct VarArgSystemZHelper : public VarArgHelper {
   }
 
   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
-    bool IsSoftFloatABI = CB.getCalledFunction()
-                              ->getFnAttribute("use-soft-float")
-                              .getValueAsBool();
     unsigned GpOffset = SystemZGpOffset;
     unsigned FpOffset = SystemZFpOffset;
     unsigned VrIndex = 0;
@@ -5487,7 +5486,7 @@ struct VarArgSystemZHelper : public VarArgHelper {
       // SystemZABIInfo does not produce ByVal parameters.
       assert(!CB.paramHasAttr(ArgNo, Attribute::ByVal));
       Type *T = A->getType();
-      ArgKind AK = classifyArgument(T, IsSoftFloatABI);
+      ArgKind AK = classifyArgument(T);
       if (AK == ArgKind::Indirect) {
         T = PointerType::get(T, 0);
         AK = ArgKind::GeneralPurpose;
index 650b3cc..de8c9d0 100644 (file)
@@ -31,7 +31,7 @@ define i64 @bar() #1 {
   ret i64 %1
 }
 
-attributes #1 = { sanitize_memory }
+attributes #1 = { sanitize_memory "target-features"="+soft-float" "use-soft-float"="true" }
 
 ; In kernel the floating point values are passed in GPRs:
 ; - r2@16              == i64 1            - skipped, because it's fixed
index d908a91..009aef9 100644 (file)
@@ -197,3 +197,16 @@ define i64 @bar_128() {
 ; CHECK: declare void @__msan_maybe_store_origin_4(i32 zeroext, ptr, i32 zeroext)
 ; CHECK: declare void @__msan_maybe_warning_8(i64 zeroext, i32 zeroext)
 ; CHECK: declare void @__msan_maybe_store_origin_8(i64 zeroext, ptr, i32 zeroext)
+
+; Test vararg function pointers.
+;
+; void (*ptr)(int, ...);
+; void call_ptr(void) { ptr(0); }
+
+@ptr = dso_local global ptr null, align 8
+
+define dso_local void @call_ptr() {
+  %1 = load ptr, ptr @ptr, align 8
+  call void (i32, ...) %1(i32 noundef signext 0)
+  ret void
+}