Skip to content

Commit 0f30a76

Browse files
authored
Merge pull request #165 from knewbury01/knewbury01/Declarations7
Implement C Declarations7 package
2 parents d74f0f2 + cae74a9 commit 0f30a76

35 files changed

+989
-13
lines changed

.vscode/tasks.json

+1
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",

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

+292
Large diffs are not rendered by default.
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.ql
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) |
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
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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+
typedef struct _point {
7+
int x;
8+
int y;
9+
} point;
10+
11+
void callee1(point *p) {
12+
p->y = 1;
13+
copy_to_user(0, p, sizeof(point)); // COMPLIANT
14+
}
15+
16+
void caller1() {
17+
point p;
18+
p.x = 1;
19+
callee1(&p);
20+
}
21+
22+
void callee2(point *p) {
23+
memset(p, 0, sizeof(point));
24+
copy_to_user(0, p, sizeof(point)); // COMPLIANT
25+
}
26+
27+
void caller2() {
28+
point p;
29+
callee2(&p);
30+
}
31+
32+
void assign_x(point *p, int value) { p->x = value; }
33+
34+
void zero_y(point *p) { memset(&p->y, 0, sizeof(p->y)); }
35+
36+
void call_to_overwrite_x() {
37+
point p;
38+
assign_x(&p, 1);
39+
copy_to_user(0, &p, sizeof p); // NON_COMPLIANT
40+
}
41+
42+
void call_to_overwrite_both() {
43+
point p;
44+
assign_x(&p, 1);
45+
zero_y(&p);
46+
copy_to_user(0, &p, sizeof p); // COMPLIANT
47+
}
48+
49+
void zero_y_and_loop(point *p) {
50+
int i;
51+
memset(&p->y, 0, sizeof(p->y));
52+
for (i = 0; i < 10; i++) {
53+
p->y++;
54+
}
55+
}
56+
57+
void call_zero_y_and_loop() {
58+
point p;
59+
zero_y_and_loop(&p);
60+
assign_x(&p, 1);
61+
copy_to_user(0, &p, sizeof p); // COMPLIANT
62+
}
63+
64+
int zero_y_or_fail(point *p) {
65+
if (p->x < 0) {
66+
return 0;
67+
}
68+
p->y = 0;
69+
return 1;
70+
}
71+
72+
void call_zero_y_or_fail(int i) {
73+
point p;
74+
p.x = i;
75+
if (!zero_y_or_fail(&p)) {
76+
return;
77+
}
78+
copy_to_user(0, &p, sizeof p); // COMPLIANT
79+
}
80+
81+
int zero_y_proxy(point *p) {
82+
if (p->x) {
83+
zero_y(p);
84+
} else {
85+
zero_y(p);
86+
}
87+
}
88+
89+
void call_zero_y_proxy() {
90+
point p;
91+
zero_y_proxy(&p);
92+
assign_x(&p, 1);
93+
copy_to_user(0, &p, sizeof p); // COMPLIANT
94+
}
95+
96+
void overwrite_after_leak(point *p) {
97+
copy_to_user(0, p, sizeof(*p)); // NON_COMPLIANT
98+
99+
p->x = 0;
100+
p->y = 0;
101+
}
102+
103+
void call_overwrite_after_leak(void) {
104+
point p;
105+
overwrite_after_leak(&p);
106+
copy_to_user(0, &p, sizeof p); // COMPLIANT
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
typedef struct {
7+
int x;
8+
} intx;
9+
10+
typedef struct {
11+
intx a;
12+
intx b;
13+
} intxab;
14+
15+
void forget_y() {
16+
intxab s;
17+
s.a.x = 1;
18+
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (y)
19+
}
20+
21+
void set_both() {
22+
intxab s;
23+
s.a.x = 1;
24+
memset(&s.b, 0, sizeof s.b);
25+
copy_to_user(0, &s, sizeof s); // COMPLIANT
26+
}
27+
28+
void set_none() {
29+
intxab s;
30+
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (both)
31+
}
32+
33+
void set_none_intx() {
34+
intx s;
35+
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (x)
36+
}

0 commit comments

Comments
 (0)