Skip to content

Commit 361b15b

Browse files
authored
Merge branch 'main' into kaspersv/prevent-python-join-order-regression
2 parents 603a97f + bfe5db2 commit 361b15b

File tree

43 files changed

+2218
-490
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2218
-490
lines changed

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,52 @@ module MergePathGraph<
361361
}
362362
}
363363
}
364+
365+
/**
366+
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
367+
*/
368+
module MergePathGraph3<
369+
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
370+
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
371+
{
372+
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
373+
374+
private module Merged =
375+
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
376+
377+
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
378+
class PathNode instanceof Merged::PathNode {
379+
/** Gets this as a projection on the first given `PathGraph`. */
380+
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
381+
382+
/** Gets this as a projection on the second given `PathGraph`. */
383+
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
384+
385+
/** Gets this as a projection on the third given `PathGraph`. */
386+
PathNode3 asPathNode3() { result = super.asPathNode2() }
387+
388+
/** Gets a textual representation of this element. */
389+
string toString() { result = super.toString() }
390+
391+
/**
392+
* Holds if this element is at the specified location.
393+
* The location spans column `startcolumn` of line `startline` to
394+
* column `endcolumn` of line `endline` in file `filepath`.
395+
* For more information, see
396+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
397+
*/
398+
predicate hasLocationInfo(
399+
string filepath, int startline, int startcolumn, int endline, int endcolumn
400+
) {
401+
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
402+
}
403+
404+
/** Gets the underlying `Node`. */
405+
Node getNode() { result = super.getNode() }
406+
}
407+
408+
/**
409+
* Provides the query predicates needed to include a graph in a path-problem query.
410+
*/
411+
module PathGraph = Merged::PathGraph;
412+
}

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,52 @@ module MergePathGraph<
361361
}
362362
}
363363
}
364+
365+
/**
366+
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
367+
*/
368+
module MergePathGraph3<
369+
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
370+
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
371+
{
372+
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
373+
374+
private module Merged =
375+
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
376+
377+
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
378+
class PathNode instanceof Merged::PathNode {
379+
/** Gets this as a projection on the first given `PathGraph`. */
380+
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
381+
382+
/** Gets this as a projection on the second given `PathGraph`. */
383+
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
384+
385+
/** Gets this as a projection on the third given `PathGraph`. */
386+
PathNode3 asPathNode3() { result = super.asPathNode2() }
387+
388+
/** Gets a textual representation of this element. */
389+
string toString() { result = super.toString() }
390+
391+
/**
392+
* Holds if this element is at the specified location.
393+
* The location spans column `startcolumn` of line `startline` to
394+
* column `endcolumn` of line `endline` in file `filepath`.
395+
* For more information, see
396+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
397+
*/
398+
predicate hasLocationInfo(
399+
string filepath, int startline, int startcolumn, int endline, int endcolumn
400+
) {
401+
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
402+
}
403+
404+
/** Gets the underlying `Node`. */
405+
Node getNode() { result = super.getNode() }
406+
}
407+
408+
/**
409+
* Provides the query predicates needed to include a graph in a path-problem query.
410+
*/
411+
module PathGraph = Merged::PathGraph;
412+
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,52 @@ module MergePathGraph<
361361
}
362362
}
363363
}
364+
365+
/**
366+
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
367+
*/
368+
module MergePathGraph3<
369+
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
370+
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
371+
{
372+
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
373+
374+
private module Merged =
375+
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
376+
377+
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
378+
class PathNode instanceof Merged::PathNode {
379+
/** Gets this as a projection on the first given `PathGraph`. */
380+
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
381+
382+
/** Gets this as a projection on the second given `PathGraph`. */
383+
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
384+
385+
/** Gets this as a projection on the third given `PathGraph`. */
386+
PathNode3 asPathNode3() { result = super.asPathNode2() }
387+
388+
/** Gets a textual representation of this element. */
389+
string toString() { result = super.toString() }
390+
391+
/**
392+
* Holds if this element is at the specified location.
393+
* The location spans column `startcolumn` of line `startline` to
394+
* column `endcolumn` of line `endline` in file `filepath`.
395+
* For more information, see
396+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
397+
*/
398+
predicate hasLocationInfo(
399+
string filepath, int startline, int startcolumn, int endline, int endcolumn
400+
) {
401+
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
402+
}
403+
404+
/** Gets the underlying `Node`. */
405+
Node getNode() { result = super.getNode() }
406+
}
407+
408+
/**
409+
* Provides the query predicates needed to include a graph in a path-problem query.
410+
*/
411+
module PathGraph = Merged::PathGraph;
412+
}

csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ private import semmle.code.csharp.dataflow.TaintTracking2
1818
*/
1919
predicate xssFlow(XssNode source, XssNode sink, string message) {
2020
// standard taint-tracking
21-
exists(
22-
TaintTrackingConfiguration c, DataFlow2::PathNode sourceNode, DataFlow2::PathNode sinkNode
23-
|
21+
exists(XssTracking::PathNode sourceNode, XssTracking::PathNode sinkNode |
2422
sourceNode = source.asDataFlowNode() and
2523
sinkNode = sink.asDataFlowNode() and
26-
c.hasFlowPath(sourceNode, sinkNode) and
24+
XssTracking::flowPath(sourceNode, sinkNode) and
2725
message =
2826
"is written to HTML or JavaScript" +
2927
any(string explanation |
@@ -45,7 +43,7 @@ predicate xssFlow(XssNode source, XssNode sink, string message) {
4543
module PathGraph {
4644
/** Holds if `(pred,succ)` is an edge in the graph of data flow path explanations. */
4745
query predicate edges(XssNode pred, XssNode succ) {
48-
exists(DataFlow2::PathNode a, DataFlow2::PathNode b | DataFlow2::PathGraph::edges(a, b) |
46+
exists(XssTracking::PathNode a, XssTracking::PathNode b | XssTracking::PathGraph::edges(a, b) |
4947
pred.asDataFlowNode() = a and
5048
succ.asDataFlowNode() = b
5149
)
@@ -56,7 +54,7 @@ module PathGraph {
5654

5755
/** Holds if `n` is a node in the graph of data flow path explanations. */
5856
query predicate nodes(XssNode n, string key, string val) {
59-
DataFlow2::PathGraph::nodes(n.asDataFlowNode(), key, val)
57+
XssTracking::PathGraph::nodes(n.asDataFlowNode(), key, val)
6058
or
6159
xssFlow(n, n, _) and
6260
key = "semmle.label" and
@@ -69,13 +67,13 @@ module PathGraph {
6967
* `ret -> out` is summarized as the edge `arg -> out`.
7068
*/
7169
query predicate subpaths(XssNode arg, XssNode par, XssNode ret, XssNode out) {
72-
DataFlow2::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(), ret.asDataFlowNode(),
73-
out.asDataFlowNode())
70+
XssTracking::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(),
71+
ret.asDataFlowNode(), out.asDataFlowNode())
7472
}
7573
}
7674

7775
private newtype TXssNode =
78-
TXssDataFlowNode(DataFlow2::PathNode node) or
76+
TXssDataFlowNode(XssTracking::PathNode node) or
7977
TXssAspNode(AspInlineMember m)
8078

8179
/**
@@ -90,21 +88,25 @@ class XssNode extends TXssNode {
9088
/** Gets the location of this node. */
9189
Location getLocation() { none() }
9290

93-
/** Gets the data flow node corresponding to this node, if any. */
94-
DataFlow2::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
91+
/**
92+
* Gets the data flow node corresponding to this node, if any.
93+
*/
94+
XssTracking::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
9595

9696
/** Gets the ASP inline code element corresponding to this node, if any. */
9797
AspInlineMember asAspInlineMember() { result = this.(XssAspNode).getAspInlineMember() }
9898
}
9999

100-
/** A data flow node, viewed as an XSS flow node. */
100+
/**
101+
* A data flow node, viewed as an XSS flow node.
102+
*/
101103
class XssDataFlowNode extends TXssDataFlowNode, XssNode {
102-
DataFlow2::PathNode node;
104+
XssTracking::PathNode node;
103105

104106
XssDataFlowNode() { this = TXssDataFlowNode(node) }
105107

106108
/** Gets the data flow node corresponding to this node. */
107-
DataFlow2::PathNode getDataFlowNode() { result = node }
109+
XssTracking::PathNode getDataFlowNode() { result = node }
108110

109111
override string toString() { result = node.toString() }
110112

@@ -136,9 +138,11 @@ abstract class Source extends DataFlow::Node { }
136138
abstract class Sanitizer extends DataFlow::ExprNode { }
137139

138140
/**
141+
* DEPRECATED: Use `XssTracking` instead.
142+
*
139143
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
140144
*/
141-
class TaintTrackingConfiguration extends TaintTracking2::Configuration {
145+
deprecated class TaintTrackingConfiguration extends TaintTracking2::Configuration {
142146
TaintTrackingConfiguration() { this = "XSSDataFlowConfiguration" }
143147

144148
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -148,6 +152,29 @@ class TaintTrackingConfiguration extends TaintTracking2::Configuration {
148152
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
149153
}
150154

155+
/**
156+
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
157+
*/
158+
module XssTrackingConfig implements DataFlow::ConfigSig {
159+
/**
160+
* Holds if `source` is a relevant data flow source.
161+
*/
162+
predicate isSource(DataFlow::Node source) { source instanceof Source }
163+
164+
/**
165+
* Holds if `sink` is a relevant data flow sink.
166+
*/
167+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
168+
169+
/**
170+
* Holds if data flow through `node` is prohibited. This completely removes
171+
* `node` from the data flow graph.
172+
*/
173+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
174+
}
175+
176+
module XssTracking = TaintTracking::Global<XssTrackingConfig>;
177+
151178
/** A source of remote user input. */
152179
private class RemoteSource extends Source instanceof RemoteFlowSource { }
153180

csharp/ql/src/API Abuse/FormatInvalid.ql

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,36 @@
1212

1313
import csharp
1414
import semmle.code.csharp.frameworks.Format
15-
import DataFlow::PathGraph
15+
import FormatInvalid::PathGraph
1616

17-
private class FormatConfiguration extends DataFlow::Configuration {
18-
FormatConfiguration() { this = "format" }
17+
module FormatInvalidConfig implements DataFlow::ConfigSig {
18+
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral }
1919

20-
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral }
21-
22-
override predicate isSink(DataFlow::Node n) {
23-
exists(FormatCall c | n.asExpr() = c.getFormatExpr())
24-
}
20+
predicate isSink(DataFlow::Node n) { exists(FormatCall c | n.asExpr() = c.getFormatExpr()) }
2521
}
2622

23+
module FormatInvalid = DataFlow::Global<FormatInvalidConfig>;
24+
2725
private predicate invalidFormatString(
28-
InvalidFormatString src, DataFlow::PathNode source, DataFlow::PathNode sink, string msg,
26+
InvalidFormatString src, FormatInvalid::PathNode source, FormatInvalid::PathNode sink, string msg,
2927
FormatCall call, string callString
3028
) {
3129
source.getNode().asExpr() = src and
3230
sink.getNode().asExpr() = call.getFormatExpr() and
33-
any(FormatConfiguration conf).hasFlowPath(source, sink) and
31+
FormatInvalid::flowPath(source, sink) and
3432
call.hasInsertions() and
3533
msg = "Invalid format string used in $@ formatting call." and
3634
callString = "this"
3735
}
3836

3937
private predicate unusedArgument(
40-
FormatCall call, DataFlow::PathNode source, DataFlow::PathNode sink, string msg,
38+
FormatCall call, FormatInvalid::PathNode source, FormatInvalid::PathNode sink, string msg,
4139
ValidFormatString src, string srcString, Expr unusedExpr, string unusedString
4240
) {
4341
exists(int unused |
4442
source.getNode().asExpr() = src and
4543
sink.getNode().asExpr() = call.getFormatExpr() and
46-
any(FormatConfiguration conf).hasFlowPath(source, sink) and
44+
FormatInvalid::flowPath(source, sink) and
4745
unused = call.getASuppliedArgument() and
4846
not unused = src.getAnInsert() and
4947
not src.getValue() = "" and
@@ -55,13 +53,13 @@ private predicate unusedArgument(
5553
}
5654

5755
private predicate missingArgument(
58-
FormatCall call, DataFlow::PathNode source, DataFlow::PathNode sink, string msg,
56+
FormatCall call, FormatInvalid::PathNode source, FormatInvalid::PathNode sink, string msg,
5957
ValidFormatString src, string srcString
6058
) {
6159
exists(int used, int supplied |
6260
source.getNode().asExpr() = src and
6361
sink.getNode().asExpr() = call.getFormatExpr() and
64-
any(FormatConfiguration conf).hasFlowPath(source, sink) and
62+
FormatInvalid::flowPath(source, sink) and
6563
used = src.getAnInsert() and
6664
supplied = call.getSuppliedArguments() and
6765
used >= supplied and
@@ -71,8 +69,8 @@ private predicate missingArgument(
7169
}
7270

7371
from
74-
Element alert, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, Element extra1,
75-
string extra1String, Element extra2, string extra2String
72+
Element alert, FormatInvalid::PathNode source, FormatInvalid::PathNode sink, string msg,
73+
Element extra1, string extra1String, Element extra2, string extra2String
7674
where
7775
invalidFormatString(alert, source, sink, msg, extra1, extra1String) and
7876
extra2 = extra1 and

0 commit comments

Comments
 (0)