Skip to content

Is it possible to display call path? #5353

Answered by intrigus-lgtm
Marcono1234 asked this question in Q&A
Is it possible to display call path? #5353
Mar 7, 2021 · 1 answers · 2 replies

Is it possible to display a 'call path' with CodeQL? It appears currently only taint / data flow paths are supported. What I am looking for is for example, the path from a method executed on HTTP GET request (regardless of user provided parameters, if any) to a specific method (e.g. System.exit(...) in Java).

Is something like this possible?
I am not sure if such a query would actually be useful (or yields too many false positives), but it might be interesting to see its results.

Yes, this is possible!

The site you linked to mentions it here and here although it's easy too miss or easy to underestimate its potential.

When you use taint or data-flow the edges predicate is defined by the PathGraph module.
But you can also define your own edges query-predicate.

A self-defined query-predicate is used in @agustingianni's blog post. It's relatively easy to port the code to "Java CodeQL".

Here's my code that only creates a path for methods itself and not for the (control flow) basic-blocks.
Link to query

/**
 * @kind path-problem
 */

import java

class StartMethod extends Method {
  StartMethod() { getName() = "validateExpression" }
}

class TargetMethod extends Method {

Replies

1 suggested answer
·
2 replies

Yes, this is possible!

The site you linked to mentions it here and here although it's easy too miss or easy to underestimate its potential.

When you use taint or data-flow the edges predicate is defined by the PathGraph module.
But you can also define your own edges query-predicate.

A self-defined query-predicate is used in @agustingianni's blog post. It's relatively easy to port the code to "Java CodeQL".

Here's my code that only creates a path for methods itself and not for the (control flow) basic-blocks.
Link to query

/**
 * @kind path-problem
 */

import java

class StartMethod extends Method {
  StartMethod() { getName() = "validateExpression" }
}

class TargetMethod extends Method {
  TargetMethod() { getName() = "findValue" }
}

query predicate edges(Method a, Method b) { a.calls(b) }

from TargetMethod end, StartMethod entryPoint
where edges+(entryPoint, end)
select end, entryPoint, end, "Found a path from start to target."
2 replies
@Marcono1234

Thanks a lot for this great answer and the link to this interesting post!

@Marcono1234

It appears there are a few important things regarding path explanations (which are implicitly shown in your example):

  • Explicitly importing DataFlow::PathGraph, as shown in the documentation, is not necessary; in fact if you use the import you are constrained to defining the predicate as predicate edges(PathNode, PathNode) which might not be suitable for all cases (e.g. the one shown in the example)
  • In the select clause you need to use the values of the same type as passed to the edges predicate (not completely sure?); when using different value types the result will not be shown as path explanation. For example in the linked blog post, both the edges predicate and the select clause use end.getBasicBlock(); only using end in the select clause would not generate a path explanation.
  • It looks like start and end need to have a location in source (e.g. they must not be a method from a third party library); otherwise at least https://lgtm.com does not show a path explanation, but only the regular result table.
Answer selected by Marcono1234
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants