Produce two-color CFG using pure codeql, remove external Python hacks

This commit is contained in:
Michael Hohn
2022-03-05 21:45:03 -08:00
committed by =Michael Hohn
parent 1e8971afab
commit 1b8412ca1d
10 changed files with 5355 additions and 7692 deletions

View File

@@ -1,34 +0,0 @@
/**
* @name Print part of the CFG
* @description Outputs a subset of the control flow graph
* @id cpp/example/polkit/cfg-false-successor
* @kind graph
*/
import cpp
query predicate edges(ControlFlowNode n1, ControlFlowNode n2) {
exists(
RelationalOperation cmp, Parameter argc, ControlFlowNode startFrom, Variable n, ForStmt forloop
|
// minimal restriction: start from comparison
argc.getName() = "argc" and
argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
n.getAnAccess() = cmp.getAnOperand().getAChild*() and
not n instanceof Parameter and
n.getName() = "n" and
forloop.getCondition() = cmp and
forloop.getControlFlowScope().getName() = "main" and
//
startFrom = cmp.getAFalseSuccessor() and
startFrom.getASuccessor*() = n1 and
//
n1.getASuccessor() = n2 and
n1.getControlFlowScope().getName() = "main" and
// polkit has many `main` functions, grab the one from pkexec.c
n1.getLocation().getFile().getBaseName() = "pkexec.c"
)
}
// For reference, see the file
// db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c
// (after extracting src.zip)

View File

@@ -1,37 +0,0 @@
#
# Print a two-colored graph by using two queries' output; one with all nodes for
# layout, the other with false-successor nodes for coloring.
#
#* Add codeql binary PATH
export PATH=$HOME/local/codeql-2.7.6/codeql:"$PATH"
#* Graph in dgml format
cd ~/local/codeql-sample-polkit/
codeql database analyze \
./db/polkit-0.119.db \
./PrintCFG-false-successor.ql \
--rerun \
-j8 -v --ram=16000 \
--search-path $HOME/local/codeql-2.7.6/ql \
--format=dgml \
--output=PrintCFG.dgml
# Clean up the dgml (xml) output
OUT=PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
tidy -xml $OUT | sponge $OUT
# Compare node Ids. They overlap, so graph visuals should work.
em PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
em PrintCFG.dgml/cpp/example/polkit/cfg.dgml
# Produce a full graph with false-successor nodes colored
./dgml2dot -m PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml < \
PrintCFG.dgml/cpp/example/polkit/cfg.dgml > \
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.dot
# Produce the DAG we really want
CFG=PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored
dot -Tpdf < $CFG.dot > $CFG.pdf &
open $CFG.pdf

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -14,6 +14,36 @@ query predicate edges(ControlFlowNode n1, ControlFlowNode n2) {
n1.getLocation().getFile().getBaseName() = "pkexec.c" n1.getLocation().getFile().getBaseName() = "pkexec.c"
} }
query predicate nodes(ControlFlowNode n1, string key, string value) {
exists(
RelationalOperation cmp, Parameter argc, ControlFlowNode startFrom, Variable n, ForStmt forloop
|
// Find the comparison
argc.getName() = "argc" and
argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
n.getAnAccess() = cmp.getAnOperand().getAChild*() and
not n instanceof Parameter and
n.getName() = "n" and
forloop.getCondition() = cmp and
forloop.getControlFlowScope().getName() = "main" and
// Find the false branch's starting node
startFrom = cmp.getAFalseSuccessor() and
//
(edges(n1, _) or edges(_, n1)) and
(
if startFrom.getASuccessor*() = n1
then (
key = "color" and value = "red"
or
key = "line" and value = n1.getLocation().getStartLine().toString()
) else (
key = "color" and value = "black"
or
key = "line" and value = n1.getLocation().getStartLine().toString()
)
)
)
}
// For reference, see the file // For reference, see the file
// db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c // db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c
// (after extracting src.zip) // (after extracting src.zip)

View File

@@ -16,19 +16,21 @@ codeql database analyze \
--format=dgml \ --format=dgml \
--output=PrintCFG.dgml --output=PrintCFG.dgml
PRE=PrintCFG.dgml/cpp/example/polkit/cfg
# Clean up the dgml (xml) output # Clean up the dgml (xml) output
tidy -xml PrintCFG.dgml/cpp/example/polkit/cfg.dgml | sponge PrintCFG.dgml/cpp/example/polkit/cfg.dgml tidy -xml $PRE.dgml | sponge $PRE.dgml
# Convert dgml to dot # Convert dgml to dot
./dgml2dot < PrintCFG.dgml/cpp/example/polkit/cfg.dgml > cfg.dot ./dgml2dot < $PRE.dgml > $PRE.dot
# Produce the DAG we really want # Produce the layed-out DAG
dot -Tpdf < cfg.dot > cfg.pdf dot -Tpdf < $PRE.dot > $PRE.pdf &
open cfg.pdf open $PRE.pdf
# Faster than dot, as sanity check: # Faster than dot, as sanity check:
sfdp -Tpdf < cfg.dot > cfg.sfdp.pdf sfdp -Tpdf < $PRE.dot > $PRE.sfdp.pdf
open cfg.sfdp.pdf open $PRE.sfdp.pdf
#* Full dot graph from codeql #* Full dot graph from codeql
# #