mirror of
https://github.com/hohn/codeql-sample-polkit.git
synced 2025-12-16 13:53:04 +01:00
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:
committed by
=Michael Hohn
parent
182f7794a6
commit
1e8971afab
34
PrintCFG-false-successor.ql
Normal file
34
PrintCFG-false-successor.ql
Normal 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)
|
||||||
37
PrintCFG-false-successor.sh
Normal file
37
PrintCFG-false-successor.sh
Normal 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
|
||||||
|
|
||||||
3032
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.dot
Normal file
3032
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.dot
Normal file
File diff suppressed because it is too large
Load Diff
BIN
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.pdf
Normal file
BIN
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.pdf
Normal file
Binary file not shown.
2568
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
Normal file
2568
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
Normal file
File diff suppressed because it is too large
Load Diff
18
dgml2dot
18
dgml2dot
@@ -5,6 +5,19 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import xml.etree.ElementTree as ET
|
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
|
# Read source
|
||||||
xml = sys.stdin.read()
|
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'])
|
keys = set(att.keys()) - set(['Id', 'Label'])
|
||||||
prop_l = ['{}="{}"'.format(key, att[key]) for key in keys]
|
prop_l = ['{}="{}"'.format(key, att[key]) for key in keys]
|
||||||
prop_l.append('{}="{}"'.format("label", att["Label"]))
|
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)
|
body_l.append(node_s)
|
||||||
|
|
||||||
for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"):
|
for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"):
|
||||||
|
|||||||
Reference in New Issue
Block a user