Skip to content

Commit 912dce3

Browse files
authored
Merge branch 'main' into gh-codeql-nightly
2 parents 759fd6c + e23a45d commit 912dce3

File tree

8 files changed

+76
-52
lines changed

8 files changed

+76
-52
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* A new class predicate `MustFlowConfiguration::allowInterproceduralFlow` has been added to the `semmle.code.cpp.ir.dataflow.MustFlow` library. The new predicate can be overridden to disable interprocedural flow.

cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ abstract class MustFlowConfiguration extends string {
3838
*/
3939
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
4040

41+
/** Holds if this configuration allows flow from arguments to parameters. */
42+
predicate allowInterproceduralFlow() { any() }
43+
4144
/**
4245
* Holds if data must flow from `source` to `sink` for this configuration.
4346
*
@@ -204,10 +207,25 @@ private module Cached {
204207
}
205208
}
206209

210+
/**
211+
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
212+
* predicate ensures that joins go from `n` to the result instead of the other
213+
* way around.
214+
*/
215+
pragma[inline]
216+
private Declaration getEnclosingCallable(DataFlow::Node n) {
217+
pragma[only_bind_into](result) = pragma[only_bind_out](n).getEnclosingCallable()
218+
}
219+
207220
/** Holds if `nodeFrom` flows to `nodeTo`. */
208221
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
209222
exists(config) and
210-
Cached::step(nodeFrom, nodeTo)
223+
Cached::step(pragma[only_bind_into](nodeFrom), pragma[only_bind_into](nodeTo)) and
224+
(
225+
config.allowInterproceduralFlow()
226+
or
227+
getEnclosingCallable(nodeFrom) = getEnclosingCallable(nodeTo)
228+
)
211229
or
212230
config.isAdditionalFlowStep(nodeFrom, nodeTo)
213231
}

cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
5252
)
5353
}
5454

55+
// We disable flow into callables in this query as we'd otherwise get a result on this piece of code:
56+
// ```cpp
57+
// int* id(int* px) {
58+
// return px; // this returns the local variable `x`, but it's fine as the local variable isn't declared in this scope.
59+
// }
60+
// void f() {
61+
// int x;
62+
// int* px = id(&x);
63+
// }
64+
// ```
65+
override predicate allowInterproceduralFlow() { none() }
66+
5567
/**
5668
* This configuration intentionally conflates addresses of fields and their object, and pointer offsets
5769
* with their base pointer as this allows us to detect cases where an object's address flows to a
@@ -77,9 +89,6 @@ from
7789
ReturnStackAllocatedMemoryConfig conf
7890
where
7991
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
80-
source.getNode().asInstruction() = var and
81-
// Only raise an alert if we're returning from the _same_ callable as the on that
82-
// declared the stack variable.
83-
var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
92+
source.getNode().asInstruction() = var
8493
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
8594
var.getAst().toString()

cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,6 @@ edges
100100
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference dereference) |
101101
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference to) |
102102
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | Unary |
103-
| test.cpp:225:14:225:15 | px | test.cpp:226:10:226:11 | Load |
104-
| test.cpp:226:10:226:11 | Load | test.cpp:226:10:226:11 | px |
105-
| test.cpp:226:10:226:11 | px | test.cpp:226:10:226:11 | StoreValue |
106-
| test.cpp:231:16:231:17 | & ... | test.cpp:225:14:225:15 | px |
107-
| test.cpp:231:17:231:17 | Unary | test.cpp:231:16:231:17 | & ... |
108-
| test.cpp:231:17:231:17 | x | test.cpp:231:17:231:17 | Unary |
109103
nodes
110104
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
111105
| test.cpp:17:9:17:11 | StoreValue | semmle.label | StoreValue |
@@ -221,13 +215,6 @@ nodes
221215
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
222216
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
223217
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
224-
| test.cpp:225:14:225:15 | px | semmle.label | px |
225-
| test.cpp:226:10:226:11 | Load | semmle.label | Load |
226-
| test.cpp:226:10:226:11 | StoreValue | semmle.label | StoreValue |
227-
| test.cpp:226:10:226:11 | px | semmle.label | px |
228-
| test.cpp:231:16:231:17 | & ... | semmle.label | & ... |
229-
| test.cpp:231:17:231:17 | Unary | semmle.label | Unary |
230-
| test.cpp:231:17:231:17 | x | semmle.label | x |
231218
#select
232219
| test.cpp:17:9:17:11 | StoreValue | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
233220
| test.cpp:25:9:25:11 | StoreValue | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |

java/ql/src/Violations of Best Practice/Naming Conventions/SameNameAsSuper.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ from RefType sub, RefType sup
1616
where
1717
sub.fromSource() and
1818
sup = sub.getASupertype() and
19-
sub.getName() = sup.getName()
19+
pragma[only_bind_out](sub.getName()) = pragma[only_bind_out](sup.getName())
2020
select sub, sub.getName() + " has the same name as its supertype $@.", sup, sup.getQualifiedName()

python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ edges
77
| tarslip.py:40:7:40:39 | ControlFlowNode for Attribute() | tarslip.py:41:24:41:26 | ControlFlowNode for tar |
88
| tarslip.py:56:7:56:39 | ControlFlowNode for Attribute() | tarslip.py:57:5:57:9 | GSSA Variable entry |
99
| tarslip.py:57:5:57:9 | GSSA Variable entry | tarslip.py:59:21:59:25 | ControlFlowNode for entry |
10-
| tarslip.py:79:7:79:39 | ControlFlowNode for Attribute() | tarslip.py:80:5:80:9 | GSSA Variable entry |
11-
| tarslip.py:80:5:80:9 | GSSA Variable entry | tarslip.py:82:21:82:25 | ControlFlowNode for entry |
1210
nodes
1311
| tarslip.py:12:7:12:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
1412
| tarslip.py:13:1:13:3 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
@@ -23,14 +21,10 @@ nodes
2321
| tarslip.py:56:7:56:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
2422
| tarslip.py:57:5:57:9 | GSSA Variable entry | semmle.label | GSSA Variable entry |
2523
| tarslip.py:59:21:59:25 | ControlFlowNode for entry | semmle.label | ControlFlowNode for entry |
26-
| tarslip.py:79:7:79:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
27-
| tarslip.py:80:5:80:9 | GSSA Variable entry | semmle.label | GSSA Variable entry |
28-
| tarslip.py:82:21:82:25 | ControlFlowNode for entry | semmle.label | ControlFlowNode for entry |
2924
subpaths
3025
#select
3126
| tarslip.py:13:1:13:3 | ControlFlowNode for tar | tarslip.py:12:7:12:39 | ControlFlowNode for Attribute() | tarslip.py:13:1:13:3 | ControlFlowNode for tar | Extraction of tarfile from $@ | tarslip.py:12:7:12:39 | ControlFlowNode for Attribute() | a potentially untrusted source |
3227
| tarslip.py:18:17:18:21 | ControlFlowNode for entry | tarslip.py:16:7:16:39 | ControlFlowNode for Attribute() | tarslip.py:18:17:18:21 | ControlFlowNode for entry | Extraction of tarfile from $@ | tarslip.py:16:7:16:39 | ControlFlowNode for Attribute() | a potentially untrusted source |
3328
| tarslip.py:37:17:37:21 | ControlFlowNode for entry | tarslip.py:33:7:33:39 | ControlFlowNode for Attribute() | tarslip.py:37:17:37:21 | ControlFlowNode for entry | Extraction of tarfile from $@ | tarslip.py:33:7:33:39 | ControlFlowNode for Attribute() | a potentially untrusted source |
3429
| tarslip.py:41:24:41:26 | ControlFlowNode for tar | tarslip.py:40:7:40:39 | ControlFlowNode for Attribute() | tarslip.py:41:24:41:26 | ControlFlowNode for tar | Extraction of tarfile from $@ | tarslip.py:40:7:40:39 | ControlFlowNode for Attribute() | a potentially untrusted source |
3530
| tarslip.py:59:21:59:25 | ControlFlowNode for entry | tarslip.py:56:7:56:39 | ControlFlowNode for Attribute() | tarslip.py:59:21:59:25 | ControlFlowNode for entry | Extraction of tarfile from $@ | tarslip.py:56:7:56:39 | ControlFlowNode for Attribute() | a potentially untrusted source |
36-
| tarslip.py:82:21:82:25 | ControlFlowNode for entry | tarslip.py:79:7:79:39 | ControlFlowNode for Attribute() | tarslip.py:82:21:82:25 | ControlFlowNode for entry | Extraction of tarfile from $@ | tarslip.py:79:7:79:39 | ControlFlowNode for Attribute() | a potentially untrusted source |

ruby/ql/lib/codeql/ruby/printAst.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
private import AST
1010
private import codeql.ruby.Regexp as RE
1111
private import codeql.ruby.ast.internal.Synthesis
12+
private import ast.internal.AST
1213

1314
/**
1415
* The query can extend this class to control which nodes are printed.
@@ -35,6 +36,8 @@ private predicate shouldPrintAstEdge(AstNode parent, string edgeName, AstNode ch
3536
any(PrintAstConfiguration config).shouldPrintAstEdge(parent, edgeName, child)
3637
}
3738

39+
private int nonSynthIndex() { result = min([-1, any(int i | exists(getSynthChild(_, i)))]) - 1 }
40+
3841
newtype TPrintNode =
3942
TPrintRegularAstNode(AstNode n) { shouldPrintNode(n) } or
4043
TPrintRegExpNode(RE::RegExpTerm term) {
@@ -112,13 +115,22 @@ class PrintRegularAstNode extends PrintAstNode, TPrintRegularAstNode {
112115
)
113116
}
114117

118+
private int getSynthAstNodeIndex() {
119+
not astNode.isSynthesized() and result = nonSynthIndex()
120+
or
121+
astNode = getSynthChild(astNode.getParent(), result)
122+
}
123+
115124
override int getOrder() {
116125
this =
117126
rank[result](PrintRegularAstNode p, Location l, File f |
118127
l = p.getLocation() and
119128
f = l.getFile()
120129
|
121-
p order by f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), l.getStartColumn()
130+
p
131+
order by
132+
f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), l.getStartColumn(),
133+
l.getEndLine(), l.getEndColumn(), p.getSynthAstNodeIndex()
122134
)
123135
}
124136

0 commit comments

Comments
 (0)