Skip to content

Commit

Permalink
coverity: Model GLib string allocation partially
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Paolo Bonzini <[email protected]>
  • Loading branch information
Markus Armbruster committed Feb 5, 2015
1 parent 9d7a4c6 commit e4b77da
Showing 1 changed file with 89 additions and 0 deletions.
89 changes: 89 additions & 0 deletions scripts/coverity-model.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit e4b77da

Please sign in to comment.