kmalloc-linux.c
2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux %s -verify \
// RUN: -Wno-incompatible-library-redeclaration \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=unix.Malloc
#define __GFP_ZERO 0x8000
#define NULL ((void *)0)
typedef __typeof(sizeof(int)) size_t;
void *kmalloc(size_t, int);
void kfree(void *);
struct test {
};
void foo(struct test *);
void test_zeroed() {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, __GFP_ZERO);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i];
foo(t);
}
kfree(list); // no-warning
}
void test_nonzero() {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, 0);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{undefined}}
foo(t);
}
kfree(list);
}
void test_indeterminate(int flags) {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, flags);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{undefined}}
foo(t);
}
kfree(list);
}
typedef unsigned long long uint64_t;
struct malloc_type;
// 3 parameter malloc:
// https://www.freebsd.org/cgi/man.cgi?query=malloc&sektion=9
void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
void test_3arg_malloc(struct malloc_type *mtp) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, __GFP_ZERO);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i];
foo(t);
}
kfree(list); // no-warning
}
void test_3arg_malloc_nonzero(struct malloc_type *mtp) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, 0);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{undefined}}
foo(t);
}
kfree(list);
}
void test_3arg_malloc_indeterminate(struct malloc_type *mtp, int flags) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, flags);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{undefined}}
foo(t);
}
kfree(list);
}
void test_3arg_malloc_leak(struct malloc_type *mtp, int flags) {
struct test **list;
list = malloc(sizeof(*list) * 10, mtp, flags);
if (list == NULL)
return;
} // expected-warning{{Potential leak of memory pointed to by 'list'}}
// kmalloc can return a constant value defined in ZERO_SIZE_PTR
// if a block of size 0 is requested
#define ZERO_SIZE_PTR ((void *)16)
void test_kfree_ZERO_SIZE_PTR() {
void *ptr = ZERO_SIZE_PTR;
kfree(ptr); // no warning about freeing this value
}
void test_kfree_other_constant_value() {
void *ptr = (void *)1;
kfree(ptr); // expected-warning{{Argument to kfree() is a constant address (1)}}
}