SVF
SVF copied to clipboard
SVFG does not use indirect call edges to join formal and actual parameters
I'm trying to use SVFG to compute a def-use graph in order to compute a thin backward interprocedural slice from a Value
.
The following case produces an SVFG as I would expect:
#include <stddef.h>
#include <stdint.h>
int myFunc(int A) {
// target
return A + 42;
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size < 1)
return 1;
int Type = Data[0];
myFunc(Type);
return 0;
}
The SVFG for the above example clearly shows a path from, e.g., LoadSVFGNode ID 18
(bottom left in figure) to the 0th argument of LLVMFuzzerTestOneInput
:
If I instead call the function indirectly:
// myFunc(Type);
int (*Fn)(int) = myFunc;
Fn(Type);
Then the SVFG for this version does not link the actual and formal parameter of the indirectly called function:
I verified that the indirect call gets resolved correctly by PTA. What am I missing?
Bitcode: https://godbolt.org/z/rjM9ban1r.
The code I'm using to build the SVFG is the same as the example pass.
Did you try ‘wpa -ander -svfg ‘?
I think you might have to update the svfg by calling its ‘updatecallgraph’ method to connect indirect edges
Did you try ‘wpa -ander -svfg ‘?
I'm running equivalent code:
auto *LLVMModuleSet = SVF::LLVMModuleSet::getLLVMModuleSet();
auto *SVFModule = LLVMModuleSet->buildSVFModule(M);
SVF::SVFIRBuilder Builder(SVFModule);
auto *PAG = Builder.build();
auto *Andersen = SVF::AndersenWaveDiff::createAndersenWaveDiff(PAG);
SVF::SVFGBuilder SvfBuilder(true);
SVF::SVFG *SVFG = SvfBuilder.buildFullSVFG(Andersen);
SVFG->updateCallGraph(Andersen);
// [...]
SVFG->dump("svfg");
// clean up memory
// delete SVFG;
SVF::AndersenWaveDiff::releaseAndersenWaveDiff();
SVF::SVFIR::releaseSVFIR();
SVF::LLVMModuleSet::getLLVMModuleSet()->dumpModulesToFile(".svf.bc");
SVF::LLVMModuleSet::releaseLLVMModuleSet();
I think you might have to update the svfg by calling its ‘updatecallgraph’ method to connect indirect edges
I tried that but the result is the same.
Could you change ‘ LLVMFuzzerTestOneInput’ to be ‘main’?
I tried with the following but the result is the same.
#include <stddef.h>
#include <stdint.h>
int myFunc(int A) {
// target
return A + 42;
}
// int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
int main(int argc, char **argv) {
// if (Size < 1)
// return 1;
// int Type = Data[0];
if (argc < 2)
return 1;
int Type = argv[1][0];
// myFunc(Type);
int (*Fn)(int) = myFunc;
Fn(Type);
return 0;
}
I am not available to debug now. The easiest way is to debug into ‘ updateCallGraph’ to see what is happening there.
@jumormt could you have a quick Look at this issue?
The issue seems to be related to these lines https://github.com/SVF-tools/SVF/blob/a83aec286b249675a56f1b48b987ceb4d8672b69/svf/lib/Graphs/VFG.cpp#L990-L991
Because the argument is not a pointer it does not connect it with the callsite parameter:
Matching ValVar ID: 67
%19 = load i32, i32* %6, align 4, !dbg !36 { "ln": 21, "cl": 6, "fl": "test-indir.c" } and ValVar ID: 7
i32 %0 { 0th arg myFunc "ln": 4, "file": "test-indir.c" }
pointers? 0 0
I'm wondering, why does it need function arguments to be pointers in this case (i.e. calling the function indirectly) and does not have this requirement if the function is called directly?
Yes, this is the problem and indirectly called function should be done the same way as the original SVFG
Yes, this is the problem and indirectly called function should be done the same way as the original SVFG
Does it mean that updateCallGraph
needs to be properly implemented for SVFG and should not rely on VFG::updateCallGraph
?
I just tried to commend out the if branch that checks if the argument is a pointer and it seems to be working.
Hi @acidghost , can you try this patch #1282 to check if it fixes your issue?
@acidghost could you try the patch before I merge?
Seems to be working also for larger examples. Thank you very much!
I'll do more complex testing and reopen if I find something awry.
Good!