Skip to content

Shared: Add support for provenance pretty-printing as a qltest postprocess step. #17011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions java/ql/test/TestUtilities/PrettyPrintModels.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @kind test-postprocess
*/

import codeql.dataflow.test.ProvenancePathGraph
import semmle.code.java.dataflow.ExternalFlow

external predicate queryResults(string relation, int row, int column, string data);

external predicate queryRelations(string relation);

query predicate resultRelations(string relation) { queryRelations(relation) }

module Res = TranslateProvenanceResults<interpretModelForTest/2, queryResults/4>;

from string relation, int row, int column, string data
where Res::results(relation, row, column, data)
select relation, row, column, data
28 changes: 16 additions & 12 deletions java/ql/test/query-tests/security/CWE-078/ExecTainted.expected
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
#select
| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
edges
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:10:61:10:73 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String | provenance | |
| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:42682 |
| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:2 |
| Test.java:7:44:7:69 | ... + ... : String | Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | provenance | |
| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:42682 |
| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:2 |
| Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} : String[] [[]] : String | provenance | |
| Test.java:16:5:16:7 | cmd [post update] : ArrayList [<element>] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:42681 |
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [<element>] : String | provenance | MaD:43744 |
| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:42682 |
| Test.java:16:5:16:7 | cmd [post update] : ArrayList [<element>] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:1 |
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [<element>] : String | provenance | MaD:3 |
| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:2 |
| Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | provenance | |
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... : String | provenance | |
| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:42682 |
| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:2 |
| Test.java:29:44:29:64 | ... + ... : String | Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | provenance | |
| Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String | provenance | |
| Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String | provenance | |
| Test.java:60:20:60:22 | arg : String | Test.java:6:35:6:44 | arg : String | provenance | |
| Test.java:61:23:61:25 | arg : String | Test.java:28:38:28:47 | arg : String | provenance | |
models
| 1 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (List); ; Argument[0]; command-injection; ai-manual |
| 2 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (String[]); ; Argument[0]; command-injection; ai-manual |
| 3 | Summary: java.util; Collection; true; add; ; ; Argument[0]; Argument[this].Element; value; manual |
nodes
| Test.java:6:35:6:44 | arg : String | semmle.label | arg : String |
| Test.java:7:25:7:70 | new ..[] { .. } | semmle.label | new ..[] { .. } |
Expand All @@ -40,9 +50,3 @@ nodes
| Test.java:60:20:60:22 | arg : String | semmle.label | arg : String |
| Test.java:61:23:61:25 | arg : String | semmle.label | arg : String |
subpaths
#select
| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Security/CWE/CWE-078/ExecTainted.ql
query: Security/CWE/CWE-078/ExecTainted.ql
postprocess: TestUtilities/PrettyPrintModels.ql
14 changes: 0 additions & 14 deletions java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-319/HttpsUrls.ql
postprocess: TestUtilities/PrettyPrintModels.ql
66 changes: 57 additions & 9 deletions shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module;

signature predicate interpretModelForTestSig(QlBuiltins::ExtensionId madId, string model);

signature predicate queryResultsSig(string relation, int row, int column, string data);

signature class PathNodeSig {
string toString();
}
Expand All @@ -28,14 +30,14 @@ signature module PathGraphSig<PathNodeSig PathNode> {
predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out);
}

/** Transforms a `PathGraph` by printing the provenance information. */
module ShowProvenance<
interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode,
PathGraphSig<PathNode> PathGraph>
private signature predicate provenanceSig(string model);

private module TranslateModels<
interpretModelForTestSig/2 interpretModelForTest, provenanceSig/1 provenance>
{
private predicate madIds(string madId) {
exists(string model |
PathGraph::edges(_, _, _, model) and
provenance(model) and
model.regexpFind("(?<=MaD:)[0-9]*", _, _) = madId
)
}
Expand All @@ -44,14 +46,15 @@ module ShowProvenance<
madId = rank[r](string madId0 | madIds(madId0) | madId0 order by madId0.toInt())
}

query predicate models(int r, string model) {
/** Lists the renumbered and pretty-printed models used in the edges relation. */
predicate models(int r, string model) {
exists(QlBuiltins::ExtensionId madId |
rankedMadIds(madId.toString(), r) and interpretModelForTest(madId, model)
)
}

private predicate translateModelsPart(string model1, string model2, int i) {
PathGraph::edges(_, _, _, model1) and
provenance(model1) and
exists(string s | model1.splitAt("MaD:", i) = s |
model2 = s and i = 0
or
Expand All @@ -65,21 +68,66 @@ module ShowProvenance<
)
}

private predicate translateModels(string model1, string model2) {
predicate translateModels(string model1, string model2) {
exists(int i |
translateModelsPart(model1, model2, i) and
not translateModelsPart(model1, _, i + 1)
)
}
}

/** Transforms a `PathGraph` by printing the provenance information. */
module ShowProvenance<
interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode,
PathGraphSig<PathNode> PathGraph>
{
private predicate provenance(string model) { PathGraph::edges(_, _, _, model) }

private module Models = TranslateModels<interpretModelForTest/2, provenance/1>;

query predicate models(int r, string model) { Models::models(r, model) }

query predicate edges(PathNode a, PathNode b, string key, string val) {
exists(string model |
PathGraph::edges(a, b, key, model) and
translateModels(model, val)
Models::translateModels(model, val)
)
}

query predicate nodes = PathGraph::nodes/3;

query predicate subpaths = PathGraph::subpaths/4;
}

/** Transforms a `PathGraph` by printing the provenance information. */
module TranslateProvenanceResults<
interpretModelForTestSig/2 interpretModelForTest, queryResultsSig/4 queryResults>
{
private int provenanceColumn() { result = 5 }

private predicate provenance(string model) { queryResults("edges", _, provenanceColumn(), model) }

private module Models = TranslateModels<interpretModelForTest/2, provenance/1>;

predicate results(string relation, int row, int column, string data) {
queryResults(relation, row, column, data) and
(relation != "edges" or column != provenanceColumn())
or
exists(string model |
relation = "edges" and
column = provenanceColumn() and
queryResults(relation, row, column, model) and
Models::translateModels(model, data)
)
or
exists(int r, string model |
Models::models(r, model) and
relation = "models" and
row = r
|
column = 0 and data = r.toString()
or
column = 1 and data = model
)
}
}
Loading