Skip to content

Commit a8151b4

Browse files
committed
C++: Add double-free tests.
1 parent fb2ec15 commit a8151b4

File tree

3 files changed

+326
-0
lines changed

3 files changed

+326
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
edges
2+
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
3+
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
4+
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
5+
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
6+
| test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a |
7+
| test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a |
8+
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
9+
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
10+
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
11+
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
12+
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
13+
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
14+
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
15+
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
16+
| test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a |
17+
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
18+
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
19+
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
20+
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
21+
| test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a |
22+
| test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... |
23+
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
24+
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
25+
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
26+
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
27+
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
28+
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
29+
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
30+
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
31+
nodes
32+
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
33+
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
34+
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
35+
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
36+
| test_free.cpp:30:10:30:10 | a | semmle.label | a |
37+
| test_free.cpp:31:27:31:27 | a | semmle.label | a |
38+
| test_free.cpp:35:10:35:10 | a | semmle.label | a |
39+
| test_free.cpp:37:27:37:27 | a | semmle.label | a |
40+
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
41+
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
42+
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
43+
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
44+
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
45+
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
46+
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
47+
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
48+
| test_free.cpp:50:27:50:27 | a | semmle.label | a |
49+
| test_free.cpp:51:10:51:10 | a | semmle.label | a |
50+
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
51+
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
52+
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
53+
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
54+
| test_free.cpp:101:10:101:10 | a | semmle.label | a |
55+
| test_free.cpp:103:10:103:10 | a | semmle.label | a |
56+
| test_free.cpp:128:10:128:11 | * ... | semmle.label | * ... |
57+
| test_free.cpp:129:10:129:11 | * ... | semmle.label | * ... |
58+
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
59+
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
60+
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
61+
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
62+
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
63+
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
64+
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
65+
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
66+
subpaths
67+
#select
68+
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
69+
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
70+
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
71+
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
72+
| test_free.cpp:31:27:31:27 | a | test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:30:5:30:8 | call to free | call to free |
73+
| test_free.cpp:37:27:37:27 | a | test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:35:5:35:8 | call to free | call to free |
74+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
75+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
76+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
77+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
78+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
79+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
80+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
81+
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
82+
| test_free.cpp:51:10:51:10 | a | test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:50:22:50:25 | call to free | call to free |
83+
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
84+
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
85+
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
86+
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
87+
| test_free.cpp:103:10:103:10 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
88+
| test_free.cpp:129:10:129:11 | * ... | test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... | Memory pointed to by '* ...' may already have been freed by $@. | test_free.cpp:128:5:128:8 | call to free | call to free |
89+
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
90+
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
91+
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
92+
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
93+
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
94+
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
95+
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
96+
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Critical/DoubleFree.ql
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
void *malloc(int);
2+
void free(void *);
3+
bool condition();
4+
void use(void*);
5+
void *realloc(void*, unsigned long);
6+
int strlen(char*);
7+
int asprintf(char ** strp, const char * fmt, ...);
8+
9+
10+
void* test_double_free1(int *a) {
11+
free(a); // GOOD
12+
a[5] = 5;
13+
*a = 5;
14+
free(a); // BAD
15+
a = (int*) malloc(8);
16+
free(a); // GOOD
17+
a = (int*) malloc(8);
18+
if (!a) free(a);
19+
return a;
20+
}
21+
22+
void test_double_free_aliasing(void *a, void* b) {
23+
free(a); // GOOD
24+
a = b;
25+
free(a); // GOOD
26+
free(b); // BAD [NOT DETECTED]
27+
}
28+
29+
void test_dominance1(void *a) {
30+
free(a);
31+
if (condition()) free(a); // BAD
32+
}
33+
34+
void test_dominance2(void *a) {
35+
free(a);
36+
if (condition()) a = malloc(10);
37+
if (condition()) free(a); // BAD
38+
}
39+
40+
void test_post_dominance1(int *a)
41+
{
42+
if (condition()) free(a); // GOOD
43+
if (condition()) a[2] = 5;
44+
if (condition()) free(a); // GOOD
45+
a[2] = 5;
46+
free(a); // BAD
47+
}
48+
49+
void test_post_dominance2(void *a) {
50+
if (condition()) free(a);
51+
free(a); // BAD
52+
}
53+
54+
void test_post_dominance3(void *a) {
55+
if (condition()) free(a);
56+
a = malloc(10);
57+
free(a); // GOOD
58+
}
59+
60+
void test_use_after_free6(int *a, int *b) {
61+
free(a);
62+
a=b;
63+
free(b);
64+
if (condition()) a[0] = 5;
65+
}
66+
67+
void test_use_after_free7(int *a) {
68+
a[0] = 42;
69+
free(a);
70+
71+
if (a[3]) {
72+
free(a); // BAD
73+
}
74+
}
75+
76+
class A {
77+
public:
78+
void f();
79+
};
80+
81+
void test_new1() {
82+
A *a = new A();
83+
delete(a);
84+
a->f();
85+
delete(a); // BAD [NOT DETECTED]
86+
}
87+
88+
void test_dereference1(A *a) {
89+
a->f();
90+
free(a);
91+
a->f();
92+
}
93+
94+
void* use_after_free(void *a) {
95+
free(a);
96+
use(a);
97+
return a;
98+
}
99+
100+
void test_realloc1(void *a) {
101+
free(a);
102+
void *b = realloc(a, sizeof(a)*3); // BAD
103+
free(a); // BAD
104+
free(b); // GOOD
105+
}
106+
void* test_realloc2(char *a) {
107+
void *b = realloc(a, strlen(a)+3); // GOOD
108+
109+
// From the man page on return values from realloc and reallocarray:
110+
// "If these functions fail, the original block is left untouched; it is not freed or moved."
111+
if (!b) {
112+
free(a); // GOOD
113+
}
114+
free(b); // GOOD
115+
}
116+
117+
void test_realloc3(void *a) {
118+
void *b = realloc(a, 100);
119+
if (b) free(b); // GOOD
120+
if (!b) {
121+
free(a); // GOOD
122+
}
123+
}
124+
125+
void test_ptr_deref(void ** a) {
126+
free(*a);
127+
*a = malloc(10);
128+
free(*a); // GOOD
129+
free(*a); // BAD [NOT DETECTED]
130+
*a = malloc(10);
131+
free(a[0]); // GOOD
132+
free(a[1]); // GOOD
133+
}
134+
135+
struct list {
136+
struct list *next;
137+
void* data;
138+
};
139+
140+
void test_loop1(struct list ** list_ptr) {
141+
struct list *next;
142+
while (*list_ptr) {
143+
free((*list_ptr)->data); // GOOD
144+
next = (*list_ptr)->next;
145+
free(*list_ptr); // GOOD
146+
*list_ptr = next;
147+
}
148+
free(list_ptr); // GOOD
149+
}
150+
151+
void test_use_after_free8(struct list * a) {
152+
if (condition()) free(a);
153+
a->data = malloc(10);
154+
free(a); // BAD
155+
}
156+
157+
void test_loop2(char ** a) {
158+
while (*a) {
159+
free(*a); // GOOD
160+
a++;
161+
}
162+
free(a); // GOOD
163+
}
164+
165+
void* test_realloc4() {
166+
void *a = 0;
167+
void *b = realloc(a, 10); // GOOD [FALSE POSITIVE]
168+
if (!b) { return a; }
169+
return b;
170+
}
171+
172+
void test_sizeof(int *a) {
173+
free(a);
174+
int x = sizeof(a[0]);
175+
}
176+
177+
void call_by_reference(char * &a);
178+
int custom_alloc_func(char ** a);
179+
180+
void test_reassign(char *a) {
181+
free(a); // GOOD
182+
asprintf(&a, "Hello world");
183+
free(a); //GOOD
184+
call_by_reference(a);
185+
free(a); // GOOD
186+
int v;
187+
if (v = custom_alloc_func(&a)) return;
188+
free(a); // GOOD
189+
}
190+
191+
char* test_return1(char *a) {
192+
int ret = condition();
193+
if (!ret) free(a);
194+
return (ret ? a : 0);
195+
}
196+
197+
char* test_return2(char *a) {
198+
int ret = condition();
199+
if (!ret) free(a);
200+
if (ret) return a;
201+
else return 0;
202+
}
203+
204+
void test_condition1(char *a) {
205+
free(a);
206+
if (asprintf(&a, "Hello world") || condition());
207+
free(a); //GOOD
208+
if (condition() || asprintf(&a, "Hello world"));
209+
free(a); // BAD
210+
}
211+
212+
void test_condition2(char *a) {
213+
free(a);
214+
if (condition()) a = (char*) malloc(10);
215+
else custom_alloc_func(&a);
216+
free(a); // GOOD
217+
}
218+
219+
void* test_return1(void *a) {
220+
free(a);
221+
return a;
222+
}
223+
224+
void MmFreePagesFromMdl(void*);
225+
void ExFreePool(void*);
226+
void test_ms_free(void * memory_descriptor_list) {
227+
MmFreePagesFromMdl(memory_descriptor_list); //GOOD
228+
ExFreePool(memory_descriptor_list); // GOOD
229+
}

0 commit comments

Comments
 (0)