Skip to content

Commit 6a80f33

Browse files
authored
Merge pull request #4527 from geoffw0/odasa3940
C++: Improve SizeCheck queries
2 parents 9bd808c + ba29591 commit 6a80f33

File tree

10 files changed

+39
-52
lines changed

10 files changed

+39
-52
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The 'Not enough memory allocated for pointer type' (cpp/allocation-too-small) and 'Not enough memory allocated for array of pointer type' (cpp/suspicious-allocation-size) queries have been improved. Previously some allocations would be reported by both queries, this no longer occurs. In addition more allocation functions are now understood by both queries.

cpp/ql/src/Critical/SizeCheck.ql

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,9 @@
1313
*/
1414

1515
import cpp
16+
import semmle.code.cpp.models.Models
1617

17-
class Allocation extends FunctionCall {
18-
Allocation() {
19-
exists(string name |
20-
this.getTarget().hasGlobalOrStdName(name) and
21-
(name = "malloc" or name = "calloc" or name = "realloc")
22-
)
23-
}
24-
25-
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
26-
27-
int getSize() {
28-
this.getName() = "malloc" and
29-
this.getArgument(0).getValue().toInt() = result
30-
or
31-
this.getName() = "realloc" and
32-
this.getArgument(1).getValue().toInt() = result
33-
or
34-
this.getName() = "calloc" and
35-
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
36-
}
37-
}
38-
39-
predicate baseType(Allocation alloc, Type base) {
18+
predicate baseType(AllocationExpr alloc, Type base) {
4019
exists(PointerType pointer |
4120
pointer.getBaseType() = base and
4221
(
@@ -54,11 +33,12 @@ predicate decideOnSize(Type t, int size) {
5433
size = min(t.getSize())
5534
}
5635

57-
from Allocation alloc, Type base, int basesize, int allocated
36+
from AllocationExpr alloc, Type base, int basesize, int allocated
5837
where
5938
baseType(alloc, base) and
60-
allocated = alloc.getSize() and
39+
allocated = alloc.getSizeBytes() and
6140
decideOnSize(base, basesize) and
41+
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
6242
basesize > allocated
6343
select alloc,
6444
"Type '" + base.getName() + "' is " + basesize.toString() + " bytes, but only " +

cpp/ql/src/Critical/SizeCheck2.ql

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,9 @@
1313
*/
1414

1515
import cpp
16+
import semmle.code.cpp.models.Models
1617

17-
class Allocation extends FunctionCall {
18-
Allocation() { this.getTarget().hasGlobalOrStdName(["malloc", "calloc", "realloc"]) }
19-
20-
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
21-
22-
int getSize() {
23-
this.getName() = "malloc" and
24-
this.getArgument(0).getValue().toInt() = result
25-
or
26-
this.getName() = "realloc" and
27-
this.getArgument(1).getValue().toInt() = result
28-
or
29-
this.getName() = "calloc" and
30-
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
31-
}
32-
}
33-
34-
predicate baseType(Allocation alloc, Type base) {
18+
predicate baseType(AllocationExpr alloc, Type base) {
3519
exists(PointerType pointer |
3620
pointer.getBaseType() = base and
3721
(
@@ -44,16 +28,23 @@ predicate baseType(Allocation alloc, Type base) {
4428
)
4529
}
4630

47-
from Allocation alloc, Type base, int basesize, int allocated
31+
predicate decideOnSize(Type t, int size) {
32+
// If the codebase has more than one type with the same name, it can have more than one size.
33+
size = min(t.getSize())
34+
}
35+
36+
from AllocationExpr alloc, Type base, int basesize, int allocated
4837
where
4938
baseType(alloc, base) and
50-
allocated = alloc.getSize() and
39+
allocated = alloc.getSizeBytes() and
40+
decideOnSize(base, basesize) and
41+
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
5142
// If the codebase has more than one type with the same name, check if any matches
5243
not exists(int size | base.getSize() = size |
5344
size = 0 or
5445
(allocated / size) * size = allocated
5546
) and
56-
basesize = min(base.getSize())
47+
not basesize > allocated // covered by SizeCheck.ql
5748
select alloc,
5849
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
5950
base.getName() + "' (" + basesize.toString() + " bytes)."

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/SizeCheck/test.expected renamed to cpp/ql/test/query-tests/Critical/SizeCheck/SizeCheck.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
| test.c:17:20:17:25 | call to malloc | Type 'double' is 8 bytes, but only 5 bytes are allocated. |
33
| test.c:32:19:32:24 | call to malloc | Type 'float' is 4 bytes, but only 2 bytes are allocated. |
44
| test.c:33:20:33:25 | call to malloc | Type 'double' is 8 bytes, but only 4 bytes are allocated. |
5+
| test.c:59:15:59:20 | call to malloc | Type 'MyUnion' is 128 bytes, but only 8 bytes are allocated. |

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/SizeCheck/test.qlref renamed to cpp/ql/test/query-tests/Critical/SizeCheck/SizeCheck.qlref

File renamed without changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| test2.c:16:23:16:28 | call to malloc | Allocated memory (27 bytes) is not a multiple of the size of 'long long' (8 bytes). |
2+
| test2.c:17:20:17:25 | call to malloc | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
3+
| 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). |
4+
| test2.c:33:20:33:25 | call to malloc | Allocated memory (20 bytes) is not a multiple of the size of 'double' (8 bytes). |

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/SizeCheck2/test.qlref renamed to cpp/ql/test/query-tests/Critical/SizeCheck/SizeCheck2.qlref

File renamed without changes.

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/SizeCheck/test.c renamed to cpp/ql/test/query-tests/Critical/SizeCheck/test.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,18 @@ void good1(void) {
4343
free(dptr);
4444
}
4545

46-
47-
46+
typedef struct _myStruct
47+
{
48+
int x, y;
49+
} MyStruct;
50+
51+
typedef union _myUnion
52+
{
53+
MyStruct ms;
54+
char data[128];
55+
} MyUnion;
56+
57+
void test_union() {
58+
MyUnion *a = malloc(sizeof(MyUnion)); // GOOD
59+
MyUnion *b = malloc(sizeof(MyStruct)); // BAD (too small)
60+
}

cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/SizeCheck2/test.c renamed to cpp/ql/test/query-tests/Critical/SizeCheck/test2.c

File renamed without changes.

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

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)