SVF-tools / SVF

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

Type inference failure for linked list #1442

Open Qcloud1223 opened 5 months ago

Qcloud1223 commented 5 months ago

Hi,

I was trying to play with type inference under SVF using linked list, and found an unexpected result. Here is a minimal reproducible example:

struct ll
{
    int a;
    ll *next;
};

int main()
{
    ll node;
    node.next = new ll;
    node.next->a = 1;

    return 0;
}

And (related part of) its PAG is:

    Node0x55f8222e1180 [shape=record,shape=box,label="{[main] ValVar ID: 30\n   %3 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #2 }"];
    Node0x55f8222e1180 -> Node0x55f822317e60[color=blue];
    Node0x55f8222ea110 [shape=record,shape=box3d,label="{[main] FIObjVar ID: 31 (base object)\n   %3 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #2 }"];
    Node0x55f8222ea110 -> Node0x55f8222e1180[color=green];

So the PAG node ID of the object on heap is 31.

The type inference result for this object is:

(gdb) p *pag->getGNode(31)->getType()
$10 = {_vptr.SVFType = 0x55555682f698 <vtable for SVF::SVFIntegerType+16>, static svfPtrTy = 0x5555568df290, 
  static svfI8Ty = 0x5555568caea0, kind = 2, typeinfo = 0x5555568ea490, isSingleValTy = true, byteSize = 1}

which presents the default type SVFIntegerType, indicating that type inference does not work correctly.

Here is the IR of main:

define dso_local noundef i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca %struct.ll, align 8
  store i32 0, ptr %1, align 4
  %3 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #2
  %4 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
  store ptr %3, ptr %4, align 8
  %5 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
  %6 = load ptr, ptr %5, align 8
  %7 = getelementptr inbounds %struct.ll, ptr %6, i32 0, i32 0
  store i32 1, ptr %7, align 8
  ret i32 0
}

I believe in the bitcode, store ptr %3, ptr %4 and %4 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1 together is enough to infer %3 is also pointing to struct ll, but SVF does not seem to catch that.

@jumormt Could you kindly help me have a look at this issue? I'm a little confused even after single-stepping SVF.

jumormt commented 5 months ago

Thanks for reporting. Should be fixed via PR #1443. Actually the type inference site for %3 should be %7 = getelementptr inbounds %struct.ll, ptr %6, i32 0, i32 0 because %6 and %3 are aliases.