[llvm] 87d604f - [SimplifyLibCalls] avoid crash on pointer math

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 26 08:09:00 PDT 2021


Author: Sanjay Patel
Date: 2021-07-26T11:08:45-04:00
New Revision: 87d604ffe494fcf66e469e2758c289f18b0e7ce9

URL: https://github.com/llvm/llvm-project/commit/87d604ffe494fcf66e469e2758c289f18b0e7ce9
DIFF: https://github.com/llvm/llvm-project/commit/87d604ffe494fcf66e469e2758c289f18b0e7ce9.diff

LOG: [SimplifyLibCalls] avoid crash on pointer math

We could try harder to screen out libcalls by
function signature (and that would be a much larger
change than for sprintf alone), but that might make
the transition to type-less pointers more difficult.

https://llvm.org/PR51200

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/test/Transforms/InstCombine/stpcpy-1.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 325eba9f2f8f..b8e0f63c481d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2522,6 +2522,8 @@ Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,
       return ConstantInt::get(CI->getType(), SrcLen - 1);
     } else if (Value *V = emitStpCpy(Dest, CI->getArgOperand(2), B, TLI)) {
       // sprintf(dest, "%s", str) -> stpcpy(dest, str) - dest
+      // Handle mismatched pointer types (goes away with typeless pointers?).
+      V = B.CreatePointerCast(V, Dest->getType());
       Value *PtrDiff = B.CreatePtrDiff(V, Dest);
       return B.CreateIntCast(PtrDiff, CI->getType(), false);
     }

diff  --git a/llvm/test/Transforms/InstCombine/stpcpy-1.ll b/llvm/test/Transforms/InstCombine/stpcpy-1.ll
index 7ccdf6c95023..f1872e77e2b1 100644
--- a/llvm/test/Transforms/InstCombine/stpcpy-1.ll
+++ b/llvm/test/Transforms/InstCombine/stpcpy-1.ll
@@ -9,7 +9,9 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
 @hello = constant [6 x i8] c"hello\00"
 @a = common global [32 x i8] zeroinitializer, align 1
 @b = common global [32 x i8] zeroinitializer, align 1
+ at percent_s = constant [3 x i8] c"%s\00"
 
+declare i32 @sprintf(i8**, i32*, ...)
 declare i8* @stpcpy(i8*, i8*)
 
 define i8* @test_simplify1() {
@@ -17,10 +19,8 @@ define i8* @test_simplify1() {
 ; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* noundef nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false)
 ; CHECK-NEXT:    ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5)
 ;
-
   %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
   %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
-
   %ret = call i8* @stpcpy(i8* %dst, i8* %src)
   ret i8* %ret
 }
@@ -31,9 +31,7 @@ define i8* @test_simplify2() {
 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @a, i32 0, i32 [[STRLEN]]
 ; CHECK-NEXT:    ret i8* [[TMP1]]
 ;
-
   %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
-
   %ret = call i8* @stpcpy(i8* %dst, i8* %dst)
   ret i8* %ret
 }
@@ -43,9 +41,7 @@ define void @test_simplify3(i8* %dst) {
 ; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(80) [[DST:%.*]], i8* noundef nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false)
 ; CHECK-NEXT:    ret void
 ;
-
   %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
-
   call i8* @stpcpy(i8* dereferenceable(80) %dst, i8* %src)
   ret void
 }
@@ -55,10 +51,8 @@ define i8* @test_no_simplify1() {
 ; CHECK-NEXT:    [[RET:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0))
 ; CHECK-NEXT:    ret i8* [[RET]]
 ;
-
   %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
   %src = getelementptr [32 x i8], [32 x i8]* @b, i32 0, i32 0
-
   %ret = call i8* @stpcpy(i8* %dst, i8* %src)
   ret i8* %ret
 }
@@ -68,10 +62,30 @@ define i8* @test_no_incompatible_attr() {
 ; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* noundef nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false)
 ; CHECK-NEXT:    ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5)
 ;
-
   %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
   %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
-
   %ret = call dereferenceable(1) i8* @stpcpy(i8* %dst, i8* %src)
   ret i8* %ret
 }
+
+; The libcall prototype checker does not check for exact pointer type
+; (just pointer of some type), so we identify this as a standard sprintf
+; call. This requires a cast to operate on mismatched pointer types.
+
+define i32 @PR51200(i8** %p, i32* %p2) {
+; CHECK-LABEL: @PR51200(
+; CHECK-NEXT:    [[CSTR:%.*]] = bitcast i8** [[P:%.*]] to i8*
+; CHECK-NEXT:    [[CSTR1:%.*]] = bitcast i32* [[P2:%.*]] to i8*
+; CHECK-NEXT:    [[STPCPY:%.*]] = call i8* @stpcpy(i8* [[CSTR]], i8* [[CSTR1]])
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint i8* [[STPCPY]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[TMP1]] to i64
+; CHECK-NEXT:    [[TMP3:%.*]] = ptrtoint i8** [[P]] to i32
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i32 [[TMP3]] to i64
+; CHECK-NEXT:    [[TMP5:%.*]] = sub nsw i64 [[TMP2]], [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr exact i64 [[TMP5]], 2
+; CHECK-NEXT:    [[TMP7:%.*]] = trunc i64 [[TMP6]] to i32
+; CHECK-NEXT:    ret i32 [[TMP7]]
+;
+  %call = call i32 (i8**, i32*, ...) @sprintf(i8** %p, i32* bitcast ([3 x i8]* @percent_s to i32*), i32* %p2)
+  ret i32 %call
+}


        


More information about the llvm-commits mailing list