Skip to content

Commit f103d45

Browse files
authored
Merge branch 'main' into atorralba/android-implicit-pending-intents
2 parents 3ff7710 + c41ec1f commit f103d45

File tree

160 files changed

+57757
-48141
lines changed

Some content is hidden

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

160 files changed

+57757
-48141
lines changed

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@
2727
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
2828

2929
# QL for QL reviewers
30-
/ql/ @erik-krogh @tausbn
30+
/ql/ @github/codeql-ql-for-ql-reviewers

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
44

55
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
66

7+
## Change notes
8+
9+
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
710

811
## Submitting a new experimental query
912

cpp/ql/lib/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 0.0.6
2+
13
## 0.0.5
24

35
## 0.0.4
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
5+
more accurate length for integers formatted with `%x`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## 0.0.6

cpp/ql/lib/codeql-pack.release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
lastReleaseVersion: 0.0.5
2+
lastReleaseVersion: 0.0.6

cpp/ql/lib/qlpack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: codeql/cpp-all
2-
version: 0.0.6-dev
2+
version: 0.0.7-dev
33
groups: cpp
44
dbscheme: semmlecode.cpp.dbscheme
55
extractor: cpp

cpp/ql/lib/semmle/code/cpp/commons/Printf.qll

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ private int lengthInBase10(float f) {
382382
result = f.log10().floor() + 1
383383
}
384384

385+
pragma[nomagic]
386+
private predicate isPointerTypeWithBase(Type base, PointerType pt) { base = pt.getBaseType() }
387+
385388
bindingset[expr]
386389
private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Expr expr) {
387390
// we consider the range analysis non trivial if it
@@ -399,6 +402,18 @@ private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Exp
399402
else result = TTypeBoundsAnalysis()
400403
}
401404

