From: Ilya Leoshkevich Date: Mon, 6 Feb 2023 22:28:06 +0000 (+0100) Subject: [MSan] Fix calling pointers to varargs functions on SystemZ X-Git-Tag: upstream/17.0.6~18417 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=322e150e3392026a205c583da80e8971653825c8;p=platform%2Fupstream%2Fllvm.git [MSan] Fix calling pointers to varargs functions on SystemZ 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 --- diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index fe8b8ce..1b7e9d0 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -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; diff --git a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll index 650b3ccc..de8c9d0 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll @@ -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 diff --git a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll index d908a91..009aef9 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll @@ -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 +}