Common Queries

note

The following examples were written for the source code of the VLC Media Player v3.0.8. You can download the source code here.

Basic Analysis

Methods

  • List all methods that match .*parse.* to the shell
ocular> cpg.method.name(".*parse.*").name.l
  • Dump all methods that match .*parse.* to the shell (syntax-highlighted)
ocular> cpg.method.name(".*parse.*").dump
  • Create K-V pair of all methods that match .*parse.* and their code
ocular> cpg.method.name(".*parse.*").map( m=> (m.name, m.start.dump)).l
  • Dump all methods that match .*parse.* to file (no highlighting)
ocular> cpg.method.name(".*parse.*").dumpRaw |> "/tmp/foo.c"
  • View all methods that match .*parse.* in a pager (e.g., less)
ocular> browse(cpg.method.name(".*parse.*").dump)
  • Dump dot representations of ASTs for all methods that match parse into file
ocular> cpg.method.name("parse_public_key_packet").dot |> "/tmp/foo.dot"
  • Find all local variables defined in a method
ocular> cpg.method.name("parse_public_key_packet").local.name.l
  • Find which file and line number they are in
ocular> cpg.method.name("parse_public_key_packet").location.map( x=> (x.lineNumber.get, x.filename)).l
  • Find the type of the first local variable defined in a method
ocular> cpg.method.name("parse_public_key_packet").local.typ.name.l.head
  • Find all outgoing calls (call-sites) in a method
ocular> cpg.method.name("parse_public_key_packet").callOut.name.l
  • Find which method calls a method
ocular> cpg.method.name("parse_public_key_packet").caller.name.l

Types and Filters

  • List all local variables of type vlc_.*
ocular> cpg.types.name("vlc_.*").localsOfType.name.l
  • Find member variables of a struct
ocular> cpg.types.name("vlc_log_t").map( x=> (x.name, x.start.member.name.l)).l
  • Find local variables and filter them by their type
ocular> cpg.local.where(_.typ.name("vlc_log_t")).name.l
  • Which method are they used in?
ocular> cpg.local.where(_.typ.name("vlc_log_t")).method.dump
  • Get the filenames where these methods are
ocular> cpg.local.where(_.typ.name("vlc_log_t")).method.file.name.l

Insights

Overview

  • Identify functions with more than 4 parameters
ocular> cpg.method.filter(_.parameter.size > 4).name.l
  • Identify functions with > 4 control structures (cyclomatic complexity)
ocular> cpg.method.filter(_.controlStructure.size > 4).name.l
  • Identify functions with more than 500 lines of code
ocular> cpg.method.filter(_.numberOfLines >= 500).name.l
  • Identify functions with multiple return statements
ocular> cpg.method.filter(_.ast.isReturn.l.size > 1).name.l
  • Identify functions with more than 4 loop statements (including loops nested inside other loops)
ocular> cpg.method.filter(_.ast.isControlStructure.parserTypeName("(For|Do|While).*").size > 4).name.l
  • Identify functions with nesting depth larger than 3
ocular> cpg.method.filter(_.depth(_.isControlStructure) > 3).name.l

Calls into libraries

  • All names of external methods used by the program
ocular> cpg.method.external.name.l.distinct.sorted
  • All calls to strcpy
ocular> cpg.call("str.*").code.l
  • All methods that call strcpy
ocular> cpg.call("str.*").method.name.l
  • Looking into parameters: second argument to sprintf is NOT a literal
ocular> cpg.call("sprintf").argument(2).whereNot(_.isLiteral).code.l
  • Quickly see this method above
ocular> cpg.call("sprintf").argument(2).whereNot(_.isLiteral).dump