405+
/**
406+
* Gets the number of hex digits required to represent the integer represented by `f`.
407+
*
408+
* `f` is assumed to be nonnegative.
409+
*/
410+
bindingset[f]
411+
private int lengthInBase16(float f) {
412+
f = 0 and result = 1
413+
or
414+
result = (f.log2() / 4.0).floor() + 1
415+
}
416+
402417
/**
403418
* A class to represent format strings that occur as arguments to invocations of formatting functions.
404419
*/
@@ -950,19 +965,19 @@ class FormatLiteral extends Literal {
950965
(
951966
conv = ["s", "S"] and
952967
len = "h" and
953-
result.(PointerType).getBaseType() instanceof PlainCharType
968+
isPointerTypeWithBase(any(PlainCharType plainCharType), result)
954969
or
955970
conv = ["s", "S"] and
956971
len = ["l", "w"] and
957-
result.(PointerType).getBaseType() = this.getWideCharType()
972+
isPointerTypeWithBase(this.getWideCharType(), result)
958973
or
959974
conv = "s" and
960975
(len != "l" and len != "w" and len != "h") and
961-
result.(PointerType).getBaseType() = this.getDefaultCharType()
976+
isPointerTypeWithBase(this.getDefaultCharType(), result)
962977
or
963978
conv = "S" and
964979
(len != "l" and len != "w" and len != "h") and
965-
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
980+
isPointerTypeWithBase(this.getNonDefaultCharType(), result)
966981
)
967982
)
968983
}
@@ -1253,23 +1268,42 @@ class FormatLiteral extends Literal {
12531268
or
12541269
this.getConversionChar(n).toLowerCase() = "x" and
12551270
// e.g. "12345678"
1256-
exists(int sizeBytes, int baseLen |
1257-
sizeBytes =
1258-
min(int bytes |
1259-
bytes = this.getIntegralDisplayType(n).getSize()
1271+
exists(int baseLen, int typeBasedBound, int valueBasedBound |
1272+
typeBasedBound =
1273+
min(int digits |
1274+
digits = 2 * this.getIntegralDisplayType(n).getSize()
12601275
or
12611276
exists(IntegralType t |
12621277
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
12631278
|
1264-
t.isUnsigned() and bytes = t.getSize()
1279+
t.isUnsigned() and
1280+
digits = 2 * t.getSize()
12651281
)
12661282
) and
1267-
baseLen = sizeBytes * 2 and
1268-
(
1269-
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
1270-
)
1271-
) and
1272-
reason = TTypeBoundsAnalysis()
1283+
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
1284+
arg = this.getUse().getConversionArgument(n) and
1285+
lower = lowerBound(arg.getFullyConverted()) and
1286+
upper = upperBound(arg.getFullyConverted()) and
1287+
typeLower = exprMinVal(arg.getFullyConverted()) and
1288+
typeUpper = exprMaxVal(arg.getFullyConverted())
1289+
|
1290+
valueBasedBound =
1291+
lengthInBase16(max(float cand |
1292+
// If lower can be negative we use `(unsigned)-1` as the candidate value.
1293+
lower < 0 and
1294+
cand = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
1295+
or
1296+
cand = upper
1297+
)) and
1298+
(
1299+
if lower > typeLower or upper < typeUpper
1300+
then reason = TValueFlowAnalysis()
1301+
else reason = TTypeBoundsAnalysis()
1302+
)
1303+
) and
1304+
baseLen = valueBasedBound.minimum(typeBasedBound) and
1305+
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
1306+
)
12731307
or
12741308
this.getConversionChar(n).toLowerCase() = "p" and
12751309
exists(PointerType ptrType, int baseLen |

cpp/ql/src/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 0.0.6
2+
13
## 0.0.5
24

35
### New Queries

cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import semmle.code.cpp.dataflow.DataFlow
2222
* Holds if `sub` is guarded by a condition which ensures that
2323
* `left >= right`.
2424
*/
25-
pragma[noinline]
25+
pragma[nomagic]
2626
predicate isGuarded(SubExpr sub, Expr left, Expr right) {
27-
exists(GuardCondition guard, int k |
28-
guard.controls(sub.getBasicBlock(), _) and
29-
guard.ensuresLt(left, right, k, sub.getBasicBlock(), false) and
27+
exprIsSubLeftOrLess(pragma[only_bind_into](sub), _) and // Manual magic
28+
exists(GuardCondition guard, int k, BasicBlock bb |
29+
pragma[only_bind_into](bb) = sub.getBasicBlock() and
30+
guard.controls(pragma[only_bind_into](bb), _) and
31+
guard.ensuresLt(left, right, k, bb, false) and
3032
k >= 0
3133
)
3234
}
@@ -36,47 +38,56 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
3638
* `sub.getLeftOperand()`.
3739
*/
3840
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
39-
n.asExpr() = sub.getLeftOperand()
40-
or
41-
exists(DataFlow::Node other |
42-
// dataflow
43-
exprIsSubLeftOrLess(sub, other) and
44-
(
45-
DataFlow::localFlowStep(n, other) or
46-
DataFlow::localFlowStep(other, n)
41+
interestingSubExpr(sub, _) and // Manual magic
42+
(
43+
n.asExpr() = sub.getLeftOperand()
44+
or
45+
exists(DataFlow::Node other |
46+
// dataflow
47+
exprIsSubLeftOrLess(sub, other) and
48+
(
49+
DataFlow::localFlowStep(n, other) or
50+
DataFlow::localFlowStep(other, n)
51+
)
52+
)
53+
or
54+
exists(DataFlow::Node other |
55+
// guard constraining `sub`
56+
exprIsSubLeftOrLess(sub, other) and
57+
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
58+
)
59+
or
60+
exists(DataFlow::Node other, float p, float q |
61+
// linear access of `other`
62+
exprIsSubLeftOrLess(sub, other) and
63+
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
64+
p <= 1 and
65+
q <= 0
66+
)
67+
or
68+
exists(DataFlow::Node other, float p, float q |
69+
// linear access of `n`
70+
exprIsSubLeftOrLess(sub, other) and
71+
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
72+
p >= 1 and
73+
q >= 0
4774
)
48-
)
49-
or
50-
exists(DataFlow::Node other |
51-
// guard constraining `sub`
52-
exprIsSubLeftOrLess(sub, other) and
53-
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
54-
)
55-
or
56-
exists(DataFlow::Node other, float p, float q |
57-
// linear access of `other`
58-
exprIsSubLeftOrLess(sub, other) and
59-
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
60-
p <= 1 and
61-
q <= 0
62-
)
63-
or
64-
exists(DataFlow::Node other, float p, float q |
65-
// linear access of `n`
66-
exprIsSubLeftOrLess(sub, other) and
67-
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
68-
p >= 1 and
69-
q >= 0
7075
)
7176
}
7277

73-
from RelationalOperation ro, SubExpr sub
74-
where
75-
not isFromMacroDefinition(ro) and
78+
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {
7679
not isFromMacroDefinition(sub) and
7780
ro.getLesserOperand().getValue().toInt() = 0 and
7881
ro.getGreaterOperand() = sub and
7982
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
80-
exprMightOverflowNegatively(sub.getFullyConverted()) and // generally catches false positives involving constants
81-
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand())) // generally catches false positives where there's a relation between the left and right operands
83+
// generally catches false positives involving constants
84+
exprMightOverflowNegatively(sub.getFullyConverted())
85+
}
86+
87+
from RelationalOperation ro, SubExpr sub
88+
where
89+
interestingSubExpr(sub, ro) and
90+
not isFromMacroDefinition(ro) and
91+
// generally catches false positives where there's a relation between the left and right operands
92+
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand()))
8293
select ro, "Unsigned subtraction can never be negative."

0 commit comments

Comments
 (0)