llvm / llvm/llvm-project

[InstCombine] memcpy -> ptrtoint lose provenance

Open
#207,477 1 comment 0 reactions 1 assignee Claimed by @dtcxzyw View on GitHub
generated by fuzzer llvm:instcombine miscompilation
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Reproducer: https://godbolt.org/z/da5K1oeMW

```llvm
; bin/opt -passes=instcombine test.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.S0 = type { i64 }

@g_247 = global %struct.S0 { i64 -1 }
@__const.func_145.l_1208 = constant [1 x ptr] [ptr @g_247]
@g_1210 = global ptr null

define i32 @main() {
entry:
%l_1208.i.i = alloca [1 x ptr], align 8
%l_1207.i.i = alloca [1 x ptr], align 8
call void @llvm.memcpy.p0.p0.i64(ptr %l_1208.i.i, ptr @__const.func_145.l_1208, i64 8, i1 false)
br label %for.cond18.i.i

for.cond18.i.i: ; preds = %for.body20.i.i, %entry
%i.2.i.i = phi i32 [ 0, %entry ], [ 1, %for.body20.i.i ]
%cmp19.i.i = icmp slt i32 %i.2.i.i, 1
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit

for.body20.i.i: ; preds = %for.cond18.i.i
store ptr %l_1208.i.i, ptr %l_1207.i.i, align 8
br label %for.cond18.i.i

func_129.exit: ; preds = %for.cond18.i.i
store ptr %l_1207.i.i, ptr @g_1210, align 8
%0 = load ptr, ptr @g_1210, align 8
%1 = load ptr, ptr %0, align 8
%2 = load ptr, ptr %1, align 8
store i64 0, ptr %2, align 8
ret i32 0
}
```

```
Entering function: main
%l_1208.i.i = alloca [1 x ptr], align 8 => ptr 0x38 [l_1208.i.i]
%l_1207.i.i = alloca [1 x ptr], align 8 => ptr 0x48 [l_1207.i.i]
call void @llvm.memcpy.p0.p0.i64(ptr %l_1208.i.i, ptr @__const.func_145.l_1208, i64 8, i1 false)
br label %for.cond18.i.i jump to %for.cond18.i.i
%i.2.i.i = phi i32 [ 0, %entry ], [ 1, %for.body20.i.i ] => i32 0
%cmp19.i.i = icmp slt i32 %i.2.i.i, 1 => T
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit jump to %for.body20.i.i
store ptr %l_1208.i.i, ptr %l_1207.i.i, align 8
br label %for.cond18.i.i jump to %for.cond18.i.i
%i.2.i.i = phi i32 [ 0, %entry ], [ 1, %for.body20.i.i ] => i32 1
%cmp19.i.i = icmp slt i32 %i.2.i.i, 1 => F
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit jump to %func_129.exit
store ptr %l_1207.i.i, ptr @g_1210, align 8
%0 = load ptr, ptr @g_1210, align 8 => ptr 0x48 [l_1207.i.i]
%1 = load ptr, ptr %0, align 8 => ptr 0x38 [l_1208.i.i]
%2 = load ptr, ptr %1, align 8 => ptr 0x8 [@g_247]
store i64 0, ptr %2, align 8
ret i32 0
Exiting function: main
```
After instcombine:

```llvm
%struct.S0 = type { i64 }

@g_247 = global %struct.S0 { i64 -1 }
@__const.func_145.l_1208 = constant [1 x ptr] [ptr @g_247]
@g_1210 = global ptr null

define i32 @main() {
entry:
%l_1208.i.i = alloca [1 x ptr], align 8
%l_1207.i.i = alloca [1 x ptr], align 8
store i64 ptrtoint (ptr @g_247 to i64), ptr %l_1208.i.i, align 8
br label %for.cond18.i.i

for.cond18.i.i:
%cmp19.i.i = phi i1 [ true, %entry ], [ false, %for.body20.i.i ]
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit

for.body20.i.i:
store ptr %l_1208.i.i, ptr %l_1207.i.i, align 8
br label %for.cond18.i.i

func_129.exit:
store ptr %l_1207.i.i, ptr @g_1210, align 8
%0 = load ptr, ptr %l_1207.i.i, align 8
%1 = load ptr, ptr %0, align 8 ; <- i64 -> ptr doesn't recover provenance
store i64 0, ptr %1, align 8
ret i32 0
}

declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
```

```
Entering function: main
%l_1208.i.i = alloca [1 x ptr], align 8 => ptr 0x38 [l_1208.i.i]
%l_1207.i.i = alloca [1 x ptr], align 8 => ptr 0x48 [l_1207.i.i]
store i64 ptrtoint (ptr @g_247 to i64), ptr %l_1208.i.i, align 8
br label %for.cond18.i.i jump to %for.cond18.i.i
%cmp19.i.i = phi i1 [ true, %entry ], [ false, %for.body20.i.i ] => T
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit jump to %for.body20.i.i
store ptr %l_1208.i.i, ptr %l_1207.i.i, align 8
br label %for.cond18.i.i jump to %for.cond18.i.i
%cmp19.i.i = phi i1 [ true, %entry ], [ false, %for.body20.i.i ] => F
br i1 %cmp19.i.i, label %for.body20.i.i, label %func_129.exit jump to %func_129.exit
store ptr %l_1207.i.i, ptr @g_1210, align 8
%0 = load ptr, ptr %l_1207.i.i, align 8 => ptr 0x38 [l_1208.i.i]
%1 = load ptr, ptr %0, align 8 => ptr 0x8 [nullary]
Stacktrace:
#0 store i64 0, ptr %1, align 8 at @main reduced.ll.tmp:31
Immediate UB detected: Invalid memory access via a pointer with nullary provenance.
error: Execution of function 'main' failed.
```

llvm version: 9b3d68f159e7f2d4ccded135b8bde8b282cd7422 w/ ptrtoint support https://github.com/llvm/llvm-project/pull/207028

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.