Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3ec1f69

Browse files
committed
C++: First query with flow-paths through globals
1 parent aaebe36 commit 3ec1f69

3 files changed

Lines changed: 115 additions & 12 deletions

File tree

cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @description Using externally-controlled format strings in
44
* printf-style functions can lead to buffer overflows
55
* or data representation problems.
6-
* @kind problem
6+
* @kind path-problem
77
* @problem.severity warning
88
* @precision medium
99
* @id cpp/tainted-format-string-through-global
@@ -16,15 +16,24 @@ import cpp
1616
import semmle.code.cpp.security.FunctionWithWrappers
1717
import semmle.code.cpp.security.Security
1818
import semmle.code.cpp.security.TaintTracking
19+
import TaintedWithPath
20+
21+
class Configuration extends TaintTrackingConfiguration {
22+
override predicate isSink(Element tainted) {
23+
exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _))
24+
}
25+
26+
override predicate taintThroughGlobals() { any() }
27+
}
1928

2029
from
21-
PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause,
22-
string globalVar
30+
PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode,
31+
string printfFunction, Expr userValue, string cause
2332
where
2433
printf.outermostWrapperFunctionCall(arg, printfFunction) and
25-
not tainted(_, arg) and
26-
taintedIncludingGlobalVars(userValue, arg, globalVar) and
34+
not taintedWithoutGlobals(arg) and
35+
taintedWithPath(userValue, arg, sourceNode, sinkNode) and
2736
isUserInput(userValue, cause)
2837
select arg,
29-
"This value may flow through $@, originating from $@, and is a formatting argument to " +
30-
printfFunction + ".", globalVarFromId(globalVar), globalVar, userValue, cause
38+
"The value of this argument may come from $@ and is being used as a formatting argument to " +
39+
printfFunction, userValue, cause

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ module TaintedWithPath {
407407
/** Override this to specify which elements are sinks in this configuration. */
408408
abstract predicate isSink(Element e);
409409

410+
/**
411+
* Override this predicate to `any()` to allow taint to flow through global
412+
* variables.
413+
*/
414+
predicate taintThroughGlobals() { none() }
415+
410416
/** Gets a textual representation of this element. */
411417
string toString() { result = "TaintTrackingConfiguration" }
412418
}
@@ -422,6 +428,12 @@ module TaintedWithPath {
422428

423429
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
424430
instructionTaintStep(n1.asInstruction(), n2.asInstruction())
431+
or
432+
exists(TaintTrackingConfiguration cfg | cfg.taintThroughGlobals() |
433+
writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable))
434+
or
435+
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
436+
)
425437
}
426438

427439
override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
@@ -564,4 +576,26 @@ module TaintedWithPath {
564576
tainted = sinkNode.(FinalPathNode).inner()
565577
)
566578
}
579+
580+
private predicate isGlobalVariablePathNode(WrapPathNode n) {
581+
n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable
582+
}
583+
584+
private predicate edgesWithoutGlobals(PathNode a, PathNode b) {
585+
edges(a, b) and
586+
not isGlobalVariablePathNode(a) and
587+
not isGlobalVariablePathNode(b)
588+
}
589+
590+
/**
591+
* Holds if `tainted` can be reached from a taint source without passing
592+
* through a global variable.
593+
*/
594+
predicate taintedWithoutGlobals(Element tainted) {
595+
exists(PathNode sourceNode, FinalPathNode sinkNode |
596+
sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(_) and
597+
edgesWithoutGlobals+(sourceNode, sinkNode) and
598+
tainted = sinkNode.inner()
599+
)
600+
}
567601
}
Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,65 @@
1-
| globalVars.c:27:9:27:12 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv |
2-
| globalVars.c:30:15:30:18 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv |
3-
| globalVars.c:38:9:38:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv |
4-
| globalVars.c:41:15:41:19 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv |
5-
| globalVars.c:50:9:50:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv |
1+
edges
2+
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
3+
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
4+
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
5+
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
6+
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
7+
| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy |
8+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
9+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
10+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
11+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
12+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
13+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
14+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
15+
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
16+
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store |
17+
| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy |
18+
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store |
19+
| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 |
20+
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
21+
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
22+
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... |
23+
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy |
24+
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
25+
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... |
26+
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
27+
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... |
28+
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
29+
nodes
30+
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
31+
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
32+
| globalVars.c:11:22:11:25 | argv | semmle.label | argv |
33+
| globalVars.c:12:2:12:15 | Store | semmle.label | Store |
34+
| globalVars.c:15:21:15:23 | val | semmle.label | val |
35+
| globalVars.c:16:2:16:12 | Store | semmle.label | Store |
36+
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
37+
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
38+
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
39+
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
40+
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
41+
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
42+
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
43+
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
44+
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
45+
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
46+
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
47+
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
48+
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
49+
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
50+
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
51+
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
52+
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
53+
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
54+
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
55+
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
56+
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
57+
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
58+
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
59+
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
60+
#select
61+
| globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |
62+
| globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv |
63+
| globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |
64+
| globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv |
65+
| globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |

0 commit comments

Comments
 (0)