Skip to content

Commit 88eeca3

Browse files
committed
Merge commit '52d8acc1a198c5ea29c1dddceda1d6c0fb75de14' into dataflow-defbyref-to-field
This is a partial merge from master. In particular, it takes in github#3382 and github#3385.
2 parents 5e8bd0a + 52d8acc commit 88eeca3

File tree

71 files changed

+1808
-1111
lines changed

Some content is hidden

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

71 files changed

+1808
-1111
lines changed

CODEOWNERS

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
/cpp/ @Semmle/cpp-analysis
2-
/csharp/ @Semmle/cs
3-
/java/ @Semmle/java
4-
/javascript/ @Semmle/js
5-
/python/ @Semmle/python
1+
/cpp/ @github/codeql-c-analysis
2+
/csharp/ @github/codeql-csharp
3+
/java/ @github/codeql-java
4+
/javascript/ @github/codeql-javascript
5+
/python/ @github/codeql-python
66
/cpp/**/*.qhelp @hubwriter
77
/csharp/**/*.qhelp @jf205
88
/java/**/*.qhelp @felicitymay

cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ where
2121
destBase = baseType(destType) and
2222
destBase.getSize() != sourceBase.getSize() and
2323
not dest.isInMacroExpansion() and
24-
// If the source type is a char* or void* then don't
24+
// If the source type is a `char*` or `void*` then don't
2525
// produce a result, because it is likely to be a false
2626
// positive.
2727
not sourceBase instanceof CharType and

cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ where
2121
destBase = baseType(destType) and
2222
destBase.getSize() != sourceBase.getSize() and
2323
not dest.isInMacroExpansion() and
24-
// If the source type is a char* or void* then don't
24+
// If the source type is a `char*` or `void*` then don't
2525
// produce a result, because it is likely to be a false
2626
// positive.
2727
not sourceBase instanceof CharType and

cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private predicate isCharSzPtrExpr(Expr e) {
2424
from Expr sizeofExpr, Expr e
2525
where
2626
// If we see an addWithSizeof then we expect the type of
27-
// the pointer expression to be char* or void*. Otherwise it
27+
// the pointer expression to be `char*` or `void*`. Otherwise it
2828
// is probably a mistake.
2929
addWithSizeof(e, sizeofExpr, _) and not isCharSzPtrExpr(e)
3030
select sizeofExpr,

cpp/ql/src/semmle/code/cpp/Function.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
103103

104104
/**
105105
* Holds if this function is declared to be `constexpr`.
106+
*
107+
* Note that this does not hold if the function has been declared
108+
* `consteval`.
106109
*/
107110
predicate isDeclaredConstexpr() { this.hasSpecifier("declared_constexpr") }
108111

@@ -115,9 +118,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
115118
* template <typename T> constexpr int g(T x) { return f(x); }
116119
* ```
117120
* `g<int>` is declared constexpr, but is not constexpr.
121+
*
122+
* Will also hold if this function is `consteval`.
118123
*/
119124
predicate isConstexpr() { this.hasSpecifier("is_constexpr") }
120125

126+
/**
127+
* Holds if this function is declared to be `consteval`.
128+
*/
129+
predicate isConsteval() { this.hasSpecifier("is_consteval") }
130+
121131
/**
122132
* Holds if this function is declared with `__attribute__((naked))` or
123133
* `__declspec(naked)`.

cpp/ql/src/semmle/code/cpp/commons/Buffer.qll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,7 @@ int getBufferSize(Expr bufferExpr, Element why) {
9292
// dataflow (all sources must be the same size)
9393
bufferExprNode = DataFlow::exprNode(bufferExpr) and
9494
result =
95-
min(Expr def |
96-
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
97-
|
98-
getBufferSize(def, _)
99-
) and
100-
result =
101-
max(Expr def |
95+
unique(Expr def |
10296
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
10397
|
10498
getBufferSize(def, _)

cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,13 +532,7 @@ library class ExprEvaluator extends int {
532532
interestingVariableAccess(e, va, v, true) and
533533
// All assignments must have the same int value
534534
result =
535-
min(Expr value |
536-
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
537-
|
538-
getValueInternalNonSubExpr(value)
539-
) and
540-
result =
541-
max(Expr value |
535+
unique(Expr value |
542536
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
543537
|
544538
getValueInternalNonSubExpr(value)

cpp/ql/src/semmle/code/cpp/dataflow/EscapesTree.qll

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,14 @@ private predicate referenceFromVariableAccess(VariableAccess va, Expr reference)
183183
)
184184
}
185185

186-
private predicate valueMayEscapeAt(Expr e) {
186+
private predicate addressMayEscapeAt(Expr e) {
187187
exists(Call call |
188188
e = call.getAnArgument().getFullyConverted() and
189189
not stdIdentityFunction(call.getTarget()) and
190190
not stdAddressOf(call.getTarget())
191+
or
192+
e = call.getQualifier().getFullyConverted() and
193+
e.getUnderlyingType() instanceof PointerType
191194
)
192195
or
193196
exists(AssignExpr assign | e = assign.getRValue().getFullyConverted())
@@ -205,8 +208,8 @@ private predicate valueMayEscapeAt(Expr e) {
205208
exists(AsmStmt asm | e = asm.getAChild().(Expr).getFullyConverted())
206209
}
207210

208-
private predicate valueMayEscapeMutablyAt(Expr e) {
209-
valueMayEscapeAt(e) and
211+
private predicate addressMayEscapeMutablyAt(Expr e) {
212+
addressMayEscapeAt(e) and
210213
exists(Type t | t = e.getType().getUnderlyingType() |
211214
exists(PointerType pt |
212215
pt = t
@@ -225,6 +228,22 @@ private predicate valueMayEscapeMutablyAt(Expr e) {
225228
)
226229
}
227230

231+
private predicate lvalueMayEscapeAt(Expr e) {
232+
// A call qualifier, like `q` in `q.f()`, is special in that the address of
233+
// `q` escapes even though `q` is not a pointer or a reference.
234+
exists(Call call |
235+
e = call.getQualifier().getFullyConverted() and
236+
e.getType().getUnspecifiedType() instanceof Class
237+
)
238+
}
239+
240+
private predicate lvalueMayEscapeMutablyAt(Expr e) {
241+
lvalueMayEscapeAt(e) and
242+
// A qualifier of a call to a const member function is converted to a const
243+
// class type.
244+
not e.getType().isConst()
245+
}
246+
228247
private predicate addressFromVariableAccess(VariableAccess va, Expr e) {
229248
pointerFromVariableAccess(va, e)
230249
or
@@ -271,8 +290,11 @@ private module EscapesTree_Cached {
271290
*/
272291
cached
273292
predicate variableAddressEscapesTree(VariableAccess va, Expr e) {
274-
valueMayEscapeAt(e) and
293+
addressMayEscapeAt(e) and
275294
addressFromVariableAccess(va, e)
295+
or
296+
lvalueMayEscapeAt(e) and
297+
lvalueFromVariableAccess(va, e)
276298
}
277299

278300
/**
@@ -301,8 +323,11 @@ private module EscapesTree_Cached {
301323
*/
302324
cached
303325
predicate variableAddressEscapesTreeNonConst(VariableAccess va, Expr e) {
304-
valueMayEscapeMutablyAt(e) and
326+
addressMayEscapeMutablyAt(e) and
305327
addressFromVariableAccess(va, e)
328+
or
329+
lvalueMayEscapeMutablyAt(e) and
330+
lvalueFromVariableAccess(va, e)
306331
}
307332

308333
/**

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,6 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
505505
// Expr -> Expr
506506
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
507507
or
508-
exprToExprStep_nocfg(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr(), nodeTo.asExpr())
509-
or
510508
// Node -> FlowVar -> VariableAccess
511509
exists(FlowVar var |
512510
(
@@ -674,7 +672,7 @@ private module FieldFlow {
674672
exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and
675673
// This configuration should not be able to cross function boundaries, but
676674
// we double-check here just to be sure.
677-
node1.getFunction() = node2.getFunction()
675+
node1.getEnclosingCallable() = node2.getEnclosingCallable()
678676
}
679677
}
680678

cpp/ql/src/semmle/code/cpp/exprs/Call.qll

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ private import semmle.code.cpp.dataflow.EscapesTree
99
*/
1010
abstract class Call extends Expr, NameQualifiableElement {
1111
/**
12-
* Gets the number of actual parameters in this call; use
13-
* `getArgument(i)` with `i` between `0` and `result - 1` to
14-
* retrieve actuals.
12+
* Gets the number of arguments (actual parameters) of this call. The count
13+
* does _not_ include the qualifier of the call, if any.
1514
*/
1615
int getNumberOfArguments() { result = count(this.getAnArgument()) }
1716

@@ -32,21 +31,24 @@ abstract class Call extends Expr, NameQualifiableElement {
3231
Expr getQualifier() { result = this.getChild(-1) }
3332

3433
/**
35-
* Gets an argument for this call.
34+
* Gets an argument for this call. To get the qualifier of this call, if
35+
* any, use `getQualifier()`.
3636
*/
3737
Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 0) }
3838

3939
/**
4040
* Gets the nth argument for this call.
4141
*
42-
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
42+
* The range of `n` is from `0` to `getNumberOfArguments() - 1`. To get the
43+
* qualifier of this call, if any, use `getQualifier()`.
4344
*/
4445
Expr getArgument(int n) { result = this.getChild(n) and n >= 0 }
4546

4647
/**
47-
* Gets a sub expression of the argument at position `index`. If the
48+
* Gets a subexpression of the argument at position `index`. If the
4849
* argument itself contains calls, such calls will be considered
49-
* leafs in the expression tree.
50+
* leaves in the expression tree. The qualifier of the call, if any, is not
51+
* considered to be an argument.
5052
*
5153
* Example: the call `f(2, 3 + 4, g(4 + 5))` has sub expression(s)
5254
* `2` at index 0; `3`, `4`, and `3 + 4` at index 1; and `g(4 + 5)`

0 commit comments

Comments
 (0)