Skip to content

Commit f22d87b

Browse files
authored
Merge pull request #14771 from MathiasVP/fix-missing-unbounded-write-results
C++: Fix missing results in `cpp/unbounded-write`
2 parents e11a688 + 967bbbc commit f22d87b

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,25 @@ predicate isUnboundedWrite(BufferWrite bw) {
5252
* Holds if `e` is a source buffer going into an unbounded write `bw` or a
5353
* qualifier of (a qualifier of ...) such a source.
5454
*/
55-
predicate unboundedWriteSource(Expr e, BufferWrite bw) {
56-
isUnboundedWrite(bw) and e = bw.getASource()
55+
predicate unboundedWriteSource(Expr e, BufferWrite bw, boolean qualifier) {
56+
isUnboundedWrite(bw) and e = bw.getASource() and qualifier = false
5757
or
58-
exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier())
58+
exists(FieldAccess fa | unboundedWriteSource(fa, bw, _) and e = fa.getQualifier()) and
59+
qualifier = true
5960
}
6061

6162
predicate isSource(FS::FlowSource source, string sourceType) { source.getSourceType() = sourceType }
6263

63-
predicate isSink(DataFlow::Node sink, BufferWrite bw) {
64-
unboundedWriteSource(sink.asIndirectExpr(), bw)
64+
predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) {
65+
unboundedWriteSource(sink.asIndirectExpr(), bw, qualifier)
6566
or
6667
// `gets` and `scanf` reads from stdin so there's no real input.
6768
// The `BufferWrite` library models this as the call itself being
6869
// the source. In this case we mark the output argument as being
6970
// the sink so that we report a path where source = sink (because
7071
// the same output argument is also included in `isSource`).
7172
bw.getASource() = bw and
72-
unboundedWriteSource(sink.asDefiningArgument(), bw)
73+
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier)
7374
}
7475

7576
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
@@ -84,9 +85,9 @@ predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
8485
module Config implements DataFlow::ConfigSig {
8586
predicate isSource(DataFlow::Node source) { isSource(source, _) }
8687

87-
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
88+
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
8889

89-
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
90+
predicate isBarrierOut(DataFlow::Node node) { isSink(node, _, false) }
9091

9192
predicate isBarrier(DataFlow::Node node) {
9293
// Block flow if the node is guarded by any <, <= or = operations.
@@ -116,7 +117,7 @@ from BufferWrite bw, Flow::PathNode source, Flow::PathNode sink, string sourceTy
116117
where
117118
Flow::flowPath(source, sink) and
118119
isSource(source.getNode(), sourceType) and
119-
isSink(sink.getNode(), bw)
120+
isSink(sink.getNode(), bw, _)
120121
select bw, source, sink,
121122
"This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.",
122123
source.getNode(), sourceType
Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
edges
22
| main.cpp:6:27:6:30 | argv indirection | main.cpp:10:20:10:23 | argv indirection |
3-
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:618:32:618:35 | argv indirection |
3+
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:631:32:631:35 | argv indirection |
44
| tests.cpp:613:19:613:24 | source indirection | tests.cpp:615:17:615:22 | source indirection |
5-
| tests.cpp:618:32:618:35 | argv indirection | tests.cpp:643:9:643:15 | access to array indirection |
6-
| tests.cpp:643:9:643:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
5+
| tests.cpp:622:19:622:24 | source indirection | tests.cpp:625:2:625:16 | ... = ... indirection |
6+
| tests.cpp:625:2:625:16 | ... = ... indirection | tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] |
7+
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | tests.cpp:628:14:628:14 | s indirection [home indirection] |
8+
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:14:628:19 | home indirection |
9+
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:16:628:19 | home indirection |
10+
| tests.cpp:628:16:628:19 | home indirection | tests.cpp:628:14:628:19 | home indirection |
11+
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:656:9:656:15 | access to array indirection |
12+
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:657:9:657:15 | access to array indirection |
13+
| tests.cpp:656:9:656:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
14+
| tests.cpp:657:9:657:15 | access to array indirection | tests.cpp:622:19:622:24 | source indirection |
715
nodes
816
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
917
| main.cpp:10:20:10:23 | argv indirection | semmle.label | argv indirection |
1018
| tests.cpp:613:19:613:24 | source indirection | semmle.label | source indirection |
1119
| tests.cpp:615:17:615:22 | source indirection | semmle.label | source indirection |
12-
| tests.cpp:618:32:618:35 | argv indirection | semmle.label | argv indirection |
13-
| tests.cpp:643:9:643:15 | access to array indirection | semmle.label | access to array indirection |
20+
| tests.cpp:622:19:622:24 | source indirection | semmle.label | source indirection |
21+
| tests.cpp:625:2:625:16 | ... = ... indirection | semmle.label | ... = ... indirection |
22+
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | semmle.label | s indirection [post update] [home indirection] |
23+
| tests.cpp:628:14:628:14 | s indirection [home indirection] | semmle.label | s indirection [home indirection] |
24+
| tests.cpp:628:14:628:19 | home indirection | semmle.label | home indirection |
25+
| tests.cpp:628:16:628:19 | home indirection | semmle.label | home indirection |
26+
| tests.cpp:631:32:631:35 | argv indirection | semmle.label | argv indirection |
27+
| tests.cpp:656:9:656:15 | access to array indirection | semmle.label | access to array indirection |
28+
| tests.cpp:657:9:657:15 | access to array indirection | semmle.label | access to array indirection |
1429
subpaths
1530
#select
1631
| tests.cpp:615:2:615:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:615:17:615:22 | source indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |
32+
| tests.cpp:628:2:628:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:628:14:628:19 | home indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |

cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,19 @@ void test24(char* source) {
615615
strcpy(buffer, source); // BAD
616616
}
617617

618+
struct my_struct {
619+
char* home;
620+
};
621+
622+
void test25(char* source) {
623+
my_struct s;
624+
625+
s.home = source;
626+
627+
char buf[100];
628+
strcpy(buf, s.home); // BAD
629+
}
630+
618631
int tests_main(int argc, char *argv[])
619632
{
620633
long long arr17[19];
@@ -641,6 +654,7 @@ int tests_main(int argc, char *argv[])
641654
test22(argc == 0, argv[0]);
642655
test23();
643656
test24(argv[0]);
657+
test25(argv[0]);
644658

645659
return 0;
646660
}

0 commit comments

Comments
 (0)