Skip to content

setjmp/longjmp control transfer is missliced #473

@Pipi9221

Description

@Pipi9221

[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 (kernel 5.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.bc

Actual 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, 1

Sliced IR (relevant):

; call to jumpit removed
store volatile i32 2, i32* %x
...
%v = load volatile i32, i32* %x
%ok = icmp eq i32 %v, 1

This 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions