Skip to main content

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