japaric / cargo-call-stack

Whole program static stack analysis
Apache License 2.0
560 stars 50 forks source link

Fix parser error on `undef` type in argument list of tail call. #83

Closed hydra closed 1 year ago

hydra commented 1 year ago

LLVM output was generated by rustc nightly-2022-11-16.

I ran into an issue with the parser in the tool and found and 'fixed' the issue.

Note: I wasn't able to run the integration tests, they ALL fail on my machine, but I don't think the code change I made is the cause. I have an underlying issue with the rustc linker failing to link targets due to an bug that is fixed, but still unreleased. (See https://github.com/rust-lang/rust/issues/88704)

The specific line that fails to parse is line 3 in the example.

tail call void %1(i32 noundef 0, i32 undef) #39, !dbg !104902

Specifically, it's missing handling for undef after the i32 type.

japaric commented 1 year ago

thanks for the fix! bors merge

I'm curious about what kind of program would produce a call with a undef value. I would naively think that if undef appears in the llvm-ir then the program has undefined behavior but I guess it could be fine depending on the signature of the function being called.

bors[bot] commented 1 year ago

Build succeeded:

japaric commented 1 year ago

release v0.1.14 includes this fix

hydra commented 1 year ago

I'm curious about what kind of program would produce a call with a undef value. I would naively think that if undef appears in the llvm-ir then the program has undefined behavior but I guess it could be fine depending on the signature of the function being called.

Here's the code, obfuscated.

struct A {}
struct B {}

pub static mut STATIC_A: Option<A> = None;
pub static mut STATIC_B: Option<B> = None;

enum E { E1, E2(u32), E3(u32), E4 }

pub fn callback(e: E) -> () {
    unsafe {
        match (&mut B, &mut A, e) {
            (Some(b), _, E::E1) => b.b1(),
            (Some(_), Some(a), E::E2(n)) => a.a1(n as u8),
            (Some(_), Some(a), E::E3(n)) => a.a2(0xfe),
            (Some(b), _, E::E4) => b.b2(),
            (_, _, _) => (),
        }
    }
}