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