xref: /openbmc/qemu/scripts/coverity-scan/model.c (revision 744c72a8)
1 /* Coverity Scan model
2  *
3  * Copyright (C) 2014 Red Hat, Inc.
4  *
5  * Authors:
6  *  Markus Armbruster <armbru@redhat.com>
7  *  Paolo Bonzini <pbonzini@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or, at your
10  * option, any later version.  See the COPYING file in the top-level directory.
11  */
12 
13 
14 /*
15  * This is the source code for our Coverity user model file.  The
16  * purpose of user models is to increase scanning accuracy by explaining
17  * code Coverity can't see (out of tree libraries) or doesn't
18  * sufficiently understand.  Better accuracy means both fewer false
19  * positives and more true defects.  Memory leaks in particular.
20  *
21  * - A model file can't import any header files.  Some built-in primitives are
22  *   available but not wchar_t, NULL etc.
23  * - Modeling doesn't need full structs and typedefs. Rudimentary structs
24  *   and similar types are sufficient.
25  * - An uninitialized local variable signifies that the variable could be
26  *   any value.
27  *
28  * The model file must be uploaded by an admin in the analysis settings of
29  * http://scan.coverity.com/projects/378
30  */
31 
32 #define NULL ((void *)0)
33 
34 typedef unsigned char uint8_t;
35 typedef char int8_t;
36 typedef unsigned int uint32_t;
37 typedef int int32_t;
38 typedef long ssize_t;
39 typedef unsigned long long uint64_t;
40 typedef long long int64_t;
41 typedef _Bool bool;
42 
43 typedef struct va_list_str *va_list;
44 
45 /* exec.c */
46 
47 typedef struct AddressSpace AddressSpace;
48 typedef uint64_t hwaddr;
49 typedef uint32_t MemTxResult;
50 typedef uint64_t MemTxAttrs;
51 
52 static void __bufwrite(uint8_t *buf, ssize_t len)
53 {
54     int first, last;
55     __coverity_negative_sink__(len);
56     if (len == 0) return;
57     buf[0] = first;
58     buf[len-1] = last;
59     __coverity_writeall__(buf);
60 }
61 
62 static void __bufread(uint8_t *buf, ssize_t len)
63 {
64     __coverity_negative_sink__(len);
65     if (len == 0) return;
66     int first = buf[0];
67     int last = buf[len-1];
68 }
69 
70 MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
71                                MemTxAttrs attrs,
72                                uint8_t *buf, int len)
73 {
74     MemTxResult result;
75     // TODO: investigate impact of treating reads as producing
76     // tainted data, with __coverity_tainted_data_argument__(buf).
77     __bufwrite(buf, len);
78     return result;
79 }
80 
81 MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
82                                 MemTxAttrs attrs,
83                                 const uint8_t *buf, int len)
84 {
85     MemTxResult result;
86     __bufread(buf, len);
87     return result;
88 }
89 
90 
91 /* Tainting */
92 
93 typedef struct {} name2keysym_t;
94 static int get_keysym(const name2keysym_t *table,
95                       const char *name)
96 {
97     int result;
98     if (result > 0) {
99         __coverity_tainted_string_sanitize_content__(name);
100         return result;
101     } else {
102         return 0;
103     }
104 }
105 
106 /* Replay data is considered trusted.  */
107 uint8_t replay_get_byte(void)
108 {
109     uint8_t byte;
110     return byte;
111 }
112 
113 
114 /*
115  * GLib memory allocation functions.
116  *
117  * Note that we ignore the fact that g_malloc of 0 bytes returns NULL,
118  * and g_realloc of 0 bytes frees the pointer.
119  *
120  * Modeling this would result in Coverity flagging a lot of memory
121  * allocations as potentially returning NULL, and asking us to check
122  * whether the result of the allocation is NULL or not.  However, the
123  * resulting pointer should never be dereferenced anyway, and in fact
124  * it is not in the vast majority of cases.
125  *
126  * If a dereference did happen, this would suppress a defect report
127  * for an actual null pointer dereference.  But it's too unlikely to
128  * be worth wading through the false positives, and with some luck
129  * we'll get a buffer overflow reported anyway.
130  */
131 
132 /*
133  * Allocation primitives, cannot return NULL
134  * See also Coverity's library/generic/libc/all/all.c
135  */
136 
137 void *g_malloc_n(size_t nmemb, size_t size)
138 {
139     size_t sz;
140     void *ptr;
141 
142     __coverity_negative_sink__(nmemb);
143     __coverity_negative_sink__(size);
144     sz = nmemb * size;
145     ptr = __coverity_alloc__(sz);
146     __coverity_mark_as_uninitialized_buffer__(ptr);
147     __coverity_mark_as_afm_allocated__(ptr, "g_free");
148     return ptr;
149 }
150 
151 void *g_malloc0_n(size_t nmemb, size_t size)
152 {
153     size_t sz;
154     void *ptr;
155 
156     __coverity_negative_sink__(nmemb);
157     __coverity_negative_sink__(size);
158     sz = nmemb * size;
159     ptr = __coverity_alloc__(sz);
160     __coverity_writeall0__(ptr);
161     __coverity_mark_as_afm_allocated__(ptr, "g_free");
162     return ptr;
163 }
164 
165 void *g_realloc_n(void *ptr, size_t nmemb, size_t size)
166 {
167     size_t sz;
168 
169     __coverity_negative_sink__(nmemb);
170     __coverity_negative_sink__(size);
171     sz = nmemb * size;
172     __coverity_escape__(ptr);
173     ptr = __coverity_alloc__(sz);
174     /*
175      * Memory beyond the old size isn't actually initialized.  Can't
176      * model that.  See Coverity's realloc() model
177      */
178     __coverity_writeall__(ptr);
179     __coverity_mark_as_afm_allocated__(ptr, "g_free");
180     return ptr;
181 }
182 
183 void g_free(void *ptr)
184 {
185     __coverity_free__(ptr);
186     __coverity_mark_as_afm_freed__(ptr, "g_free");
187 }
188 
189 /*
190  * Derive the g_try_FOO_n() from the g_FOO_n() by adding indeterminate
191  * out of memory conditions
192  */
193 
194 void *g_try_malloc_n(size_t nmemb, size_t size)
195 {
196     int nomem;
197 
198     if (nomem) {
199         return NULL;
200     }
201     return g_malloc_n(nmemb, size);
202 }
203 
204 void *g_try_malloc0_n(size_t nmemb, size_t size)
205 {
206     int nomem;
207 
208     if (nomem) {
209         return NULL;
210     }
211     return g_malloc0_n(nmemb, size);
212 }
213 
214 void *g_try_realloc_n(void *ptr, size_t nmemb, size_t size)
215 {
216     int nomem;
217 
218     if (nomem) {
219         return NULL;
220     }
221     return g_realloc_n(ptr, nmemb, size);
222 }
223 
224 /* Trivially derive the g_FOO() from the g_FOO_n() */
225 
226 void *g_malloc(size_t size)
227 {
228     return g_malloc_n(1, size);
229 }
230 
231 void *g_malloc0(size_t size)
232 {
233     return g_malloc0_n(1, size);
234 }
235 
236 void *g_realloc(void *ptr, size_t size)
237 {
238     return g_realloc_n(ptr, 1, size);
239 }
240 
241 void *g_try_malloc(size_t size)
242 {
243     return g_try_malloc_n(1, size);
244 }
245 
246 void *g_try_malloc0(size_t size)
247 {
248     return g_try_malloc0_n(1, size);
249 }
250 
251 void *g_try_realloc(void *ptr, size_t size)
252 {
253     return g_try_realloc_n(ptr, 1, size);
254 }
255 
256 /* Other memory allocation functions */
257 
258 void *g_memdup(const void *ptr, unsigned size)
259 {
260     unsigned char *dup;
261     unsigned i;
262 
263     if (!ptr) {
264         return NULL;
265     }
266 
267     dup = g_malloc(size);
268     for (i = 0; i < size; i++)
269         dup[i] = ((unsigned char *)ptr)[i];
270     return dup;
271 }
272 
273 /*
274  * GLib string allocation functions
275  */
276 
277 char *g_strdup(const char *s)
278 {
279     char *dup;
280     size_t i;
281 
282     if (!s) {
283         return NULL;
284     }
285 
286     __coverity_string_null_sink__(s);
287     __coverity_string_size_sink__(s);
288     dup = __coverity_alloc_nosize__();
289     __coverity_mark_as_afm_allocated__(dup, "g_free");
290     for (i = 0; (dup[i] = s[i]); i++) ;
291     return dup;
292 }
293 
294 char *g_strndup(const char *s, size_t n)
295 {
296     char *dup;
297     size_t i;
298 
299     __coverity_negative_sink__(n);
300 
301     if (!s) {
302         return NULL;
303     }
304 
305     dup = g_malloc(n + 1);
306     for (i = 0; i < n && (dup[i] = s[i]); i++) ;
307     dup[i] = 0;
308     return dup;
309 }
310 
311 char *g_strdup_printf(const char *format, ...)
312 {
313     char ch, *s;
314     size_t len;
315 
316     __coverity_string_null_sink__(format);
317     __coverity_string_size_sink__(format);
318 
319     ch = *format;
320 
321     s = __coverity_alloc_nosize__();
322     __coverity_writeall__(s);
323     __coverity_mark_as_afm_allocated__(s, "g_free");
324     return s;
325 }
326 
327 char *g_strdup_vprintf(const char *format, va_list ap)
328 {
329     char ch, *s;
330     size_t len;
331 
332     __coverity_string_null_sink__(format);
333     __coverity_string_size_sink__(format);
334 
335     ch = *format;
336     ch = *(char *)ap;
337 
338     s = __coverity_alloc_nosize__();
339     __coverity_writeall__(s);
340     __coverity_mark_as_afm_allocated__(s, "g_free");
341 
342     return len;
343 }
344 
345 char *g_strconcat(const char *s, ...)
346 {
347     char *s;
348 
349     /*
350      * Can't model: last argument must be null, the others
351      * null-terminated strings
352      */
353 
354     s = __coverity_alloc_nosize__();
355     __coverity_writeall__(s);
356     __coverity_mark_as_afm_allocated__(s, "g_free");
357     return s;
358 }
359 
360 /* Other glib functions */
361 
362 typedef struct pollfd GPollFD;
363 
364 int poll();
365 
366 int g_poll (GPollFD *fds, unsigned nfds, int timeout)
367 {
368     return poll(fds, nfds, timeout);
369 }
370 
371 typedef struct _GIOChannel GIOChannel;
372 GIOChannel *g_io_channel_unix_new(int fd)
373 {
374     GIOChannel *c = g_malloc0(sizeof(GIOChannel));
375     __coverity_escape__(fd);
376     return c;
377 }
378 
379 void g_assertion_message_expr(const char     *domain,
380                               const char     *file,
381                               int             line,
382                               const char     *func,
383                               const char     *expr)
384 {
385     __coverity_panic__();
386 }
387