|
14 | 14 |
|
15 | 15 | import cpp |
16 | 16 | import semmle.code.cpp.commons.Buffer |
| 17 | +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis |
17 | 18 | import LoopBounds |
18 | 19 |
|
19 | 20 | private predicate staticBufferBase(VariableAccess access, Variable v) { |
@@ -51,6 +52,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) { |
51 | 52 | loop.getStmt().getAChild*() = bufaccess.getEnclosingStmt() and |
52 | 53 | loop.limit() >= bufaccess.bufferSize() and |
53 | 54 | loop.counter().getAnAccess() = bufaccess.getArrayOffset() and |
| 55 | + // Ensure that we don't have an upper bound on the array index that's less than the buffer size. |
| 56 | + not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and |
54 | 57 | msg = |
55 | 58 | "Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " + |
56 | 59 | loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " + |
@@ -94,17 +97,22 @@ class CallWithBufferSize extends FunctionCall { |
94 | 97 | } |
95 | 98 |
|
96 | 99 | int statedSizeValue() { |
97 | | - exists(Expr statedSizeSrc | |
98 | | - DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) and |
99 | | - result = statedSizeSrc.getValue().toInt() |
100 | | - ) |
| 100 | + // `upperBound(e)` defaults to `exprMaxVal(e)` when `e` isn't analyzable. So to get a meaningful |
| 101 | + // result in this case we pick the minimum value obtainable from dataflow and range analysis. |
| 102 | + result = |
| 103 | + upperBound(statedSizeExpr()) |
| 104 | + .minimum(min(Expr statedSizeSrc | |
| 105 | + DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) |
| 106 | + | |
| 107 | + statedSizeSrc.getValue().toInt() |
| 108 | + )) |
101 | 109 | } |
102 | 110 | } |
103 | 111 |
|
104 | 112 | predicate wrongBufferSize(Expr error, string msg) { |
105 | 113 | exists(CallWithBufferSize call, int bufsize, Variable buf, int statedSize | |
106 | 114 | staticBuffer(call.buffer(), buf, bufsize) and |
107 | | - statedSize = min(call.statedSizeValue()) and |
| 115 | + statedSize = call.statedSizeValue() and |
108 | 116 | statedSize > bufsize and |
109 | 117 | error = call.statedSizeExpr() and |
110 | 118 | msg = |
|
0 commit comments