Commit a342dc91 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Dave Airlie

renderer: fix leak in hashtable on replace

Some american fuzzy lop tests managed to replace resources, however the
old values got leaked (I am not sure if this should be allowed)

In all cases, introduce a destroy callback to the hashtable, used when a
value is removed, replaced or the table is cleared. This simplifies a
bit resource management and help avoid potential errors by using simply
refcounts.
Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
parent dcc83cca
...@@ -57,7 +57,8 @@ struct util_hash_table ...@@ -57,7 +57,8 @@ struct util_hash_table
/** Compare two keys */ /** Compare two keys */
int (*compare)(void *key1, void *key2); int (*compare)(void *key1, void *key2);
/* TODO: key, value destructors? */ /** free value */
void (*destroy)(void *value);
}; };
...@@ -77,7 +78,8 @@ util_hash_table_item(struct cso_hash_iter iter) ...@@ -77,7 +78,8 @@ util_hash_table_item(struct cso_hash_iter iter)
struct util_hash_table * struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key), util_hash_table_create(unsigned (*hash)(void *key),
int (*compare)(void *key1, void *key2)) int (*compare)(void *key1, void *key2),
void (*destroy)(void *value))
{ {
struct util_hash_table *ht; struct util_hash_table *ht;
...@@ -93,6 +95,7 @@ util_hash_table_create(unsigned (*hash)(void *key), ...@@ -93,6 +95,7 @@ util_hash_table_create(unsigned (*hash)(void *key),
ht->hash = hash; ht->hash = hash;
ht->compare = compare; ht->compare = compare;
ht->destroy = destroy;
return ht; return ht;
} }
...@@ -155,7 +158,7 @@ util_hash_table_set(struct util_hash_table *ht, ...@@ -155,7 +158,7 @@ util_hash_table_set(struct util_hash_table *ht,
item = util_hash_table_find_item(ht, key, key_hash); item = util_hash_table_find_item(ht, key, key_hash);
if(item) { if(item) {
/* TODO: key/value destruction? */ ht->destroy(item->value);
item->value = value; item->value = value;
return PIPE_OK; return PIPE_OK;
} }
...@@ -218,6 +221,7 @@ util_hash_table_remove(struct util_hash_table *ht, ...@@ -218,6 +221,7 @@ util_hash_table_remove(struct util_hash_table *ht,
item = util_hash_table_item(iter); item = util_hash_table_item(iter);
assert(item); assert(item);
ht->destroy(item->value);
FREE(item); FREE(item);
cso_hash_erase(ht->cso, iter); cso_hash_erase(ht->cso, iter);
...@@ -237,6 +241,7 @@ util_hash_table_clear(struct util_hash_table *ht) ...@@ -237,6 +241,7 @@ util_hash_table_clear(struct util_hash_table *ht)
iter = cso_hash_first_node(ht->cso); iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) { while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter)); item = (struct util_hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter));
ht->destroy(item->value);
FREE(item); FREE(item);
iter = cso_hash_first_node(ht->cso); iter = cso_hash_first_node(ht->cso);
} }
...@@ -283,6 +288,7 @@ util_hash_table_destroy(struct util_hash_table *ht) ...@@ -283,6 +288,7 @@ util_hash_table_destroy(struct util_hash_table *ht)
iter = cso_hash_first_node(ht->cso); iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) { while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter); item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
ht->destroy(item->value);
FREE(item); FREE(item);
iter = cso_hash_iter_next(iter); iter = cso_hash_iter_next(iter);
} }
......
...@@ -57,7 +57,8 @@ struct util_hash_table; ...@@ -57,7 +57,8 @@ struct util_hash_table;
*/ */
struct util_hash_table * struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key), util_hash_table_create(unsigned (*hash)(void *key),
int (*compare)(void *key1, void *key2)); int (*compare)(void *key1, void *key2),
void (*destroy)(void *value));
enum pipe_error enum pipe_error
......
...@@ -71,15 +71,10 @@ struct vrend_object { ...@@ -71,15 +71,10 @@ struct vrend_object {
bool free_data; bool free_data;
}; };
struct util_hash_table *vrend_object_init_ctx_table(void) static void free_object(void *value)
{ {
struct util_hash_table *ctx_hash; struct vrend_object *obj = value;
ctx_hash = util_hash_table_create(hash_func, compare);
return ctx_hash;
}
static void vrend_object_free(struct vrend_object *obj)
{
if (obj->free_data) { if (obj->free_data) {
if (obj_types[obj->type].unref) if (obj_types[obj->type].unref)
obj_types[obj->type].unref(obj->data); obj_types[obj->type].unref(obj->data);
...@@ -91,11 +86,11 @@ static void vrend_object_free(struct vrend_object *obj) ...@@ -91,11 +86,11 @@ static void vrend_object_free(struct vrend_object *obj)
free(obj); free(obj);
} }
static enum pipe_error free_cb(void *key, void *value, void *data) struct util_hash_table *vrend_object_init_ctx_table(void)
{ {
struct vrend_object *obj = value; struct util_hash_table *ctx_hash;
vrend_object_free(obj); ctx_hash = util_hash_table_create(hash_func, compare, free_object);
return PIPE_OK; return ctx_hash;
} }
void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash) void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash)
...@@ -103,29 +98,26 @@ void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash) ...@@ -103,29 +98,26 @@ void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash)
if (!ctx_hash) if (!ctx_hash)
return; return;
util_hash_table_foreach(ctx_hash, free_cb, NULL);
util_hash_table_destroy(ctx_hash); util_hash_table_destroy(ctx_hash);
} }
void static void free_res(void *value)
vrend_object_init_resource_table(void)
{
if (!res_hash)
res_hash = util_hash_table_create(hash_func, compare);
}
static enum pipe_error free_res_cb(void *key, void *value, void *data)
{ {
struct vrend_object *obj = value; struct vrend_object *obj = value;
(*resource_unref)(obj->data); (*resource_unref)(obj->data);
free(obj); free(obj);
return PIPE_OK; }
void
vrend_object_init_resource_table(void)
{
if (!res_hash)
res_hash = util_hash_table_create(hash_func, compare, free_res);
} }
void vrend_object_fini_resource_table(void) void vrend_object_fini_resource_table(void)
{ {
if (res_hash) { if (res_hash) {
util_hash_table_foreach(res_hash, free_res_cb, NULL);
util_hash_table_destroy(res_hash); util_hash_table_destroy(res_hash);
} }
res_hash = NULL; res_hash = NULL;
...@@ -159,15 +151,8 @@ void ...@@ -159,15 +151,8 @@ void
vrend_object_remove(struct util_hash_table *handle_hash, vrend_object_remove(struct util_hash_table *handle_hash,
uint32_t handle, enum virgl_object_type type) uint32_t handle, enum virgl_object_type type)
{ {
struct vrend_object *obj;
obj = util_hash_table_get(handle_hash, intptr_to_pointer(handle));
if (!obj)
return;
util_hash_table_remove(handle_hash, intptr_to_pointer(handle)); util_hash_table_remove(handle_hash, intptr_to_pointer(handle));
vrend_object_free(obj);
} }
void *vrend_object_lookup(struct util_hash_table *handle_hash, void *vrend_object_lookup(struct util_hash_table *handle_hash,
...@@ -204,13 +189,7 @@ int vrend_resource_insert(void *data, uint32_t handle) ...@@ -204,13 +189,7 @@ int vrend_resource_insert(void *data, uint32_t handle)
void vrend_resource_remove(uint32_t handle) void vrend_resource_remove(uint32_t handle)
{ {
struct vrend_object *obj;
obj = util_hash_table_get(res_hash, intptr_to_pointer(handle));
if (!obj)
return;
util_hash_table_remove(res_hash, intptr_to_pointer(handle)); util_hash_table_remove(res_hash, intptr_to_pointer(handle));
free(obj);
} }
void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id) void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id)
......
...@@ -4258,9 +4258,6 @@ void vrend_renderer_resource_unref(uint32_t res_handle) ...@@ -4258,9 +4258,6 @@ void vrend_renderer_resource_unref(uint32_t res_handle)
} }
vrend_resource_remove(res->handle); vrend_resource_remove(res->handle);
res->handle = 0;
vrend_resource_reference(&res, NULL);
} }
static int use_sub_data = 0; static int use_sub_data = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment