[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