Skip to content

Commit 3f218c9

Browse files
authored
C++: add some more range analysis tests
Add more covering for integer conversions and some unsigned bit manipulation.
1 parent c91b6f7 commit 3f218c9

File tree

2 files changed

+50
-29
lines changed

2 files changed

+50
-29
lines changed

cpp/ql/test/query-tests/Security/CWE/CWE-242/semmle/tests/OverrunWrite.expected

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
| tests.cpp:272:2:272:8 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
44
| tests.cpp:273:2:273:8 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
55
| tests.cpp:308:3:308:9 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 8 bytes. |
6-
| tests.cpp:315:2:315:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 2 bytes. |
7-
| tests.cpp:316:2:316:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 2 bytes. |
8-
| tests.cpp:321:2:321:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 2 bytes. |
9-
| tests.cpp:324:3:324:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 2 bytes. |
10-
| tests.cpp:327:2:327:8 | call to sprintf | This 'call to sprintf' operation requires 12 bytes but the destination is only 2 bytes. |
11-
| tests.cpp:329:3:329:9 | call to sprintf | This 'call to sprintf' operation requires 12 bytes but the destination is only 2 bytes. |
6+
| tests.cpp:315:2:315:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
7+
| tests.cpp:316:2:316:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
8+
| tests.cpp:321:2:321:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
9+
| tests.cpp:324:3:324:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 4 bytes. |
10+
| tests.cpp:327:2:327:8 | call to sprintf | This 'call to sprintf' operation requires 12 bytes but the destination is only 4 bytes. |
11+
| tests.cpp:329:3:329:9 | call to sprintf | This 'call to sprintf' operation requires 12 bytes but the destination is only 4 bytes. |
1212
| tests.cpp:341:2:341:8 | call to sprintf | This 'call to sprintf' operation requires 3 bytes but the destination is only 2 bytes. |
1313
| tests.cpp:343:2:343:8 | call to sprintf | This 'call to sprintf' operation requires 3 bytes but the destination is only 2 bytes. |
1414
| tests.cpp:345:2:345:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 2 bytes. |
1515
| tests.cpp:347:2:347:8 | call to sprintf | This 'call to sprintf' operation requires 3 bytes but the destination is only 2 bytes. |
16+
| tests.cpp:350:2:350:8 | call to sprintf | This 'call to sprintf' operation requires 4 bytes but the destination is only 3 bytes. |
17+
| tests.cpp:354:2:354:8 | call to sprintf | This 'call to sprintf' operation requires 4 bytes but the destination is only 3 bytes. |
18+
| tests.cpp:358:2:358:8 | call to sprintf | This 'call to sprintf' operation requires 4 bytes but the destination is only 3 bytes. |
19+
| tests.cpp:363:2:363:8 | call to sprintf | This 'call to sprintf' operation requires 5 bytes but the destination is only 4 bytes. |

cpp/ql/test/query-tests/Security/CWE/CWE-242/semmle/tests/tests.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -310,39 +310,56 @@ namespace custom_sprintf_impl {
310310
}
311311

312312
void test6(unsigned unsigned_value, int value) {
313-
char buffer[2];
313+
char buffer2[2], buffer3[3], buffer4[4], buffer5[5];
314314

315-
sprintf(buffer, "%u", unsigned_value); // BAD: buffer overflow
316-
sprintf(buffer, "%d", unsigned_value); // BAD: buffer overflow
317-
if (unsigned_value < 10) {
318-
sprintf(buffer, "%u", unsigned_value); // GOOD
315+
sprintf(buffer4, "%u", unsigned_value); // BAD: buffer overflow
316+
sprintf(buffer4, "%d", unsigned_value); // BAD: buffer overflow
317+
if (unsigned_value < 1000) {
318+
sprintf(buffer4, "%u", unsigned_value); // GOOD
319319
}
320320

321-
sprintf(buffer, "%u", -10); // BAD: buffer overflow
321+
sprintf(buffer4, "%u", -100); // BAD: buffer overflow
322322

323-
if(unsigned_value == (unsigned)-10) {
324-
sprintf(buffer, "%u", unsigned_value); // BAD: buffer overflow
323+
if(unsigned_value == (unsigned)-100) {
324+
sprintf(buffer4, "%u", unsigned_value); // BAD: buffer overflow
325325
}
326326

327-
sprintf(buffer, "%d", value); // BAD: buffer overflow
328-
if (value < 10) {
329-
sprintf(buffer, "%d", value); // BAD: buffer overflow
327+
sprintf(buffer4, "%d", value); // BAD: buffer overflow
328+
if (value < 1000) {
329+
sprintf(buffer4, "%d", value); // BAD: buffer overflow
330330

331-
if(value > 0) {
332-
sprintf(buffer, "%d", value); // GOOD
331+
if(value > -100) {
332+
sprintf(buffer4, "%d", value); // GOOD
333333
}
334334
}
335335

336-
sprintf(buffer, "%u", 0); // GOOD
337-
sprintf(buffer, "%d", 0); // GOOD
338-
sprintf(buffer, "%u", 5); // GOOD
339-
sprintf(buffer, "%d", 5); // GOOD
336+
sprintf(buffer2, "%u", 0); // GOOD
337+
sprintf(buffer2, "%d", 0); // GOOD
338+
sprintf(buffer2, "%u", 5); // GOOD
339+
sprintf(buffer2, "%d", 5); // GOOD
340340

341-
sprintf(buffer, "%d", -1); // BAD
342-
sprintf(buffer, "%d", 9); // GOOD
343-
sprintf(buffer, "%d", 10); // BAD
341+
sprintf(buffer2, "%d", -1); // BAD
342+
sprintf(buffer2, "%d", 9); // GOOD
343+
sprintf(buffer2, "%d", 10); // BAD
344344

345-
sprintf(buffer, "%u", -1); // BAD
346-
sprintf(buffer, "%u", 9); // GOOD
347-
sprintf(buffer, "%u", 10); // BAD
345+
sprintf(buffer2, "%u", -1); // BAD
346+
sprintf(buffer2, "%u", 9); // GOOD
347+
sprintf(buffer2, "%u", 10); // BAD
348+
349+
unsigned char unsigned_char = unsigned_value;
350+
sprintf(buffer3, "%u", (unsigned)unsigned_char); // BAD
351+
sprintf(buffer4, "%u", (unsigned)unsigned_char); // GOOD: 0..255 fits
352+
353+
unsigned small = unsigned_value >> (sizeof(unsigned_value) * 8 - 9); // in range 0..511
354+
sprintf(buffer3, "%u", small); // BAD
355+
sprintf(buffer4, "%u", small); // GOOD
356+
357+
small = unsigned_value & ((1u << 9) - 1); // in range 0..511
358+
sprintf(buffer3, "%u", small); // BAD
359+
sprintf(buffer4, "%u", small); // GOOD: 0..511 fits
360+
361+
char c = value;
362+
363+
sprintf(buffer4, "%d", (int)c); // BAD: e.g. -127 does not fit
364+
sprintf(buffer5, "%d", (int)c); // GOOD: -127..128 fits
348365
}

0 commit comments

Comments
 (0)