Skip to content

Commit 5269fb7

Browse files
author
Robert Marsh
authored
Merge pull request #2812 from geoffw0/nospacezero
C++: Improve NoSpaceForZeroTerminator.ql
2 parents 5838df1 + 87781a9 commit 5269fb7

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
1919
| Memory is never freed (`cpp/memory-never-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. |
2020
| Memory may not be freed (`cpp/memory-may-not-be-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. |
2121
| Missing return statement (`cpp/missing-return`) | Fewer false positive results | Functions containing `asm` statements are no longer highlighted by this query. |
22+
| No space for zero terminator (`cpp/no-space-for-terminator`) | More correct results | String arguments to formatting functions are now (usually) expected to be null terminated strings. |
2223
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. |
2324
| No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. |
2425
| Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. |

cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,25 @@ import semmle.code.cpp.models.interfaces.Allocation
2222
predicate terminationProblem(AllocationExpr malloc, string msg) {
2323
// malloc(strlen(...))
2424
exists(StrlenCall strlen | DataFlow::localExprFlow(strlen, malloc.getSizeExpr())) and
25-
// flows into a null-terminated string function
25+
// flows to a call that implies this is a null-terminated string
2626
exists(ArrayFunction af, FunctionCall fc, int arg |
2727
DataFlow::localExprFlow(malloc, fc.getArgument(arg)) and
2828
fc.getTarget() = af and
2929
(
30-
// null terminated string
30+
// flows into null terminated string argument
3131
af.hasArrayWithNullTerminator(arg)
3232
or
33-
// likely a null terminated string (such as `strcpy`, `strcat`)
33+
// flows into likely null terminated string argument (such as `strcpy`, `strcat`)
3434
af.hasArrayWithUnknownSize(arg)
35+
or
36+
// flows into string argument to a formatting function (such as `printf`)
37+
exists(int n, FormatLiteral fl |
38+
fc.getArgument(arg) = fc.(FormattingFunctionCall).getConversionArgument(n) and
39+
fl = fc.(FormattingFunctionCall).getFormat() and
40+
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
41+
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
42+
not fl.hasPrecision(n) // exclude: `%.*s`
43+
)
3544
)
3645
) and
3746
msg = "This allocation does not include space to null-terminate the string."

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/NoSpaceForZeroTerminator.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| test.c:49:20:49:25 | call to malloc | This allocation does not include space to null-terminate the string. |
66
| test.cpp:24:35:24:40 | call to malloc | This allocation does not include space to null-terminate the string. |
77
| test.cpp:45:28:45:33 | call to malloc | This allocation does not include space to null-terminate the string. |
8+
| test.cpp:55:28:55:33 | call to malloc | This allocation does not include space to null-terminate the string. |
89
| test.cpp:63:28:63:33 | call to malloc | This allocation does not include space to null-terminate the string. |
910
| test.cpp:71:28:71:33 | call to malloc | This allocation does not include space to null-terminate the string. |
1011
| test.cpp:79:28:79:33 | call to malloc | This allocation does not include space to null-terminate the string. |

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/test.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void decode(char *dest, char *src);
5151
void wdecode(wchar_t *dest, wchar_t *src);
5252

5353
void bad4(char *str) {
54-
// BAD -- zero-termination proved by wprintf (as parameter) [NOT DETECTED]
54+
// BAD -- zero-termination proved by wprintf (as parameter)
5555
char *buffer = (char *)malloc(strlen(str));
5656
decode(buffer, str);
5757
wprintf(L"%s", buffer);
@@ -107,3 +107,19 @@ void bad9(wchar_t *wstr) {
107107
wcscpy(wbuffer, wstr);
108108
delete wbuffer;
109109
}
110+
111+
void good3(char *str) {
112+
// GOOD -- zero-termination not required for this printf
113+
char *buffer = (char *)malloc(strlen(str));
114+
decode(buffer, str);
115+
wprintf(L"%p", buffer);
116+
free(buffer);
117+
}
118+
119+
void good4(char *str) {
120+
// GOOD -- zero-termination not required for this printf
121+
char *buffer = (char *)malloc(strlen(str));
122+
decode(buffer, str);
123+
wprintf(L"%.*s", strlen(str), buffer);
124+
free(buffer);
125+
}

0 commit comments

Comments
 (0)