|
1 | 1 | import cpp |
2 | | -import semmle.code.cpp.dataflow.TaintTracking |
3 | | -private import semmle.code.cpp.dataflow.RecursionPrevention |
4 | | - |
5 | | -/** |
6 | | - * A buffer which includes an allocation size. |
7 | | - */ |
8 | | -abstract class BufferWithSize extends DataFlow::Node { |
9 | | - abstract Expr getSizeExpr(); |
10 | | - |
11 | | - BufferAccess getAnAccess() { |
12 | | - any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer())) |
13 | | - } |
14 | | -} |
15 | | - |
16 | | -/** An allocation function. */ |
17 | | -abstract class Alloc extends Function { } |
18 | | - |
19 | | -/** |
20 | | - * Allocation functions identified by the QL for C/C++ standard library. |
21 | | - */ |
22 | | -class DefaultAlloc extends Alloc { |
23 | | - DefaultAlloc() { allocationFunction(this) } |
24 | | -} |
25 | | - |
26 | | -/** A buffer created through a call to an allocation function. */ |
27 | | -class AllocBuffer extends BufferWithSize { |
28 | | - FunctionCall call; |
29 | | - |
30 | | - AllocBuffer() { |
31 | | - asExpr() = call and |
32 | | - call.getTarget() instanceof Alloc |
33 | | - } |
34 | | - |
35 | | - override Expr getSizeExpr() { result = call.getArgument(0) } |
36 | | -} |
37 | | - |
38 | | -/** |
39 | | - * Find accesses of buffers for which we have a size expression. |
40 | | - */ |
41 | | -private class BufferWithSizeConfig extends TaintTracking::Configuration { |
42 | | - BufferWithSizeConfig() { this = "BufferWithSize" } |
43 | | - |
44 | | - override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) } |
45 | | - |
46 | | - override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() } |
47 | | - |
48 | | - override predicate isSanitizer(DataFlow::Node s) { |
49 | | - s = any(BufferWithSize b) and |
50 | | - s.asExpr().getControlFlowScope() instanceof Alloc |
51 | | - } |
52 | | -} |
| 2 | +import semmle.code.cpp.dataflow.DataFlow |
| 3 | +import semmle.code.cpp.controlflow.Guards |
| 4 | +import semmle.code.cpp.valuenumbering.GlobalValueNumbering |
53 | 5 |
|
54 | 6 | /** |
55 | 7 | * An access (read or write) to a buffer, provided as a pair of |
@@ -172,3 +124,31 @@ class MallocSizeExpr extends BufferAccess, FunctionCall { |
172 | 124 |
|
173 | 125 | override Expr getAccessedLength() { result = getArgument(1) } |
174 | 126 | } |
| 127 | + |
| 128 | +class NetworkFunctionCall extends FunctionCall { |
| 129 | + NetworkFunctionCall() { |
| 130 | + getTarget().hasName("ntohd") or |
| 131 | + getTarget().hasName("ntohf") or |
| 132 | + getTarget().hasName("ntohl") or |
| 133 | + getTarget().hasName("ntohll") or |
| 134 | + getTarget().hasName("ntohs") |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +class NetworkToBufferSizeConfiguration extends DataFlow::Configuration { |
| 139 | + NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" } |
| 140 | + |
| 141 | + override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall } |
| 142 | + |
| 143 | + override predicate isSink(DataFlow::Node node) { |
| 144 | + node.asExpr() = any(BufferAccess ba).getAccessedLength() |
| 145 | + } |
| 146 | + |
| 147 | + override predicate isBarrier(DataFlow::Node node) { |
| 148 | + exists(GuardCondition gc, GVN gvn | |
| 149 | + gc.getAChild*() = gvn.getAnExpr() and |
| 150 | + globalValueNumber(node.asExpr()) = gvn and |
| 151 | + gc.controls(node.asExpr().getBasicBlock(), _) |
| 152 | + ) |
| 153 | + } |
| 154 | +} |
0 commit comments