Skip to content

Commit b0882a9

Browse files
committed
Merge branch 'main' into alexdenisov+redsun82/tuple-mangling
2 parents 2fb6cdc + 081c069 commit b0882a9

File tree

113 files changed

+827
-248
lines changed

Some content is hidden

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

113 files changed

+827
-248
lines changed

.github/workflows/check-change-note.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ on:
1111
- "*/ql/lib/**/*.yml"
1212
- "!**/experimental/**"
1313
- "!ql/**"
14-
- "!swift/**"
1514
- ".github/workflows/check-change-note.yml"
1615

1716
jobs:
@@ -32,4 +31,4 @@ jobs:
3231
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3332
run: |
3433
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
35-
grep true -c
34+
grep true -c

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,8 +1640,15 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
16401640
localFlow(instructionNode(e1), instructionNode(e2))
16411641
}
16421642

1643+
/**
1644+
* INTERNAL: Do not use.
1645+
*
1646+
* Ideally this module would be private, but the `asExprInternal` predicate is
1647+
* needed in `DefaultTaintTrackingImpl`. Once `DefaultTaintTrackingImpl` is gone
1648+
* we can make this module private.
1649+
*/
16431650
cached
1644-
private module ExprFlowCached {
1651+
module ExprFlowCached {
16451652
/**
16461653
* Holds if `n` is an indirect operand of a `PointerArithmeticInstruction`, and
16471654
* `e` is the result of loading from the `PointerArithmeticInstruction`.
@@ -1692,7 +1699,8 @@ private module ExprFlowCached {
16921699
* `x[i]` steps to the expression `x[i - 1]` without traversing the
16931700
* entire chain.
16941701
*/
1695-
private Expr asExpr(Node n) {
1702+
cached
1703+
Expr asExprInternal(Node n) {
16961704
isIndirectBaseOfArrayAccess(n, result)
16971705
or
16981706
not isIndirectBaseOfArrayAccess(n, _) and
@@ -1704,7 +1712,7 @@ private module ExprFlowCached {
17041712
* dataflow step.
17051713
*/
17061714
private predicate localStepFromNonExpr(Node n1, Node n2) {
1707-
not exists(asExpr(n1)) and
1715+
not exists(asExprInternal(n1)) and
17081716
localFlowStep(n1, n2)
17091717
}
17101718

@@ -1715,7 +1723,7 @@ private module ExprFlowCached {
17151723
pragma[nomagic]
17161724
private predicate localStepsToExpr(Node n1, Node n2, Expr e2) {
17171725
localStepFromNonExpr*(n1, n2) and
1718-
e2 = asExpr(n2)
1726+
e2 = asExprInternal(n2)
17191727
}
17201728

17211729
/**
@@ -1726,7 +1734,7 @@ private module ExprFlowCached {
17261734
exists(Node mid |
17271735
localFlowStep(n1, mid) and
17281736
localStepsToExpr(mid, n2, e2) and
1729-
e1 = asExpr(n1)
1737+
e1 = asExprInternal(n1)
17301738
)
17311739
}
17321740

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private DataFlow::Node getNodeForSource(Expr source) {
6060
}
6161

6262
private DataFlow::Node getNodeForExpr(Expr node) {
63-
result = DataFlow::exprNode(node)
63+
node = DataFlow::ExprFlowCached::asExprInternal(result)
6464
or
6565
// Some of the sources in `isUserInput` are intended to match the value of
6666
// an expression, while others (those modeled below) are intended to match
@@ -221,7 +221,7 @@ private module Cached {
221221
predicate nodeIsBarrierIn(DataFlow::Node node) {
222222
// don't use dataflow into taint sources, as this leads to duplicate results.
223223
exists(Expr source | isUserInput(source, _) |
224-
node = DataFlow::exprNode(source)
224+
source = DataFlow::ExprFlowCached::asExprInternal(node)
225225
or
226226
// This case goes together with the similar (but not identical) rule in
227227
// `getNodeForSource`.

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ module RangeStage<
729729
) {
730730
exists(SemExpr e, D::Delta d1, D::Delta d2 |
731731
unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and
732-
boundedUpper(e, b, d1) and
732+
boundedUpper(e, b, d2) and
733733
boundedLower(e, b, d2) and
734734
delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2))
735735
)

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/test.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,36 @@ void testInterproc(BigArray *arr) {
7878

7979
addToPointerAndAssign(arr->buf);
8080
}
81+
82+
void testEqRefinement() {
83+
int arr[MAX_SIZE];
84+
85+
for(int i = 0; i <= MAX_SIZE; i++) {
86+
if(i != MAX_SIZE) {
87+
arr[i] = 0; // GOOD
88+
}
89+
}
90+
}
91+
92+
void testEqRefinement2() {
93+
int arr[MAX_SIZE];
94+
95+
int n = 0;
96+
97+
for(int i = 0; i <= MAX_SIZE; i++) {
98+
if(n == 0) {
99+
if(i == MAX_SIZE) {
100+
break;
101+
}
102+
n = arr[i]; // GOOD
103+
continue;
104+
}
105+
106+
if (i == MAX_SIZE || n != arr[i]) {
107+
if (i == MAX_SIZE) {
108+
break;
109+
}
110+
n = arr[i]; // GOOD
111+
}
112+
}
113+
}

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,24 @@ edges
653653
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:6 | xs |
654654
| test.cpp:308:5:308:6 | xs | test.cpp:308:5:308:11 | access to array |
655655
| test.cpp:308:5:308:11 | access to array | test.cpp:308:5:308:29 | Store: ... = ... |
656-
| test.cpp:313:16:313:29 | new[] | test.cpp:314:17:314:18 | xs |
656+
| test.cpp:313:14:313:27 | new[] | test.cpp:314:15:314:16 | xs |
657+
| test.cpp:325:14:325:27 | new[] | test.cpp:326:15:326:16 | xs |
658+
| test.cpp:326:15:326:16 | xs | test.cpp:326:15:326:23 | ... + ... |
659+
| test.cpp:326:15:326:16 | xs | test.cpp:326:15:326:23 | ... + ... |
660+
| test.cpp:326:15:326:16 | xs | test.cpp:338:8:338:15 | * ... |
661+
| test.cpp:326:15:326:16 | xs | test.cpp:341:8:341:17 | * ... |
662+
| test.cpp:326:15:326:23 | ... + ... | test.cpp:342:8:342:17 | * ... |
663+
| test.cpp:326:15:326:23 | ... + ... | test.cpp:342:8:342:17 | * ... |
664+
| test.cpp:338:8:338:15 | * ... | test.cpp:342:8:342:17 | * ... |
665+
| test.cpp:341:8:341:17 | * ... | test.cpp:342:8:342:17 | * ... |
666+
| test.cpp:342:8:342:17 | * ... | test.cpp:333:5:333:21 | Store: ... = ... |
667+
| test.cpp:342:8:342:17 | * ... | test.cpp:341:5:341:21 | Store: ... = ... |
668+
| test.cpp:347:14:347:27 | new[] | test.cpp:348:15:348:16 | xs |
669+
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
670+
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
671+
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:15:350:19 | Load: * ... |
672+
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
673+
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
657674
subpaths
658675
#select
659676
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -679,3 +696,6 @@ subpaths
679696
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
680697
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
681698
| test.cpp:308:5:308:29 | Store: ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
699+
| test.cpp:333:5:333:21 | Store: ... = ... | test.cpp:325:14:325:27 | new[] | test.cpp:333:5:333:21 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:325:14:325:27 | new[] | new[] | test.cpp:326:20:326:23 | size | size |
700+
| test.cpp:341:5:341:21 | Store: ... = ... | test.cpp:325:14:325:27 | new[] | test.cpp:341:5:341:21 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:325:14:325:27 | new[] | new[] | test.cpp:326:20:326:23 | size | size |
701+
| test.cpp:350:15:350:19 | Load: * ... | test.cpp:347:14:347:27 | new[] | test.cpp:350:15:350:19 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:347:14:347:27 | new[] | new[] | test.cpp:348:20:348:23 | size | size |

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,43 @@ void test21() {
310310
}
311311

312312
void test22(unsigned size, int val) {
313-
char *xs = new char[size];
314-
char *end = xs + size; // GOOD
315-
char **current = &end;
316-
do
317-
{
318-
if( *current - xs < 1 ) // GOOD
319-
return;
320-
*--(*current) = 0; // GOOD
321-
val >>= 8;
322-
}
323-
while( val > 0 );
313+
char *xs = new char[size];
314+
char *end = xs + size; // GOOD
315+
char **current = &end;
316+
do {
317+
if (*current - xs < 1) // GOOD
318+
return;
319+
*--(*current) = 0; // GOOD
320+
val >>= 8;
321+
} while (val > 0);
322+
}
323+
324+
void test23(unsigned size, int val) {
325+
char *xs = new char[size];
326+
char *end = xs + size;
327+
char **current = &end;
328+
329+
if (val < 1) {
330+
if(*current - xs < 1)
331+
return;
332+
333+
*--(*current) = 0; // GOOD [FALSE POSITIVE]
334+
return;
335+
}
336+
337+
if (val < 2) {
338+
if(*current - xs < 2)
339+
return;
340+
341+
*--(*current) = 0; // GOOD [FALSE POSITIVE]
342+
*--(*current) = 0; // GOOD
343+
}
344+
}
345+
346+
void test24(unsigned size) {
347+
char *xs = new char[size];
348+
char *end = xs + size;
349+
if (xs < end) {
350+
int val = *xs++; // GOOD [FALSE POSITIVE]
351+
}
324352
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted.ql:9,8-47)
22
WARNING: Predicate tainted has been deprecated and may be removed in future (tainted.ql:20,49-74)
3+
failures
4+
testFailures

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_path_to_sink/tainted.ql

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag
3838
)
3939
}
4040

41-
class IRDefaultTaintTrackingTest extends InlineExpectationsTest {
42-
IRDefaultTaintTrackingTest() { this = "IRDefaultTaintTrackingTest" }
41+
module IRDefaultTaintTrackingTest implements TestSig {
42+
string getARelevantTag() { result = ["ir-path", "ir-sink"] }
4343

44-
override string getARelevantTag() { result = ["ir-path", "ir-sink"] }
45-
46-
override predicate hasActualResult(Location location, string element, string tag, string value) {
44+
predicate hasActualResult(Location location, string element, string tag, string value) {
4745
exists(Element elem, TaintedWithPath::PathNode node, int n |
4846
irTaint(_, node, tag) and
4947
elem = getElementFromPathNode(node) and
@@ -67,12 +65,10 @@ class IRDefaultTaintTrackingTest extends InlineExpectationsTest {
6765
}
6866
}
6967

70-
class AstTaintTrackingTest extends InlineExpectationsTest {
71-
AstTaintTrackingTest() { this = "ASTTaintTrackingTest" }
72-
73-
override string getARelevantTag() { result = "ast" }
68+
module AstTaintTrackingTest implements TestSig {
69+
string getARelevantTag() { result = "ast" }
7470

75-
override predicate hasActualResult(Location location, string element, string tag, string value) {
71+
predicate hasActualResult(Location location, string element, string tag, string value) {
7672
exists(Expr source, Element tainted, int n |
7773
tag = "ast" and
7874
astTaint(source, tainted) and
@@ -100,3 +96,5 @@ class AstTaintTrackingTest extends InlineExpectationsTest {
10096
)
10197
}
10298
}
99+
100+
import MakeTest<MergeTests<IRDefaultTaintTrackingTest, AstTaintTrackingTest>>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted.ql:10,8-47)
22
WARNING: Predicate tainted has been deprecated and may be removed in future (tainted.ql:21,3-28)
3+
failures
4+
testFailures

0 commit comments

Comments
 (0)