diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c index 4f23d09c5..8dafdedac 100644 --- a/libcutils/str_parms.c +++ b/libcutils/str_parms.c @@ -31,6 +31,20 @@ #define UNUSED __attribute__((unused)) +/* When an object is allocated but not freed in a function, + * because its ownership is released to other object like a hashmap, + * call RELEASE_OWNERSHIP to tell the clang analyzer and avoid + * false warnings about potential memory leak. + * For now, a "temporary" assignment to global variables + * is enough to confuse the clang static analyzer. + */ +#ifdef __clang_analyzer__ +static void *released_pointer; +#define RELEASE_OWNERSHIP(x) { released_pointer = x; released_pointer = 0; } +#else +#define RELEASE_OWNERSHIP(x) +#endif + struct str_parms { Hashmap *map; }; @@ -170,9 +184,12 @@ struct str_parms *str_parms_create_str(const char *_string) /* if we replaced a value, free it */ old_val = hashmapPut(str_parms->map, key, value); + RELEASE_OWNERSHIP(value); if (old_val) { free(old_val); free(key); + } else { + RELEASE_OWNERSHIP(key); } items++; @@ -222,10 +239,13 @@ int str_parms_add_str(struct str_parms *str_parms, const char *key, goto clean_up; } // For new keys, hashmap takes ownership of tmp_key and tmp_val. + RELEASE_OWNERSHIP(tmp_key); + RELEASE_OWNERSHIP(tmp_val); tmp_key = tmp_val = NULL; } else { // For existing keys, hashmap takes ownership of tmp_val. // (It also gives up ownership of old_val.) + RELEASE_OWNERSHIP(tmp_val); tmp_val = NULL; }