check_seapp: mac build memory leak

rule_map_free() took as a parameter a boolean menu rule_map_switch
that was used to determine if it should free the key pointer that
is also in the table. On GLIBC variants, calls to hdestroy do not
free the key pointer, on NON-GLIBC variants, it does. The original
patch was meant to correct this, however, it always passes "destroy"
as the rule_map_switch. On GLIBC variants this is fine, however on
NON-GLIBC variants, that free was compiled out, and the free() was
handled by hdestroy. In cases of failure where the rule_map was not
in the htable, those key's were not properly free'd.

Change-Id: Ifdf616e09862bca642a4d31bf0cb266168170e50
Signed-off-by: William Roberts <william.c.roberts@intel.com>
This commit is contained in:
William Roberts 2015-06-19 09:43:28 -07:00
parent 9c7570ef79
commit 7d65b547d3

View file

@ -50,17 +50,6 @@ enum key_dir {
dir_in, dir_out
};
/**
* Used as options to rule_map_free()
*
* This is needed to get around the fact that GNU C's hash_map doesn't copy the key, so
* we cannot free a key when overrding rule_map's in the table.
*/
enum rule_map_switch {
rule_map_preserve_key, /** Used to preserve the key in the rule_map, ie don't free it*/
rule_map_destroy_key /** Used when you need a full free of the rule_map structure*/
};
/**
* The expected "type" of data the value in the key
* value pair should be.
@ -407,8 +396,15 @@ static map_match rule_map_cmp(rule_map *rmA, rule_map *rmB) {
* @param rm
* rule map to be freed.
*/
static void rule_map_free(rule_map *rm,
rule_map_switch s __attribute__((unused)) /* only glibc builds, ignored otherwise */) {
/**
* Frees a rule map
* @param rm
* rule map to be freed.
* @is_in_htable
* True if the rule map has been added to the hash table, false
* otherwise.
*/
static void rule_map_free(rule_map *rm, bool is_in_htable) {
size_t i;
size_t len = rm->length;
@ -417,11 +413,22 @@ static void rule_map_free(rule_map *rm,
free(m->data);
}
/* hdestroy() frees comparsion keys for non glibc */
/*
* hdestroy() frees comparsion keys for non glibc
* on GLIBC we always free on NON-GLIBC we free if
* it is not in the htable.
*/
if (rm->key) {
#ifdef __GLIBC__
if(s == rule_map_destroy_key && rm->key)
/* silence unused warning */
(void)is_in_htable;
free(rm->key);
#else
if (!is_in_htable) {
free(rm->key);
}
#endif
}
free(rm);
}
@ -582,7 +589,7 @@ oom:
log_error("Out of memory!\n");
err:
if(new_map) {
rule_map_free(new_map, rule_map_destroy_key);
rule_map_free(new_map, false);
for (; i < num_of_keys; i++) {
k = &(keys[i]);
free_kvp(k);
@ -777,7 +784,7 @@ static void list_free() {
cursor = list_head;
while (cursor) {
e = cursor->e;
rule_map_free(e->r, rule_map_destroy_key);
rule_map_free(e->r, true);
tmp = cursor;
cursor = cursor->next;
free(e);
@ -817,7 +824,7 @@ static void rule_add(rule_map *rm) {
"Lines %d and %d %s!\n",
in_file_name, tmp->r->lineno, rm->lineno,
map_match_str[cmp]);
rule_map_free(rm, rule_map_destroy_key);
rule_map_free(rm, false);
goto err;
}
/* It wasn't found, just add the rule map to the table */