mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #10833 from MathiasVP/repair-badly-bounded-write-2
C++: Prepare `Buffer.qll` for IR-based use-use dataflow
This commit is contained in:
@@ -25,10 +25,24 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
|
||||
* Gets the expression associated with `n`. Unlike `n.asExpr()` this also gets the
|
||||
* expression underlying an indirect dataflow node.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
int getBufferSize(Expr bufferExpr, Element why) {
|
||||
private Expr getExpr(DataFlow::Node n, boolean isIndirect) {
|
||||
result = n.asExpr() and isIndirect = false
|
||||
or
|
||||
result = n.asIndirectExpr() and isIndirect = true
|
||||
}
|
||||
|
||||
private DataFlow::Node exprNode(Expr e, boolean isIndirect) { e = getExpr(result, isIndirect) }
|
||||
|
||||
/**
|
||||
* Holds if `bufferExpr` is an allocation-like expression.
|
||||
*
|
||||
* This includes both actual allocations, as well as various operations that return a pointer to
|
||||
* stack-allocated objects.
|
||||
*/
|
||||
private int isSource(Expr bufferExpr, Element why) {
|
||||
exists(Variable bufferVar | bufferVar = bufferExpr.(VariableAccess).getTarget() |
|
||||
// buffer is a fixed size array
|
||||
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
|
||||
@@ -46,42 +60,12 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
) and
|
||||
result = why.(Expr).getType().(ArrayType).getSize() and
|
||||
not exists(bufferVar.getUnspecifiedType().(ArrayType).getSize())
|
||||
or
|
||||
exists(Class parentClass, VariableAccess parentPtr, int bufferSize |
|
||||
// buffer is the parentPtr->bufferVar of a 'variable size struct'
|
||||
memberMayBeVarSize(parentClass, bufferVar) and
|
||||
why = bufferVar and
|
||||
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
|
||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||
(
|
||||
if exists(bufferVar.getType().getSize())
|
||||
then bufferSize = bufferVar.getType().getSize()
|
||||
else bufferSize = 0
|
||||
) and
|
||||
result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
|
||||
)
|
||||
)
|
||||
or
|
||||
// buffer is a fixed size dynamic allocation
|
||||
result = bufferExpr.(AllocationExpr).getSizeBytes() and
|
||||
why = bufferExpr
|
||||
or
|
||||
exists(DataFlow::ExprNode bufferExprNode |
|
||||
// dataflow (all sources must be the same size)
|
||||
bufferExprNode = DataFlow::exprNode(bufferExpr) and
|
||||
result =
|
||||
unique(Expr def |
|
||||
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
|
||||
|
|
||||
getBufferSize(def, _)
|
||||
) and
|
||||
// find reason
|
||||
exists(Expr def | DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) |
|
||||
why = def or
|
||||
exists(getBufferSize(def, why))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Type bufferType |
|
||||
// buffer is the address of a variable
|
||||
why = bufferExpr.(AddressOfExpr).getAddressable() and
|
||||
@@ -100,3 +84,117 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
result = bufferType.getSize()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the value of `n2 + delta` may be equal to the value of `n1`. */
|
||||
private predicate localFlowIncrStep(DataFlow::Node n1, DataFlow::Node n2, int delta) {
|
||||
DataFlow::localFlowStep(n1, n2) and
|
||||
(
|
||||
exists(IncrementOperation incr |
|
||||
n1.asIndirectExpr() = incr.getOperand() and
|
||||
delta = -1
|
||||
)
|
||||
or
|
||||
exists(DecrementOperation decr |
|
||||
n1.asIndirectExpr() = decr.getOperand() and
|
||||
delta = 1
|
||||
)
|
||||
or
|
||||
exists(AddExpr add, Expr e1, Expr e2 |
|
||||
add.hasOperands(e1, e2) and
|
||||
n1.asIndirectExpr() = e1 and
|
||||
delta = -e2.getValue().toInt()
|
||||
)
|
||||
or
|
||||
exists(SubExpr add, Expr e1, Expr e2 |
|
||||
add.hasOperands(e1, e2) and
|
||||
n1.asIndirectExpr() = e1 and
|
||||
delta = e2.getValue().toInt()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n1` may flow to `n2` without passing through any back-edges.
|
||||
*
|
||||
* Back-edges are excluded to prevent infinite loops on examples like:
|
||||
* ```
|
||||
* while(true) { ++n; }
|
||||
* ```
|
||||
* which, when used in `localFlowStepRec`, would create infinite loop that continuously
|
||||
* increments the `delta` parameter.
|
||||
*/
|
||||
private predicate localFlowNotIncrStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
not localFlowIncrStep(n1, n2, _) and
|
||||
DataFlow::localFlowStep(n1, n2) and
|
||||
not n1 = n2.(DataFlow::SsaPhiNode).getAnInput(true)
|
||||
}
|
||||
|
||||
private predicate localFlowToExprStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
not exists([n1.asExpr(), n1.asIndirectExpr()]) and
|
||||
localFlowNotIncrStep(n1, n2)
|
||||
}
|
||||
|
||||
/** Holds if `mid2 + delta` may be equal to `n1`. */
|
||||
private predicate localFlowStepRec0(DataFlow::Node n1, DataFlow::Node mid2, int delta) {
|
||||
exists(DataFlow::Node mid1, int d1, int d2 |
|
||||
// Or we take a number of steps that adds `d1` to the pointer
|
||||
localFlowStepRec(n1, mid1, d1) and
|
||||
// followed by a step that adds `d2` to the pointer
|
||||
localFlowIncrStep(mid1, mid2, d2) and
|
||||
delta = d1 + d2
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n2 + delta` may be equal to `n1`. */
|
||||
private predicate localFlowStepRec(DataFlow::Node n1, DataFlow::Node n2, int delta) {
|
||||
// Either we take one or more steps that doesn't modify the size of the buffer
|
||||
localFlowNotIncrStep+(n1, n2) and
|
||||
delta = 0
|
||||
or
|
||||
exists(DataFlow::Node mid2 |
|
||||
// Or we step from `n1` to `mid2 + delta`
|
||||
localFlowStepRec0(n1, mid2, delta) and
|
||||
// and finally to the next `ExprNode`.
|
||||
localFlowToExprStep*(mid2, n2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e2` is an expression that is derived from `e1` such that if `e1[n]` is a
|
||||
* well-defined expression for some number `n`, then `e2[n + delta]` is also a well-defined
|
||||
* expression.
|
||||
*/
|
||||
private predicate step(Expr e1, Expr e2, int delta) {
|
||||
exists(Variable bufferVar, Class parentClass, VariableAccess parentPtr, int bufferSize |
|
||||
e1 = parentPtr
|
||||
|
|
||||
bufferVar = e2.(VariableAccess).getTarget() and
|
||||
// buffer is the parentPtr->bufferVar of a 'variable size struct'
|
||||
memberMayBeVarSize(parentClass, bufferVar) and
|
||||
parentPtr = e2.(VariableAccess).getQualifier() and
|
||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||
(
|
||||
if exists(bufferVar.getType().getSize())
|
||||
then bufferSize = bufferVar.getType().getSize()
|
||||
else bufferSize = 0
|
||||
) and
|
||||
delta = bufferSize - parentClass.getSize()
|
||||
)
|
||||
or
|
||||
exists(boolean isIndirect |
|
||||
localFlowStepRec(exprNode(e1, isIndirect), exprNode(e2, isIndirect), delta)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
|
||||
*/
|
||||
int getBufferSize(Expr bufferExpr, Element why) {
|
||||
result = isSource(bufferExpr, why)
|
||||
or
|
||||
exists(Expr e0, int delta, int size |
|
||||
size = getBufferSize(e0, why) and
|
||||
delta = unique(int cand | step(e0, bufferExpr, cand) | cand) and
|
||||
result = size + delta
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| tests.cpp:350:13:350:19 | call to strncat | This 'call to strncat' operation is limited to 100 bytes but the destination is only 50 bytes. |
|
||||
| tests.cpp:452:9:452:15 | call to wcsncpy | This 'call to wcsncpy' operation is limited to 396 bytes but the destination is only 200 bytes. |
|
||||
| tests.cpp:481:9:481:16 | call to swprintf | This 'call to swprintf' operation is limited to 400 bytes but the destination is only 200 bytes. |
|
||||
| tests.cpp:630:13:630:20 | call to swprintf | This 'call to swprintf' operation is limited to 400 bytes but the destination is only 200 bytes. |
|
||||
|
||||
@@ -1,2 +1,13 @@
|
||||
| tests.cpp:45:9:45:14 | call to memcpy | This 'memcpy' operation accesses 32 bytes but the $@ is only 16 bytes. | tests.cpp:32:10:32:18 | charFirst | destination buffer |
|
||||
| tests.cpp:60:9:60:14 | call to memcpy | This 'memcpy' operation accesses 32 bytes but the $@ is only 16 bytes. | tests.cpp:32:10:32:18 | charFirst | destination buffer |
|
||||
| tests.cpp:171:9:171:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | destination buffer |
|
||||
| tests.cpp:172:9:172:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | array |
|
||||
| tests.cpp:192:9:192:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | destination buffer |
|
||||
| tests.cpp:193:9:193:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | array |
|
||||
| tests.cpp:212:9:212:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | destination buffer |
|
||||
| tests.cpp:213:9:213:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | array |
|
||||
| tests.cpp:237:9:237:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:221:36:221:41 | call to alloca | array |
|
||||
| tests.cpp:261:9:261:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:245:10:245:22 | dataBadBuffer | array |
|
||||
| tests.cpp:384:9:384:14 | call to memcpy | This 'memcpy' operation accesses 40 bytes but the $@ is only 10 bytes. | tests.cpp:380:19:380:24 | call to alloca | destination buffer |
|
||||
| tests.cpp:434:9:434:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:422:12:422:26 | new[] | array |
|
||||
| tests.cpp:453:9:453:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:445:12:445:26 | new[] | array |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| tests.cpp:668:9:668:14 | call to strcpy | This 'call to strcpy' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
|
||||
@@ -664,7 +664,7 @@ void CWE121_Stack_Based_Buffer_Overflow__CWE193_char_declare_cpy_12_bad()
|
||||
}
|
||||
{
|
||||
char source[10+1] = SRC_STRING;
|
||||
/* POTENTIAL FLAW: data may not have enough space to hold source */ // [NOT DETECTED]
|
||||
/* POTENTIAL FLAW: data may not have enough space to hold source */
|
||||
strcpy(data, source);
|
||||
printLine(data);
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
| var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'call to strncpy' operation is limited to 1025 bytes but the destination is only 1024 bytes. |
|
||||
| var_size_struct.cpp:103:3:103:9 | call to strncpy | This 'call to strncpy' operation is limited to 129 bytes but the destination is only 128 bytes. |
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
| overflowdestination.cpp:46:2:46:7 | call to memcpy | This 'memcpy' operation accesses 128 bytes but the $@ is only 64 bytes. | overflowdestination.cpp:40:7:40:10 | dest | destination buffer |
|
||||
| tests.cpp:23:2:23:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | destination buffer |
|
||||
| tests.cpp:23:2:23:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | source buffer |
|
||||
| tests.cpp:25:2:25:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | destination buffer |
|
||||
| tests.cpp:25:2:25:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | source buffer |
|
||||
| tests.cpp:172:23:172:31 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:170:17:170:41 | {...} | array |
|
||||
| tests.cpp:176:23:176:30 | access to array | This array indexing operation accesses byte offset 31 but the $@ is only 24 bytes. | tests.cpp:170:17:170:41 | {...} | array |
|
||||
| tests.cpp:222:3:222:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:214:8:214:14 | buffer1 | destination buffer |
|
||||
| tests.cpp:224:3:224:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:215:19:215:30 | new[] | destination buffer |
|
||||
| tests.cpp:226:3:226:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:218:13:218:18 | call to malloc | destination buffer |
|
||||
| tests.cpp:228:3:228:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:218:13:218:18 | call to malloc | destination buffer |
|
||||
| tests.cpp:231:3:231:8 | call to memcmp | This 'memcmp' operation may access 33 bytes but the $@ is only 32 bytes. | tests.cpp:214:8:214:14 | buffer1 | first buffer |
|
||||
| tests.cpp:231:3:231:8 | call to memcmp | This 'memcmp' operation may access 33 bytes but the $@ is only 32 bytes. | tests.cpp:215:19:215:30 | new[] | second buffer |
|
||||
| tests.cpp:244:2:244:8 | call to memmove | This 'memmove' operation accesses 6 bytes but the $@ is only 5 bytes. | tests.cpp:208:25:208:39 | {...} | source buffer |
|
||||
| tests.cpp:245:2:245:8 | call to memmove | This 'memmove' operation accesses 6 bytes but the $@ is only 5 bytes. | tests.cpp:208:25:208:39 | {...} | destination buffer |
|
||||
| tests.cpp:265:2:265:8 | call to wmemset | This 'wmemset' operation accesses 132 bytes but the $@ is only 128 bytes. | tests.cpp:260:10:260:16 | buffer1 | destination buffer |
|
||||
| tests.cpp:266:2:266:8 | call to wmemset | This 'wmemset' operation accesses 128 bytes but the $@ is only 32 bytes. | tests.cpp:261:7:261:13 | buffer2 | destination buffer |
|
||||
| tests.cpp:275:3:275:8 | call to memset | This 'memset' operation accesses 15 bytes but the $@ is only 14 bytes. | tests.cpp:272:18:272:32 | Hello, world! | destination buffer |
|
||||
| tests.cpp:275:3:275:8 | call to memset | This 'memset' operation accesses 15 bytes but the $@ is only 14 bytes. | tests.cpp:274:10:274:15 | string | destination buffer |
|
||||
| tests.cpp:285:3:285:8 | call to memset | This 'memset' operation accesses 128 bytes but the $@ is only 64 bytes. | tests.cpp:283:12:283:23 | new[] | destination buffer |
|
||||
| tests.cpp:292:3:292:8 | call to memset | This 'memset' operation accesses 11 bytes but the $@ is only 10 bytes. | tests.cpp:289:8:289:12 | array | destination buffer |
|
||||
| tests.cpp:310:2:310:7 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer |
|
||||
| tests.cpp:312:2:312:7 | call to memset | This 'memset' operation accesses 17 bytes but the $@ is only 16 bytes. | tests.cpp:298:7:298:12 | buffer | destination buffer |
|
||||
| tests.cpp:314:2:314:7 | call to memset | This 'memset' operation accesses 8 bytes but the $@ is only 4 bytes. | tests.cpp:299:6:299:10 | field | destination buffer |
|
||||
| tests.cpp:327:3:327:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer |
|
||||
| tests.cpp:329:3:329:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer |
|
||||
| tests.cpp:336:3:336:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer |
|
||||
| tests.cpp:346:2:346:14 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:342:7:342:15 | charArray | array |
|
||||
| tests.cpp:349:2:349:14 | access to array | This array indexing operation accesses byte offset 10 but the $@ is only 10 bytes. | tests.cpp:342:7:342:15 | charArray | array |
|
||||
| tests.cpp:350:17:350:29 | access to array | This array indexing operation accesses byte offset 10 but the $@ is only 10 bytes. | tests.cpp:342:7:342:15 | charArray | array |
|
||||
@@ -25,18 +34,45 @@
|
||||
| tests.cpp:361:2:361:16 | access to array | This array indexing operation accesses byte offset 219 but the $@ is only 200 bytes. | tests.cpp:344:11:344:21 | structArray | array |
|
||||
| tests.cpp:362:25:362:39 | access to array | This array indexing operation accesses byte offset 219 but the $@ is only 200 bytes. | tests.cpp:344:11:344:21 | structArray | array |
|
||||
| tests.cpp:365:23:365:34 | access to array | This array indexing operation accesses byte offset 43 but the $@ is only 40 bytes. | tests.cpp:343:6:343:13 | intArray | array |
|
||||
| tests.cpp:373:3:373:13 | access to array | This array indexing operation accesses byte offset 101 but the $@ is only 100 bytes. | tests.cpp:368:47:368:52 | call to malloc | array |
|
||||
| tests.cpp:376:3:376:13 | access to array | This array indexing operation accesses byte offset 101 but the $@ is only 101 bytes. | tests.cpp:369:47:369:52 | call to malloc | array |
|
||||
| tests.cpp:446:3:446:24 | access to array | This array indexing operation accesses a negative index -3 on the $@. | tests.cpp:444:7:444:14 | intArray | array |
|
||||
| tests.cpp:454:3:454:11 | access to array | This array indexing operation accesses a negative index -21 on the $@. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:455:3:455:14 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:456:3:456:11 | access to array | This array indexing operation accesses a negative index -21 on the $@. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:456:3:456:15 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:457:3:457:14 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:459:3:459:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:461:3:461:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array |
|
||||
| tests.cpp:476:2:476:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
|
||||
| tests.cpp:477:2:477:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
|
||||
| tests.cpp:479:2:479:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
|
||||
| tests.cpp:481:2:481:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
|
||||
| tests.cpp:485:2:485:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
|
||||
| tests.cpp:487:2:487:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:473:21:473:26 | call to malloc | array |
|
||||
| tests.cpp:489:2:489:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:473:21:473:26 | call to malloc | array |
|
||||
| tests.cpp:491:2:491:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:474:21:474:26 | call to malloc | array |
|
||||
| tests.cpp:495:2:495:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:474:21:474:26 | call to malloc | array |
|
||||
| tests.cpp:519:3:519:8 | call to memset | This 'memset' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:502:15:502:20 | call to malloc | destination buffer |
|
||||
| tests.cpp:519:3:519:8 | call to memset | This 'memset' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:510:16:510:21 | call to malloc | destination buffer |
|
||||
| tests.cpp:520:3:520:8 | call to memset | This 'memset' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:503:15:503:20 | call to malloc | destination buffer |
|
||||
| tests.cpp:541:6:541:10 | call to fread | This 'fread' operation may access 101 bytes but the $@ is only 100 bytes. | tests.cpp:532:7:532:16 | charBuffer | destination buffer |
|
||||
| tests.cpp:546:6:546:10 | call to fread | This 'fread' operation may access 400 bytes but the $@ is only 100 bytes. | tests.cpp:532:7:532:16 | charBuffer | destination buffer |
|
||||
| tests.cpp:569:6:569:15 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
|
||||
| tests.cpp:575:7:575:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
|
||||
| tests.cpp:577:7:577:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
|
||||
| tests.cpp:579:6:579:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
|
||||
| tests.cpp:586:6:586:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
|
||||
| tests_restrict.c:12:2:12:7 | call to memcpy | This 'memcpy' operation accesses 2 bytes but the $@ is only 1 byte. | tests_restrict.c:7:6:7:13 | smallbuf | source buffer |
|
||||
| unions.cpp:26:2:26:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:21:10:21:11 | mu | destination buffer |
|
||||
| unions.cpp:27:2:27:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||
| unions.cpp:29:2:29:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||
| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||
| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:16:7:16:11 | large | destination buffer |
|
||||
| var_size_struct.cpp:71:3:71:8 | call to memset | This 'memset' operation accesses 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:67:35:67:40 | call to malloc | destination buffer |
|
||||
| var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'strncpy' operation may access 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:67:35:67:40 | call to malloc | destination buffer |
|
||||
| var_size_struct.cpp:87:3:87:19 | access to array | This array indexing operation accesses byte offset 67 but the $@ is only 64 bytes. | var_size_struct.cpp:82:35:82:40 | call to malloc | array |
|
||||
| var_size_struct.cpp:99:3:99:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
| var_size_struct.cpp:101:3:101:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
| var_size_struct.cpp:103:3:103:9 | call to strncpy | This 'strncpy' operation may access 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| overflowdestination.cpp:46:20:46:30 | sizeof(<expr>) | Potential buffer-overflow: 'dest' has size 64 not 128. |
|
||||
| tests.cpp:23:33:23:49 | sizeof(<expr>) | Potential buffer-overflow: 'bigbuffer' has size 10 not 20. |
|
||||
| tests.cpp:25:33:25:49 | sizeof(<expr>) | Potential buffer-overflow: 'smallbuffer' has size 10 not 20. |
|
||||
| tests.cpp:163:3:163:11 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||
| tests.cpp:164:8:164:16 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||
|
||||
@@ -454,7 +454,7 @@ void test17(long long *longArray)
|
||||
multi[-5][5] = 0; // BAD: underrun write [INCORRECT MESSAGE]
|
||||
multi[5][-5] = 0; // DUBIOUS: underrun write (this one is still within the bounds of the whole array)
|
||||
multi[-5][-5] = 0; // BAD: underrun write [INCORRECT MESSAGE]
|
||||
multi[0][-5] = 0; // BAD: underrun write [NOT DETECTED]
|
||||
multi[0][-5] = 0; // BAD: underrun write
|
||||
|
||||
multi[15][5] = 0; // BAD: overrun write
|
||||
multi[5][15] = 0; // DUBIOUS: overrun write (this one is still within the bounds of the whole array)
|
||||
@@ -476,23 +476,23 @@ void test18()
|
||||
p1[-1] = 0; // BAD: underrun write
|
||||
p2[-1] = 0; // BAD: underrun write
|
||||
p2++;
|
||||
p2[-1] = 0; // GOOD
|
||||
p2[-1] = 0; // GOOD [FALSE POSITIVE]
|
||||
|
||||
p3[-1] = 0; // BAD
|
||||
while (*p3 != 0) {
|
||||
p3 = update(p3);
|
||||
}
|
||||
p3[-1] = 0; // GOOD
|
||||
p3[-1] = 0; // GOOD [FALSE POSITIVE]
|
||||
|
||||
p4[-1] = 0; // BAD: underrun write
|
||||
p4++;
|
||||
p4[-1] = 0; // GOOD
|
||||
p4[-1] = 0; // GOOD [FALSE POSITIVE]
|
||||
|
||||
p5[-1] = 0; // BAD
|
||||
while (*p5 != 0) {
|
||||
p5 = update(p5);
|
||||
}
|
||||
p5[-1] = 0; // GOOD
|
||||
p5[-1] = 0; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test19(bool b)
|
||||
@@ -517,7 +517,7 @@ void test19(bool b)
|
||||
if (b)
|
||||
{
|
||||
memset(p1, 0, 20); // BAD
|
||||
memset(p2, 0, 20); // GOOD
|
||||
memset(p2, 0, 20); // GOOD [FALSE POSITIVE]
|
||||
memset(p3, 0, 20); // GOOD
|
||||
}
|
||||
}
|
||||
@@ -572,7 +572,7 @@ void test21(bool cond)
|
||||
if (cond)
|
||||
{
|
||||
ptr++;
|
||||
if (ptr[-1] == 0) { return; } // GOOD: accesses buffer[0]
|
||||
if (ptr[-1] == 0) { return; } // GOOD: accesses buffer[0] [FALSE POSITIVE]
|
||||
} else {
|
||||
if (ptr[-1] == 0) { return; } // BAD: accesses buffer[-1]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
| tests2.cpp:17:3:17:8 | call to wcscpy | This 'call to wcscpy' operation requires 12 bytes but the destination is only 8 bytes. |
|
||||
| tests2.cpp:22:3:22:8 | call to wcscpy | This 'call to wcscpy' operation requires 16 bytes but the destination is only 12 bytes. |
|
||||
| tests2.cpp:27:3:27:8 | call to wcscpy | This 'call to wcscpy' operation requires 20 bytes but the destination is only 16 bytes. |
|
||||
| tests2.cpp:31:3:31:8 | call to wcscpy | This 'call to wcscpy' operation requires 24 bytes but the destination is only 20 bytes. |
|
||||
| tests2.cpp:36:3:36:8 | call to wcscpy | This 'call to wcscpy' operation requires 28 bytes but the destination is only 24 bytes. |
|
||||
| tests2.cpp:41:3:41:8 | call to wcscpy | This 'call to wcscpy' operation requires 32 bytes but the destination is only 28 bytes. |
|
||||
| tests2.cpp:46:3:46:8 | call to wcscpy | This 'call to wcscpy' operation requires 36 bytes but the destination is only 32 bytes. |
|
||||
| tests.c:54:3:54:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:58:3:58:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:62:17:62:24 | buffer10 | This 'scanf string argument' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
@@ -10,4 +17,6 @@
|
||||
| tests.c:186:3:186:9 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 2 bytes. |
|
||||
| tests.c:189:3:189:9 | call to sprintf | This 'call to sprintf' operation requires 3 bytes but the destination is only 2 bytes. |
|
||||
| unions.c:26:2:26:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 15 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
| var_size_struct.cpp:22:3:22:8 | call to strcpy | This 'call to strcpy' operation requires 10 bytes but the destination is only 9 bytes. |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| tests.cpp:272:2:272:8 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
|
||||
| tests.cpp:273:2:273:8 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
|
||||
| tests.cpp:308:3:308:9 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
|
||||
| tests.cpp:321:2:321:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
|
||||
| tests.cpp:324:3:324:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
|
||||
|
||||
Reference in New Issue
Block a user