C++: Update the queries.

This commit is contained in:
Geoffrey White
2023-01-05 11:29:52 +00:00
parent a9aa67177b
commit 2023abdc60
14 changed files with 38 additions and 22 deletions

View File

@@ -16,7 +16,7 @@
import cpp
import semmle.code.cpp.models.Models
predicate baseType(AllocationExpr alloc, Type base) {
predicate baseType(HeuristicAllocationExpr alloc, Type base) {
exists(PointerType pointer |
pointer.getBaseType() = base and
(
@@ -34,12 +34,12 @@ predicate decideOnSize(Type t, int size) {
size = min(t.getSize())
}
from AllocationExpr alloc, Type base, int basesize, int allocated
from HeuristicAllocationExpr alloc, Type base, int basesize, int allocated
where
baseType(alloc, base) and
allocated = alloc.getSizeBytes() and
decideOnSize(base, basesize) and
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
alloc.(FunctionCall).getTarget() instanceof HeuristicAllocationFunction and // exclude `new` and similar
basesize > allocated
select alloc,
"Type '" + base.getName() + "' is " + basesize.toString() + " bytes, but only " +

View File

@@ -16,7 +16,7 @@
import cpp
import semmle.code.cpp.models.Models
predicate baseType(AllocationExpr alloc, Type base) {
predicate baseType(HeuristicAllocationExpr alloc, Type base) {
exists(PointerType pointer |
pointer.getBaseType() = base and
(
@@ -34,12 +34,12 @@ predicate decideOnSize(Type t, int size) {
size = min(t.getSize())
}
from AllocationExpr alloc, Type base, int basesize, int allocated
from HeuristicAllocationExpr alloc, Type base, int basesize, int allocated
where
baseType(alloc, base) and
allocated = alloc.getSizeBytes() and
decideOnSize(base, basesize) and
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
alloc.(FunctionCall).getTarget() instanceof HeuristicAllocationFunction and // exclude `new` and similar
// If the codebase has more than one type with the same name, check if any matches
not exists(int size | base.getSize() = size |
size = 0 or

View File

@@ -21,7 +21,7 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.commons.NullTermination
predicate terminationProblem(AllocationExpr malloc, string msg) {
predicate terminationProblem(HeuristicAllocationExpr malloc, string msg) {
// malloc(strlen(...))
exists(StrlenCall strlen | DataFlow::localExprFlow(strlen, malloc.getSizeExpr())) and
// flows to a call that implies this is a null-terminated string

View File

@@ -25,9 +25,8 @@ import DataFlow::PathGraph
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
* taint sink.
*/
predicate allocSink(Expr alloc, DataFlow::Node sink) {
predicate allocSink(HeuristicAllocationExpr alloc, DataFlow::Node sink) {
exists(Expr e | e = sink.asConvertedExpr() |
isAllocationExpr(alloc) and
e = alloc.getAChild() and
e.getUnspecifiedType() instanceof IntegralType
)

View File

@@ -7,3 +7,5 @@
| tests3.cpp:25:21:25:31 | call to malloc | This allocation does not include space to null-terminate the string. |
| tests3.cpp:30:21:30:31 | call to malloc | This allocation does not include space to null-terminate the string. |
| tests3.cpp:53:17:53:44 | new[] | This allocation does not include space to null-terminate the string. |
| tests3.cpp:81:20:81:28 | call to MyMalloc1 | This allocation does not include space to null-terminate the string. |
| tests3.cpp:84:20:84:28 | call to MyMalloc2 | This allocation does not include space to null-terminate the string. |

View File

@@ -78,9 +78,9 @@ void tests4()
char *buffer1 = 0;
char *buffer2 = 0;
buffer1 = (char *)MyMalloc1(strlen(str4)); // BAD [NOT DETECTED]
buffer1 = (char *)MyMalloc1(strlen(str4)); // BAD
strcpy(buffer1, str4);
buffer2 = (char *)MyMalloc2(strlen(str4)); // BAD [NOT DETECTED]
buffer2 = (char *)MyMalloc2(strlen(str4)); // BAD
strcpy(buffer2, str4);
}

View File

@@ -3,3 +3,5 @@
| test.c:32:19:32:24 | call to malloc | Type 'float' is 4 bytes, but only 2 bytes are allocated. |
| test.c:33:20:33:25 | call to malloc | Type 'double' is 8 bytes, but only 4 bytes are allocated. |
| test.c:59:15:59:20 | call to malloc | Type 'MyUnion' is 128 bytes, but only 8 bytes are allocated. |
| test.c:69:20:69:28 | call to MyMalloc1 | Type 'float' is 4 bytes, but only 3 bytes are allocated. |
| test.c:70:20:70:28 | call to MyMalloc2 | Type 'float' is 4 bytes, but only 3 bytes are allocated. |

View File

@@ -2,3 +2,5 @@
| test2.c:17:20:17:25 | call to malloc | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:32:23:32:28 | call to malloc | Allocated memory (28 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test2.c:33:20:33:25 | call to malloc | Allocated memory (20 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:53:21:53:29 | call to MyMalloc1 | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:54:21:54:29 | call to MyMalloc2 | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |

View File

@@ -66,6 +66,6 @@ void *MyMalloc2(size_t size);
void customAllocatorTests()
{
float *fptr1 = MyMalloc1(3); // BAD (too small) [NOT DETECTED]
float *fptr2 = MyMalloc2(3); // BAD (too small) [NOT DETECTED]
float *fptr1 = MyMalloc1(3); // BAD (too small)
float *fptr2 = MyMalloc2(3); // BAD (too small)
}

View File

@@ -50,6 +50,6 @@ void *MyMalloc2(size_t size);
void customAllocatorTests()
{
double *dptr1 = MyMalloc1(33); // BAD -- Not a multiple of sizeof(double) [NOT DETECTED]
double *dptr2 = MyMalloc2(33); // BAD -- Not a multiple of sizeof(double) [NOT DETECTED]
double *dptr1 = MyMalloc1(33); // BAD -- Not a multiple of sizeof(double)
double *dptr2 = MyMalloc2(33); // BAD -- Not a multiple of sizeof(double)
}

View File

@@ -1,5 +1,7 @@
| test2.cpp:64:34:64:39 | call to calloc | This allocation does not include space to null-terminate the string. |
| test2.cpp:71:28:71:34 | call to realloc | This allocation does not include space to null-terminate the string. |
| test2.cpp:84:27:84:35 | call to MyMalloc1 | This allocation does not include space to null-terminate the string. |
| test2.cpp:89:27:89:35 | call to MyMalloc2 | This allocation does not include space to null-terminate the string. |
| test.c:16:20:16:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:32:20:32:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:49:20:49:25 | call to malloc | This allocation does not include space to null-terminate the string. |

View File

@@ -81,12 +81,12 @@ void *MyMalloc2(size_t size);
void customAllocatorTests(char *str)
{
{
char *buffer1 = (char *)MyMalloc1(strlen(str)); // BAD (no room for `\0` terminator) [NOT DETECTED]
char *buffer1 = (char *)MyMalloc1(strlen(str)); // BAD (no room for `\0` terminator)
strcpy(buffer1, str);
}
{
char *buffer2 = (char *)MyMalloc2(strlen(str)); // BAD (no room for `\0` terminator) [NOT DETECTED]
char *buffer2 = (char *)MyMalloc2(strlen(str)); // BAD (no room for `\0` terminator)
strcpy(buffer2, str);
}
}

View File

@@ -14,6 +14,7 @@ edges
| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:10:247:19 | local_size |
| test.cpp:245:11:245:20 | local_size | test.cpp:224:23:224:23 | s |
| test.cpp:247:10:247:19 | local_size | test.cpp:230:21:230:21 | s |
@@ -27,6 +28,8 @@ edges
| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
| test.cpp:348:24:348:27 | size | test.cpp:348:46:348:49 | size |
| test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size |
| test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size |
| test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size |
| test.cpp:355:35:355:38 | size | test.cpp:348:24:348:27 | size |
nodes
| test.cpp:39:27:39:30 | argv | semmle.label | argv |
@@ -52,6 +55,7 @@ nodes
| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
| test.cpp:245:11:245:20 | local_size | semmle.label | local_size |
| test.cpp:245:11:245:20 | local_size | semmle.label | local_size |
| test.cpp:247:10:247:19 | local_size | semmle.label | local_size |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] |
| test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv |
@@ -65,6 +69,8 @@ nodes
| test.cpp:348:46:348:49 | size | semmle.label | size |
| test.cpp:353:18:353:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:355:35:355:38 | size | semmle.label | size |
| test.cpp:355:35:355:38 | size | semmle.label | size |
| test.cpp:356:35:356:38 | size | semmle.label | size |
subpaths
#select
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
@@ -80,7 +86,10 @@ subpaths
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:19 | call to getenv | user input (an environment variable) |
| test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:25 | call to getenv | user input (an environment variable) |
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
| test.cpp:348:39:348:44 | call to malloc | test.cpp:353:18:353:23 | call to getenv | test.cpp:348:46:348:49 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) |
| test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) |
| test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) |

View File

@@ -222,7 +222,7 @@ size_t get_bounded_size()
}
void *my_alloc(size_t s) {
void *ptr = malloc(s); // [UNHELPFUL RESULT]
void *ptr = malloc(s); // [additional detection here]
return ptr;
}
@@ -242,7 +242,7 @@ void more_cases() {
malloc(get_bounded_size()); // GOOD
my_alloc(100); // GOOD
my_alloc(local_size); // BAD [NOT DETECTED IN CORRECT LOCATION]
my_alloc(local_size); // BAD
my_func(100); // GOOD
my_func(local_size); // GOOD
}
@@ -345,13 +345,13 @@ void equality_barrier() {
// --- custom allocators ---
void *MyMalloc1(size_t size) { return malloc(size); } // [detected here]
void *MyMalloc1(size_t size) { return malloc(size); } // [additional detection here]
void *MyMalloc2(size_t size);
void customAllocatorTests()
{
int size = atoi(getenv("USER"));
char *chars1 = (char *)MyMalloc1(size); // BAD [detected above]
char *chars2 = (char *)MyMalloc2(size); // BAD [NOT DETECTED]
char *chars1 = (char *)MyMalloc1(size); // BAD
char *chars2 = (char *)MyMalloc2(size); // BAD
}