-
Notifications
You must be signed in to change notification settings - Fork 141
setjmp/longjmp control transfer is missliced #473
Description
[llvm-slicer] setjmp/longjmp control transfer is missliced
Hi, thanks for maintaining dg and llvm-slicer.
We may have found a slicing correctness issue and wanted to report it with a
minimal reproducer below.
Summary
For a setjmp/longjmp program, slicing with -c __assert_fail (or line
criterion 17:x) changes semantics: original/unsliced passes, but sliced
fails assertion.
The slice keeps _setjmp and assertion checks, but drops the longjmp
control-transfer path (jumpit()), which makes the remaining path assign
x = 2 and fail assert(x == 1).
Environment
- dg commit:
dc3615d03fedfce62f37604b45d22e31c9d7e557 - slicer:
llvm-slicer(built from this dg checkout) - clang:
Ubuntu clang version 14.0.0-1ubuntu1.1 - lli:
Ubuntu LLVM version 14.0.0 - OS:
Linux ... WSL2 x86_64(kernel5.15.167.4-microsoft-standard-WSL2)
Minimal Reproducer
#include <assert.h>
#include <setjmp.h>
static jmp_buf jb;
static void jumpit(void) {
longjmp(jb, 1);
}
int main(void) {
volatile int x = 0;
if (setjmp(jb) == 0) {
x = 1;
jumpit();
x = 2;
}
assert(x == 1);
return 0;
}Reproduction Steps
cat > /tmp/setjmp_longjmp_misslice.c <<'EOF'
#include <assert.h>
#include <setjmp.h>
static jmp_buf jb;
static void jumpit(void) { longjmp(jb, 1); }
int main(void) {
volatile int x = 0;
if (setjmp(jb) == 0) {
x = 1;
jumpit();
x = 2;
}
assert(x == 1);
return 0;
}
EOF
clang-14 -O0 -g -c -emit-llvm /tmp/setjmp_longjmp_misslice.c -o /tmp/setjmp_longjmp_misslice.bc
lli-14 /tmp/setjmp_longjmp_misslice.bc
llvm-slicer -c __assert_fail /tmp/setjmp_longjmp_misslice.bc -o /tmp/setjmp_longjmp_misslice.assert.sliced.bc
lli-14 /tmp/setjmp_longjmp_misslice.assert.sliced.bc
llvm-slicer -c 17:x /tmp/setjmp_longjmp_misslice.bc -o /tmp/setjmp_longjmp_misslice.line.sliced.bc
lli-14 /tmp/setjmp_longjmp_misslice.line.sliced.bcActual Result
- Unsliced run passes.
- Sliced runs fail:
Assertion `x == 1' failed.
Expected Result
Slicing should preserve semantics for the selected criterion.
The sliced program should not change setjmp/longjmp behavior and should not
turn a passing program into an assertion failure.
IR Evidence
Original IR (relevant):
store volatile i32 1, i32* %x
call void @jumpit()
store volatile i32 2, i32* %x
...
%v = load volatile i32, i32* %x
%ok = icmp eq i32 %v, 1Sliced IR (relevant):
; call to jumpit removed
store volatile i32 2, i32* %x
...
%v = load volatile i32, i32* %x
%ok = icmp eq i32 %v, 1This is a clear semantic mismatch introduced by slicing.
Additional Note
A repository grep for setjmp/longjmp handling (titles/bodies in local issue
snapshot and source-level modeling) shows no direct dedicated modeling path for
this control transfer, which may be related.