Skip to content

Commit 11786cd

Browse files
authored
Add Tests and handle additional scenario:
- Pointer case: sizeof(pointer) gives pointer size (e.g., 8 bytes), which is completely wrong
1 parent 47486a4 commit 11786cd

File tree

3 files changed

+94
-10
lines changed

3 files changed

+94
-10
lines changed

cpp/ql/src/Critical/OverflowCalculated.ql

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @name Buffer overflow from insufficient space or incorrect size calculation
33
* @description A buffer allocated using 'malloc' may not have enough space for a string being copied into it, or wide character functions may receive incorrect size parameters causing buffer overrun. Make sure that buffers contain enough room for strings (including zero terminator) and that size parameters are correctly calculated.
44
* @kind problem
5-
* @precision medium
65
* @id cpp/overflow-calculated
76
* @problem.severity warning
87
* @security-severity 9.8
@@ -43,20 +42,33 @@ predicate spaceProblem(FunctionCall append, string msg) {
4342

4443
predicate wideCharSizeofProblem(FunctionCall call, string msg) {
4544
exists(
46-
Variable buffer, SizeofExprOperator sizeofOp, ArrayType arrayType
45+
Variable buffer, SizeofExprOperator sizeofOp
4746
|
4847
// Function call is to wcsftime
4948
call.getTarget().hasGlobalOrStdName("wcsftime") and
5049
// Second argument (count parameter) is a sizeof operation
5150
call.getArgument(1) = sizeofOp and
5251
// The sizeof is applied to a buffer variable
5352
sizeofOp.getExprOperand() = buffer.getAnAccess() and
54-
// The buffer is an array of wchar_t
55-
arrayType = buffer.getType() and
56-
arrayType.getBaseType().hasName("wchar_t") and
57-
msg =
58-
"Using sizeof(" + buffer.getName() + ") passes byte count instead of wchar_t element count to wcsftime. " +
59-
"Use sizeof(" + buffer.getName() + ")/sizeof(wchar_t) or array length instead."
53+
(
54+
// Case 1: Array of wchar_t - sizeof gives bytes instead of element count
55+
exists(ArrayType arrayType |
56+
arrayType = buffer.getType() and
57+
arrayType.getBaseType().hasName("wchar_t") and
58+
msg =
59+
"Using sizeof(" + buffer.getName() + ") passes byte count instead of wchar_t element count to wcsftime. " +
60+
"Use sizeof(" + buffer.getName() + ")/sizeof(wchar_t) or array length instead."
61+
)
62+
or
63+
// Case 2: Pointer to wchar_t - sizeof gives pointer size, which is completely wrong
64+
exists(PointerType ptrType |
65+
ptrType = buffer.getType() and
66+
ptrType.getBaseType().hasName("wchar_t") and
67+
msg =
68+
"Using sizeof(" + buffer.getName() + ") passes pointer size instead of buffer size to wcsftime. " +
69+
"Pass the actual element count or use a length variable instead."
70+
)
71+
)
6072
)
6173
}
6274

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
| tests2.cpp:34:4:34:9 | call to strcat | This buffer only contains enough room for 'str1' (copied on line 33) |
2-
| tests2.cpp:52:4:52:9 | call to strcat | This buffer only contains enough room for 'str1' (copied on line 51) |
1+
| tests2.cpp:48:4:48:9 | call to strcat | This buffer only contains enough room for 'str1' (copied on line 47) |
2+
| tests2.cpp:66:4:66:9 | call to strcat | This buffer only contains enough room for 'str1' (copied on line 65) |
3+
| tests2.cpp:118:4:118:11 | call to wcsftime | Using sizeof(buf) passes byte count instead of wchar_t element count to wcsftime. Use sizeof(buf)/sizeof(wchar_t) or array length instead. |
4+
| tests2.cpp:142:4:142:11 | call to wcsftime | Using sizeof(smallBuf) passes byte count instead of wchar_t element count to wcsftime. Use sizeof(smallBuf)/sizeof(wchar_t) or array length instead. |
5+
| tests2.cpp:151:5:151:12 | call to wcsftime | Using sizeof(dynamicBuf) passes pointer size instead of buffer size to wcsftime. Pass the actual element count or use a length variable instead. |

cpp/ql/test/query-tests/Critical/OverflowCalculated/tests2.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,22 @@
22

33
typedef unsigned int size_t;
44

5+
// Time structures and functions for wcsftime tests
6+
struct tm {
7+
int tm_sec;
8+
int tm_min;
9+
int tm_hour;
10+
int tm_mday;
11+
int tm_mon;
12+
int tm_year;
13+
int tm_wday;
14+
int tm_yday;
15+
int tm_isdst;
16+
};
17+
518
size_t strlen(const char *str);
619
size_t wcslen(const wchar_t *wcs);
20+
size_t wcsftime(wchar_t *strDest, size_t maxsize, const wchar_t *format, const struct tm *timeptr);
721

822
char *strcpy(char *destination, const char *source);
923
wchar_t *wcscpy(wchar_t *strDestination, const wchar_t *strSource);
@@ -95,6 +109,61 @@ void tests2(int case_num)
95109
wcscpy(wbuffer, wstr1);
96110
wcscat(wbuffer, wstr2);
97111
break;
112+
113+
// wcsftime test cases
114+
case 200:
115+
{
116+
wchar_t buf[80];
117+
struct tm timeinfo = {0};
118+
wcsftime(buf, sizeof(buf), L"%Y-%m-%d %H:%M:%S", &timeinfo); // BAD: sizeof(buf) returns bytes, not wchar_t count
119+
break;
120+
}
121+
122+
case 201:
123+
{
124+
wchar_t buf[80];
125+
struct tm timeinfo = {0};
126+
wcsftime(buf, sizeof(buf) / sizeof(wchar_t), L"%Y-%m-%d %H:%M:%S", &timeinfo); // GOOD: correct element count
127+
break;
128+
}
129+
130+
case 202:
131+
{
132+
wchar_t buf[80];
133+
struct tm timeinfo = {0};
134+
wcsftime(buf, 80, L"%Y-%m-%d %H:%M:%S", &timeinfo); // GOOD: direct array length
135+
break;
136+
}
137+
138+
case 203:
139+
{
140+
wchar_t smallBuf[20];
141+
struct tm timeinfo = {0};
142+
wcsftime(smallBuf, sizeof(smallBuf), L"%Y-%m-%d %H:%M:%S", &timeinfo); // BAD: sizeof returns bytes
143+
break;
144+
}
145+
146+
case 204:
147+
{
148+
wchar_t *dynamicBuf = (wchar_t *)malloc(50 * sizeof(wchar_t));
149+
struct tm timeinfo = {0};
150+
if (dynamicBuf) {
151+
wcsftime(dynamicBuf, sizeof(dynamicBuf), L"%Y-%m-%d %H:%M:%S", &timeinfo); // BAD: sizeof on pointer
152+
free(dynamicBuf);
153+
}
154+
break;
155+
}
156+
157+
case 205:
158+
{
159+
wchar_t *dynamicBuf = (wchar_t *)malloc(50 * sizeof(wchar_t));
160+
struct tm timeinfo = {0};
161+
if (dynamicBuf) {
162+
wcsftime(dynamicBuf, 50, L"%Y-%m-%d %H:%M:%S", &timeinfo); // GOOD: correct element count
163+
free(dynamicBuf);
164+
}
165+
break;
166+
}
98167
}
99168

100169
if (buffer != 0)

0 commit comments

Comments
 (0)