Skip to content

Commit 64f8316

Browse files
committed
C++: Tidy up the ql file and accept test changes.
1 parent 1e32728 commit 64f8316

File tree

3 files changed

+31
-51
lines changed

3 files changed

+31
-51
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,54 +11,32 @@
1111
*/
1212

1313
import cpp
14+
import semmle.code.cpp.models.implementations.Strcat
1415
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1516

1617
/**
17-
* A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`.
18+
* Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and
19+
* destination arguments, respectively.
1820
*/
19-
class WrongCallStrncat extends FunctionCall {
20-
Expr leftsomeExpr;
21-
22-
WrongCallStrncat() {
23-
this.getTarget().hasGlobalOrStdName("strncat") and
24-
// the expression of the first argument in `strncat` and `strnlen` is identical
25-
globalValueNumber(this.getArgument(0)) =
26-
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
27-
// using a string constant often speaks of manually calculating the length of the required buffer.
28-
(
29-
not this.getArgument(1) instanceof StringLiteral and
30-
not this.getArgument(1) instanceof CharLiteral
31-
) and
32-
// for use in predicates
33-
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
34-
}
35-
36-
/**
37-
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
38-
*/
39-
predicate isExpressionEqualSizeof() {
40-
// the left side of the expression `someExpr` is `sizeof(buf)`.
41-
globalValueNumber(this.getArgument(0)) =
42-
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
43-
or
44-
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
45-
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
46-
}
47-
48-
/**
49-
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
50-
*/
51-
predicate isVariableEqualValueSizegBuffer() {
52-
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
53-
exists(AllocationExpr alc |
54-
leftsomeExpr.(VariableAccess).getTarget() =
55-
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
56-
)
57-
}
21+
predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
22+
exists(StrcatFunction strcat |
23+
strcat = call.getTarget() and
24+
sizeArg = call.getArgument(strcat.getParamSize()) and
25+
destArg = call.getArgument(strcat.getParamDest())
26+
)
5827
}
5928

60-
from WrongCallStrncat sc
29+
from FunctionCall call, Expr sizeArg, Expr destArg, SubExpr sub, int n
6130
where
62-
sc.isExpressionEqualSizeof() or
63-
sc.isVariableEqualValueSizegBuffer()
64-
select sc, "if the used buffer is full, writing out of the buffer is possible"
31+
interestringCallWithArgs(call, sizeArg, destArg) and
32+
// The destination buffer is an array of size n
33+
destArg.getUnspecifiedType().(ArrayType).getSize() = n and
34+
// The size argument is equivalent to a subtraction
35+
globalValueNumber(sizeArg).getAnExpr() = sub and
36+
// ... where the left side of the subtraction is the constant n
37+
globalValueNumber(sub.getLeftOperand()).getAnExpr().getValue().toInt() = n and
38+
// ... and the right side of the subtraction is a call to `strlen` where the argument is the
39+
// destination buffer.
40+
globalValueNumber(sub.getRightOperand()).getAnExpr().(StrlenCall).getStringExpr() =
41+
globalValueNumber(destArg).getAnExpr()
42+
select call, "Possible out-of-bounds write due to incorrect size argument."
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
| test.c:8:3:8:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
2-
| test.c:17:3:17:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
3-
| test.c:25:3:25:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
1+
| test.c:8:3:8:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
2+
| test.c:9:3:9:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
3+
| test.c:17:3:17:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
4+
| test.c:18:3:18:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
5+
| test.c:46:3:46:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ void strncat_test1(char *s) {
66
char buf[80];
77
strncat(buf, s, sizeof(buf) - strlen(buf) - 1); // GOOD
88
strncat(buf, s, sizeof(buf) - strlen(buf)); // BAD
9-
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED]
9+
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD
1010
}
1111

1212
#define MAX_SIZE 80
@@ -15,14 +15,14 @@ void strncat_test2(char *s) {
1515
char buf[MAX_SIZE];
1616
strncat(buf, s, MAX_SIZE - strlen(buf) - 1); // GOOD
1717
strncat(buf, s, MAX_SIZE - strlen(buf)); // BAD
18-
strncat(buf, "fix", MAX_SIZE - strlen(buf)); // BAD [NOT DETECTED]
18+
strncat(buf, "fix", MAX_SIZE - strlen(buf)); // BAD
1919
}
2020

2121
void strncat_test3(char *s) {
2222
int len = 80;
2323
char* buf = (char *) malloc(len);
2424
strncat(buf, s, len - strlen(buf) - 1); // GOOD
25-
strncat(buf, s, len - strlen(buf)); // BAD
25+
strncat(buf, s, len - strlen(buf)); // BAD [NOT DETECTED]
2626
strncat(buf, "fix", len - strlen(buf)); // BAD [NOT DETECTED]
2727
}
2828

@@ -43,7 +43,7 @@ void strncat_test5(char* s, struct buffers* buffers) {
4343
unsigned len_array = strlen(buffers->array);
4444
unsigned max_size = sizeof(buffers->array);
4545
unsigned free_size = max_size - len_array;
46-
strncat(buffers->array, s, free_size); // BAD [NOT DETECTED]
46+
strncat(buffers->array, s, free_size); // BAD
4747
}
4848

4949
void strlen_test1(){

0 commit comments

Comments
 (0)