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