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 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"):
|
||||
|
||||
Reference in New Issue
Block a user