Add a two-color CFG to illustrate the branches following the first for-loop

This includes the scripts, dgml, and pdf output
This commit is contained in:
Michael Hohn
2022-03-05 18:07:10 -08:00
committed by =Michael Hohn
parent 182f7794a6
commit 1e8971afab
6 changed files with 5688 additions and 1 deletions

View File

@@ -0,0 +1,34 @@
/**
* @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

@@ -0,0 +1,37 @@
#
# 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

View File

@@ -5,6 +5,19 @@
import re
import sys
import xml.etree.ElementTree as ET
import argparse
parser = argparse.ArgumentParser(description='Read a dgml file and produce dot output.')
parser.add_argument('-m', '--merge-with', metavar='mergefile', type=str,
help='Color nodes found in main and mergefile to distinguish them')
args = parser.parse_args()
mergenodes = set()
if args.merge_with:
# Form a set of Node Ids to check Node presence later
mergetree = ET.fromstring(open(args.merge_with, 'rb').read())
for node in mergetree.find("{http://schemas.microsoft.com/vs/2009/dgml}Nodes"):
mergenodes.add(node.attrib['Id'])
# Read source
xml = sys.stdin.read()
@@ -20,7 +33,10 @@ for node in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Nodes"):
keys = set(att.keys()) - set(['Id', 'Label'])
prop_l = ['{}="{}"'.format(key, att[key]) for key in keys]
prop_l.append('{}="{}"'.format("label", att["Label"]))
node_s = "nd_{} [{}];".format(att['Id'], ", ".join(prop_l))
node_id = att['Id']
if node_id in mergenodes:
prop_l.append('color=green')
node_s = "nd_{} [{}];".format(node_id, ", ".join(prop_l))
body_l.append(node_s)
for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"):