Fix incomplete/incorrect PTA when using C++ namespaces & virtual functions #1369
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request fixes a bug that caused call graphs to be incomplete/incorrect when using C++ namespaces and virtual functions.
Currently, whenever namespaces and virtual functions are used with C++ classes, the underlying object's name is used to find the VTable for a called function. However, the name used therein is incorrect (the namespace component is stripped off when it shouldn't be), and causes incomplete and incorrect results to be returned, leading to an incomplete callgraph.
For example, take the following snippets:
Example 1:
This corresponds to the following — expected — callgraph:
Example 2:
This results in the following, incomplete callgraph:
The introduction of the namespaces causes the virtual call not to be found. This is because the set of indirect call edges found in the
AndersenBase::solveConstraints()
function (line 118) is empty in the second example.This set is retrieved from the PAG's indirect callsites
SVFIR::indCallSiteToFunPtrMap
, which is then passed toAndersen::updateCallGraph()
, which again callsBVDataPTAImpl::onTheFlyCallGraphSolve
. This callsPointerAnalysis::resolveCPPIndCalls
, which, by default, will not connect virtual calls based on the Call Hierarchy Analysis (CHA), and thus callsPointerAnalysis::getVFnsFromPts
.This function calls
chgraph->csHasVtblsBasedonCHA(SVFUtil::getSVFCallSite(cs->getCallSite()))
, which returnsfalse
in the second example, because the CHG'sCHG::csToCHAVtblsMap
map has no VTable entries for the given callsite. During construction of the CHG however this map is correctly built (note: without stripping the namespace component from the objects) and contains mappings forn1::Child
and such.However, during lookup, the
getClassNameOfThisPtr
function returns onlyChild
, rather thann1::Child
, causing the lookup to fail, and no call-edge to be created. This is due toinferThisPtrClsName
callingextractClsNamesFromFunc
, which callsupdateClassNameBeforeBrackets
on the demangled name. However, this last function call strips then1::
part from the demangled name incorrectly, causing the broken lookup. Since this function only gets called on this code-path, removing this stripping (which makes it consistent with other places) should be fine and produces correct call graphs for the above examples.I believe this could also be the underlying issue for issue #1301 and possibly issue #1314.