Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVFG does not use indirect call edges to join formal and actual parameters #1279

Open
acidghost opened this issue Dec 11, 2023 · 15 comments
Open

Comments

@acidghost
Copy link
Contributor

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: svfg-direct

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:
svfg-indir

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.

@yuleisui
Copy link
Collaborator

Did you try ‘wpa -ander -svfg ‘?

@yuleisui
Copy link
Collaborator

I think you might have to update the svfg by calling its ‘updatecallgraph’ method to connect indirect edges

@acidghost
Copy link
Contributor Author

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.

@yuleisui
Copy link
Collaborator

Could you change ‘ LLVMFuzzerTestOneInput’ to be ‘main’?

@acidghost
Copy link
Contributor Author

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;
}

@yuleisui
Copy link
Collaborator

I am not available to debug now. The easiest way is to debug into ‘ updateCallGraph’ to see what is happening there.

@yuleisui
Copy link
Collaborator

@jumormt could you have a quick Look at this issue?

@acidghost
Copy link
Contributor Author

The issue seems to be related to these lines

SVF/svf/lib/Graphs/VFG.cpp

Lines 990 to 991 in a83aec2

if (fun_arg->isPointer() && cs_arg->isPointer())
connectAParamAndFParam(cs_arg, fun_arg, callBlockNode, csId, edges);

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?

@yuleisui
Copy link
Collaborator

Yes, this is the problem and indirectly called function should be done the same way as the original SVFG

@acidghost
Copy link
Contributor Author

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?

@acidghost
Copy link
Contributor Author

I just tried to commend out the if branch that checks if the argument is a pointer and it seems to be working.

@jumormt
Copy link
Contributor

jumormt commented Dec 12, 2023

Hi @acidghost , can you try this patch #1282 to check if it fixes your issue?

@yuleisui
Copy link
Collaborator

@acidghost could you try the patch before I merge?

@acidghost
Copy link
Contributor Author

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.

@yuleisui
Copy link
Collaborator

Good!

yuleisui added a commit that referenced this issue Dec 12, 2023
(fix issue #1279) connect actual to formal vfgnode for full svfg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants