Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c82957c

Browse filesBrowse files
committed
Merge remote-tracking branch 'upstream/jsinglet/slash-fixes' into jsinglet/slash-fixes
2 parents 9cc6fbe + edbc273 commit c82957c
Copy full SHA for c82957c

File tree

77 files changed

+3148
-49
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner

77 files changed

+3148
-49
lines changed

‎.vscode/tasks.json

Copy file name to clipboardExpand all lines: .vscode/tasks.json
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@
210210
"Declarations4",
211211
"Declarations5",
212212
"Declarations6",
213+
"Declarations7",
213214
"Exceptions1",
214215
"Exceptions2",
215216
"Expressions",
@@ -222,6 +223,8 @@
222223
"Includes",
223224
"Initialization",
224225
"IntegerConversion",
226+
"InvalidMemory1",
227+
"InvalidMemory2",
225228
"Invariants",
226229
"Iterators",
227230
"Lambdas",
@@ -230,6 +233,8 @@
230233
"Literals",
231234
"Loops",
232235
"Macros",
236+
"Memory1",
237+
"Memory2",
233238
"Misc",
234239
"MoveForward",
235240
"Naming",

‎c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md

Copy file name to clipboardExpand all lines: c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md
+292Lines changed: 292 additions & 0 deletions
Large diffs are not rendered by default.
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @id c/cert/information-leakage-across-trust-boundaries-c
3+
* @name DCL39-C: Avoid information leakage when passing a structure across a trust boundary
4+
* @description Passing a structure with uninitialized fields or padding bytes can cause information
5+
* to be unintentionally leaked.
6+
* @kind problem
7+
* @precision medium
8+
* @problem.severity error
9+
* @tags external/cert/id/dcl39-c
10+
* security
11+
* external/cert/obligation/rule
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.cert
16+
import codingstandards.cpp.rules.informationleakageacrossboundaries.InformationLeakageAcrossBoundaries
17+
18+
class InformationLeakageAcrossTrustBoundariesCQuery extends InformationLeakageAcrossBoundariesSharedQuery {
19+
InformationLeakageAcrossTrustBoundariesCQuery() {
20+
this = Declarations7Package::informationLeakageAcrossTrustBoundariesCQuery()
21+
}
22+
}

‎c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.md

Copy file name to clipboardExpand all lines: c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.md
+417Lines changed: 417 additions & 0 deletions
Large diffs are not rendered by default.
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @id c/cert/do-not-read-uninitialized-memory
3+
* @name EXP33-C: Do not read uninitialized memory
4+
* @description Using the value of an object with automatic storage duration while it is
5+
* indeterminate is undefined behavior.
6+
* @kind problem
7+
* @precision medium
8+
* @problem.severity error
9+
* @tags external/cert/id/exp33-c
10+
* correctness
11+
* security
12+
* external/cert/obligation/rule
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.cert
17+
import codingstandards.cpp.rules.readofuninitializedmemory.ReadOfUninitializedMemory
18+
19+
class DoNotReadUninitializedMemoryQuery extends ReadOfUninitializedMemorySharedQuery {
20+
DoNotReadUninitializedMemoryQuery() {
21+
this = InvalidMemory1Package::doNotReadUninitializedMemoryQuery()
22+
}
23+
}

‎c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.md

Copy file name to clipboardExpand all lines: c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.md
+219Lines changed: 219 additions & 0 deletions
Large diffs are not rendered by default.
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @id c/cert/do-not-dereference-null-pointers
3+
* @name EXP34-C: Do not dereference null pointers
4+
* @description Dereferencing a null pointer leads to undefined behavior.
5+
* @kind problem
6+
* @precision medium
7+
* @problem.severity error
8+
* @tags external/cert/id/exp34-c
9+
* correctness
10+
* external/cert/obligation/rule
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.cert
15+
import codingstandards.cpp.rules.dereferenceofnullpointer.DereferenceOfNullPointer
16+
17+
class DoNotDereferenceNullPointersQuery extends DereferenceOfNullPointerSharedQuery {
18+
DoNotDereferenceNullPointersQuery() {
19+
this = InvalidMemory1Package::doNotDereferenceNullPointersQuery()
20+
}
21+
}

‎c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.md

Copy file name to clipboardExpand all lines: c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.md
+258Lines changed: 258 additions & 0 deletions
Large diffs are not rendered by default.
+66Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @id c/cert/do-not-access-freed-memory
3+
* @name MEM30-C: Do not access freed memory
4+
* @description Accessing memory that has been deallocated is undefined behavior.
5+
* @kind problem
6+
* @precision high
7+
* @problem.severity error
8+
* @tags external/cert/id/mem30-c
9+
* correctness
10+
* security
11+
* external/cert/obligation/rule
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.cert
16+
import codingstandards.cpp.Allocations
17+
import semmle.code.cpp.controlflow.StackVariableReachability
18+
19+
/** `e` is an expression that frees the memory pointed to by `v`. */
20+
predicate isFreeExpr(Expr e, StackVariable v) {
21+
exists(VariableAccess va | va.getTarget() = v and freeExprOrIndirect(e, va, _))
22+
}
23+
24+
/** `e` is an expression that accesses `v` but is not the lvalue of an assignment. */
25+
predicate isAccessExpr(Expr e, StackVariable v) {
26+
v.getAnAccess() = e and
27+
not exists(Assignment a | a.getLValue() = e)
28+
or
29+
isDerefByCallExpr(_, _, e, v)
30+
}
31+
32+
/**
33+
* `va` is passed by value as (part of) the `i`th argument in
34+
* call `c`. The target function is either a library function
35+
* or a source code function that dereferences the relevant
36+
* parameter.
37+
*/
38+
predicate isDerefByCallExpr(Call c, int i, VariableAccess va, StackVariable v) {
39+
v.getAnAccess() = va and
40+
va = c.getAnArgumentSubExpr(i) and
41+
not c.passesByReference(i, va) and
42+
(c.getTarget().hasEntryPoint() implies isAccessExpr(_, c.getTarget().getParameter(i)))
43+
}
44+
45+
class UseAfterFreeReachability extends StackVariableReachability {
46+
UseAfterFreeReachability() { this = "UseAfterFree" }
47+
48+
override predicate isSource(ControlFlowNode node, StackVariable v) { isFreeExpr(node, v) }
49+
50+
override predicate isSink(ControlFlowNode node, StackVariable v) { isAccessExpr(node, v) }
51+
52+
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
53+
definitionBarrier(v, node) or
54+
isFreeExpr(node, v)
55+
}
56+
}
57+
58+
// This query is a modified version of the `UseAfterFree.ql`
59+
// (cpp/use-after-free) query from the CodeQL standard library.
60+
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e
61+
where
62+
not isExcluded(e, InvalidMemory1Package::doNotAccessFreedMemoryQuery()) and
63+
r.reaches(free, v, e)
64+
select e,
65+
"Pointer '" + v.getName().toString() + "' accessed but may have been previously freed $@.", free,
66+
"here"
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.ql
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/readofuninitializedmemory/ReadOfUninitializedMemory.ql
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/dereferenceofnullpointer/DereferenceOfNullPointer.ql
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| test.c:11:47:11:47 | p | Pointer 'p' accessed but may have been previously freed $@. | test.c:12:5:12:8 | call to free | here |
2+
| test.c:25:10:25:12 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:24:3:24:6 | call to free | here |
3+
| test.c:32:15:32:17 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |
4+
| test.c:33:9:33:11 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |
5+
| test.c:34:16:34:18 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/MEM30-C/DoNotAccessFreedMemory.ql

‎c/cert/test/rules/MEM30-C/test.c

Copy file name to clipboard
+38Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <stdlib.h>
2+
#include <string.h>
3+
4+
struct node {
5+
struct node *next;
6+
};
7+
8+
void test_freed_loop_var(struct node *list1, struct node *list2) {
9+
struct node *tmp;
10+
11+
for (struct node *p = list1; p != NULL; p = p->next) { // NON_COMPLIANT
12+
free(p);
13+
}
14+
15+
for (struct node *p = list2; p != NULL; p = tmp) { // COMPLIANT
16+
tmp = p->next;
17+
free(p);
18+
}
19+
}
20+
21+
void test_freed_arg(char *input) {
22+
char *buf = (char *)malloc(strlen(input) + 1);
23+
strcpy(buf, input); // COMPLIANT
24+
free(buf);
25+
strcpy(buf, input); // NON_COMPLIANT
26+
}
27+
28+
void test_freed_access_no_deref(char *input) {
29+
char *buf = (char *)malloc(strlen(input) + 1);
30+
strcpy(buf, input); // COMPLIANT
31+
free(buf);
32+
char *tmp = buf; // NON_COMPLIANT
33+
tmp = buf + 1; // NON_COMPLIANT
34+
char *tmp2 = buf; // NON_COMPLIANT
35+
buf = NULL; // COMPLIANT
36+
(char *)buf; // COMPLIANT
37+
tmp2 = buf + 1; // COMPLIANT
38+
}
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:11:4:11:5 | l1 | Null may be dereferenced here because a null value was assigned $@. | test.c:4:21:4:21 | 0 | here |
2+
| test.c:18:6:18:7 | l1 | Null may be dereferenced here because a null value was assigned $@. | test.c:4:21:4:21 | 0 | here |
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.dereferenceofnullpointer.DereferenceOfNullPointer
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <stdlib.h>
2+
3+
void test_null(int p1) {
4+
int *l1 = (void *)0;
5+
6+
if (p1 > 10) {
7+
// l1 is only conditionally initialized
8+
l1 = malloc(10 * sizeof(int));
9+
}
10+
11+
*l1; // NON_COMPLIANT - dereferenced and still null
12+
13+
if (l1) {
14+
*l1; // COMPLIANT - null check before dereference
15+
}
16+
17+
if (!l1) {
18+
*l1; // NON_COMPLIANT - dereferenced and definitely null
19+
} else {
20+
*l1; // COMPLIANT - null check before dereference
21+
}
22+
23+
free(l1); // COMPLIANT - free of `NULL` is not undefined behavior
24+
}
25+
26+
void test_default_value_init() {
27+
int *l1; // indeterminate and thus invalid but non-null state
28+
29+
*l1; // COMPLIANT - considered an uninitialized pointer,
30+
// not a null pointer
31+
}
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
| arrays.c:11:20:11:21 | wa | 'wa' may leak information from {elements of a[...] (arrays.c:7)}. Path: wa (arrays.c:11) --> & ... (arrays.c:12) |
2+
| arrays.c:33:22:33:23 | wa | 'wa' may leak information from {elements of elements of a[...][...] (arrays.c:29)}. Path: wa (arrays.c:33) --> & ... (arrays.c:34) |
3+
| arrays.c:57:22:57:23 | wa | 'wa' may leak information from {WithPointer (arrays.c:52)}. Path: wa (arrays.c:57) --> & ... (arrays.c:59) |
4+
| interprocedural.c:37:9:37:9 | p | 'p' may leak information from {y (interprocedural.c:8)}. Path: p (interprocedural.c:37) --> past assign_x (interprocedural.c:32) --> & ... (interprocedural.c:39) |
5+
| interprocedural.c:104:9:104:9 | p | 'p' may leak information from {x (interprocedural.c:7), y (interprocedural.c:8)}. Path: p (interprocedural.c:104) --> overwrite_after_leak(...) (interprocedural.c:96) --> p (interprocedural.c:97) |
6+
| multilayer.c:16:10:16:10 | s | 's' may leak information from {b (multilayer.c:12)}. Path: s (multilayer.c:16) --> & ... (multilayer.c:18) |
7+
| multilayer.c:29:10:29:10 | s | 's' may leak information from {b (multilayer.c:12), x (multilayer.c:7)}. Path: s (multilayer.c:29) --> & ... (multilayer.c:30) |
8+
| multilayer.c:34:8:34:8 | s | 's' may leak information from {struct <unnamed> (multilayer.c:6)}. Path: s (multilayer.c:34) --> & ... (multilayer.c:35) |
9+
| test.c:12:12:12:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:12) --> & ... (test.c:14) |
10+
| test.c:18:12:18:12 | s | 's' may leak information from {x (test.c:7)}. Path: s (test.c:18) --> & ... (test.c:20) |
11+
| test.c:24:12:24:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:24) --> & ... (test.c:25) |
12+
| test.c:36:12:36:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:36) --> & ... (test.c:38) |
13+
| test.c:43:12:43:12 | s | 's' may leak information from {x (test.c:7)}. Path: s (test.c:43) --> & ... (test.c:47) |
14+
| test.c:58:12:58:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:58) --> & ... (test.c:59) |
15+
| test.c:64:12:64:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:64) --> & ... (test.c:66) |
16+
| test.c:112:16:112:16 | s | 's' may leak information from {buf (test.c:92)}. Path: s (test.c:112) --> & ... (test.c:115) |
17+
| test.c:128:12:128:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:128) --> & ... (test.c:132) |
18+
| test.c:157:22:157:22 | s | 's' may leak information from {2 to 2 bytes of padding in has_padding (test.c:151)}. Path: s (test.c:157) --> & ... (test.c:160) |
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.informationleakageacrossboundaries.InformationLeakageAcrossBoundaries
+62Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <stddef.h>
2+
#include <string.h>
3+
4+
unsigned long copy_to_user(void *to, const void *from, unsigned long n);
5+
6+
struct WithArray {
7+
int a[2];
8+
};
9+
10+
void forget_array() {
11+
struct WithArray wa;
12+
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
13+
}
14+
15+
void write_partial_array() {
16+
struct WithArray wa;
17+
wa.a[0] = 1;
18+
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT[FALSE NEGATIVE]
19+
}
20+
21+
void write_full_array() {
22+
struct WithArray wa;
23+
wa.a[0] = 1;
24+
wa.a[1] = 1;
25+
copy_to_user(0, &wa, sizeof wa); // COMPLIANT
26+
}
27+
28+
struct WithArray2D {
29+
int a[2][1];
30+
};
31+
32+
void forget_array2d() {
33+
struct WithArray2D wa;
34+
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
35+
}
36+
37+
void write_partial_array2d() {
38+
struct WithArray2D wa;
39+
wa.a[0][0] = 1;
40+
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT[FALSE NEGATIVE]
41+
}
42+
43+
void write_full_array2d() {
44+
struct WithArray2D wa;
45+
wa.a[0][0] = 1;
46+
wa.a[1][0] = 1;
47+
copy_to_user(0, &wa, sizeof wa); // COMPLIANT
48+
}
49+
50+
// A pointer field allows mostly the same syntactic operations as an array
51+
// field, but the semantics are completely different.
52+
struct WithPointer {
53+
int *a;
54+
};
55+
56+
void pointer_array_expression() {
57+
struct WithPointer wa;
58+
wa.a[0] = 1;
59+
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
60+
}
61+
62+
// TODO: test a struct in an array

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.