Complex Steps

Complex Steps are CPGQL Steps which combine the functionality of one or more Node-Type Steps, Repeat Steps, Filter Steps, Core Steps or Execution Directives. They are represented by one or more Directives and can be of three types: Generic Complex Steps, Call Graph Steps or Dataflow Complex Steps.

Generic Complex Steps #

dump #

dump is a Complex Step which executes the traversal and returns the value of the CODE property of the nodes it suffixes with syntax-highlighting.

joern> cpg.method.name("main").dump
res0: List[String] = List(
  """int main(int argc, char *argv[]) { /* <=== */
  if (argc > 1 && strcmp(argv[1], "42") == 0) {
    fprintf(stderr, "It depends!\n");
    exit(42);
  }
  printf("What is the meaning of life?\n");
  exit(0);
}"""
)

dumpRaw #

dumpRaw is a Complex Step which executes the traversal and returns the value of the CODE property of the nodes it suffixes.

joern> cpg.method.name("main").dumpRaw
res0: List[String] = List(
  """int main(int argc, char *argv[]) { /* <=== */
  if (argc > 1 && strcmp(argv[1], "42") == 0) {
    fprintf(stderr, "It depends!\n");
    exit(42);
  }
  printf("What is the meaning of life?\n");
  exit(0);
}"""
)

tagList #

tagList is a Complex Step which executes the traversal and returns the list of all TAG nodes found at each node visited by the traversal it suffixes.

joern> cpg.method.tagList 
res0: List[List[TagBase]] = List(List(NewTag("MY_TAG", "")))

Call Graph Steps #

Call Graph Steps are Complex Steps which traverse the nodes of a Code Property Graph which represent a program’s Call Graph.

The following examples are run on the simple program named X42:

public class X42 {
  public static void main(String[] args) {
    if (args.length > 0 && args[0].equals("42")) {
      System.err.println("It depends!");
      System.exit(42);
    }
    System.out.println("What is the meaning of life?");
    System.exit(0);
  }
}

callee #

callee is a Call Graph Step which lists all nodes representing Call Graph callees of the traversed nodes.

joern> cpg.method.name("main").callee.name.l 
res0: List[String] = List(
  "printf",
  "exit",
  "exit",
  "<operator>.logicalAnd",
  "<operator>.greaterThan",
  "<operator>.equals",
  "fprintf",
  "strcmp",
  "<operator>.indirectIndexAccess"
)

caller #

caller is a Call Graph Step which lists all nodes representing Call Graph callers of the traversed nodes.

joern> cpg.method.name("exit").caller.code.l 
res0: List[String] = List("main (int argc,char *argv[])", "main (int argc,char *argv[])")

callIn #

callIn is a Call Graph Step which lists all nodes representing Call Graph parent call-sites of the traversed nodes.

joern> cpg.method.name("exit").callIn.code.l 
res0: List[String] = List("exit(0)", "exit(42)")

inCall #

inCall is a Call Graph Step which lists all nodes representing surrounding Call Graph call-sites of the traversed nodes.

joern> cpg.call.name("<operator>.indirectIndexAccess").inCall.code.l 
res0: List[String] = List("strcmp(argv[1], \"42\")")

Dataflow Steps #

Dataflow Steps are Complex Steps which traverse the nodes of a Code Property Graph which represent a program’s data-flow. controlledBy, flows, source, sink, reachableBy are all CPGQL Components that are combined to construct Dataflow Steps.