SVF-tools / SVF

Static Value-Flow Analysis Framework for Source Code
http://svf-tools.github.io/SVF/
Other
1.35k stars 427 forks source link

Incomplete Pointer Analysis #524

Open Flokka opened 2 years ago

Flokka commented 2 years ago

Analysing the following code with SVF returns no targets for the indirect call structA->f() in CallF. I would expect SVF to return FuncA.

#include <stdio.h>
#include <stdlib.h>

typedef struct StructA
{
    int foo;
    int (*f)(void);
} StructA;

int FuncA() {
    return 1;
}

__attribute__((noinline))
int CallF(StructA *structA) {
    int ret = structA->f();
    return ret;
}

int main() {
    StructA *structA = malloc(sizeof(StructA));
    structA->f = FuncA;

    int ret = CallF(structA);
    printf("ret: %d\n", ret);  
    return 0;
}

The code was compiled using clang -c -emit-llvm -O3 svf_no_targets.c giving this .bc file. Running svf-ex svf_no_targets.bc -print-fp prints "!!!has no targets!!!" for the indirect call structA->f().

yuleisui commented 2 years ago

Thanks for reporting this. I had a debug for your case. It looks to me that the optimized bc does not follow the standard type system, so SVF was not able to know make a proper field-sensitive analysis. However, if you compile using clang -O0, SVF works fine.

Let us look at the two getelementptr instructions in CallF and main when accessing the second field f of StructA.

CallF

%2 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i64 0, i32 1

main

  %1 = tail call noalias dereferenceable_or_null(16) i8* @malloc(i64 16) #4
  %2 = bitcast i8* %1 to %struct.StructA*
  %3 = getelementptr inbounds i8, i8* %1, i64 8

The first one uses standard field offset (based on the struct type), while the second one uses byte offset after optimization. Therefore SVF will not fetch the correct field for the second getelementptr (SVF does not support byte offset field-sensitivity now). In fact, this optimization looks odd and it should also use the same way to retrieve the field pointer as the one in CallF since the bitcast was done just before the getelementptr. I believe this should be reported to llvm-dev to seek advice and reasons.