diff options
author | Markus Armbruster <armbru@redhat.com> | 2015-01-26 15:05:11 +0100 |
---|---|---|
committer | Markus Armbruster <armbru@redhat.com> | 2015-02-05 17:16:07 +0100 |
commit | e4b77daa5724a9dd41aaa44d2dea4b8e92351081 (patch) | |
tree | 400f986980cddbe191501de75d426e98ce373cfa /scripts | |
parent | 9d7a4c6690ef9962a3b20034f65008f1ea15c1d6 (diff) | |
download | qemu-e4b77daa5724a9dd41aaa44d2dea4b8e92351081.zip |
coverity: Model GLib string allocation partially
Without a model, Coverity can't know that the result of g_strdup()
needs to be fed to g_free().
One way to get such a model is to scan GLib, build a derived model
file with cov-collect-models, and use that when scanning QEMU.
Unfortunately, the Coverity Scan service we use doesn't support that.
Thus, we're stuck with the other way: write a user model. Doing that
for all of GLib is hardly practical. I'm doing it for the "String
Utility Functions" we actually use that return dynamically allocated
strings.
In a local scan, this flags 20 additional RESOURCE_LEAKs. The ones I
checked look genuine.
It also loses a NULL_RETURNS about ppce500_init() using
qemu_find_file() without error checking. I don't understand why.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/coverity-model.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c index 8d0839ef08..230bc30cf9 100644 --- a/scripts/coverity-model.c +++ b/scripts/coverity-model.c @@ -40,6 +40,8 @@ typedef unsigned long long uint64_t; typedef long long int64_t; typedef _Bool bool; +typedef struct va_list_str *va_list; + /* exec.c */ typedef struct AddressSpace AddressSpace; @@ -232,6 +234,93 @@ void *g_try_realloc(void *ptr, size_t size) return g_try_realloc_n(ptr, 1, size); } +/* + * GLib string allocation functions + */ + +char *g_strdup(const char *s) +{ + char *dup; + size_t i; + + if (!s) { + return NULL; + } + + __coverity_string_null_sink__(s); + __coverity_string_size_sink__(s); + dup = __coverity_alloc_nosize__(); + __coverity_mark_as_afm_allocated__(dup, AFM_free); + for (i = 0; (dup[i] = s[i]); i++) ; + return dup; +} + +char *g_strndup(const char *s, size_t n) +{ + char *dup; + size_t i; + + __coverity_negative_sink__(n); + + if (!s) { + return NULL; + } + + dup = g_malloc(n + 1); + for (i = 0; i < n && (dup[i] = s[i]); i++) ; + dup[i] = 0; + return dup; +} + +char *g_strdup_printf(const char *format, ...) +{ + char ch, *s; + size_t len; + + __coverity_string_null_sink__(format); + __coverity_string_size_sink__(format); + + ch = *format; + + s = __coverity_alloc_nosize__(); + __coverity_writeall__(s); + __coverity_mark_as_afm_allocated__(s, AFM_free); + return s; +} + +char *g_strdup_vprintf(const char *format, va_list ap) +{ + char ch, *s; + size_t len; + + __coverity_string_null_sink__(format); + __coverity_string_size_sink__(format); + + ch = *format; + ch = *(char *)ap; + + s = __coverity_alloc_nosize__(); + __coverity_writeall__(s); + __coverity_mark_as_afm_allocated__(s, AFM_free); + + return len; +} + +char *g_strconcat(const char *s, ...) +{ + char *s; + + /* + * Can't model: last argument must be null, the others + * null-terminated strings + */ + + s = __coverity_alloc_nosize__(); + __coverity_writeall__(s); + __coverity_mark_as_afm_allocated__(s, AFM_free); + return s; +} + /* Other glib functions */ typedef struct _GIOChannel GIOChannel; |