cache: free the cache table when it is empty and set to NULL

We do the latter for the benefit of libpkgconf. This cleans up a
significant number of memory leaks in the cache handling.
pull/239/head
Dylan Baker 2022-08-03 15:24:05 -07:00
parent d240afe7d9
commit ebe74fd253
2 changed files with 27 additions and 2 deletions

View File

@ -16,6 +16,8 @@
#include <libpkgconf/stdinc.h> #include <libpkgconf/stdinc.h>
#include <libpkgconf/libpkgconf.h> #include <libpkgconf/libpkgconf.h>
#include <assert.h>
/* /*
* !doc * !doc
* *
@ -86,6 +88,9 @@ cache_dump(const pkgconf_client_t *client)
pkgconf_pkg_t * pkgconf_pkg_t *
pkgconf_cache_lookup(pkgconf_client_t *client, const char *id) pkgconf_cache_lookup(pkgconf_client_t *client, const char *id)
{ {
if (client->cache_table == NULL)
return NULL;
pkgconf_pkg_t **pkg; pkgconf_pkg_t **pkg;
pkg = bsearch(id, client->cache_table, pkg = bsearch(id, client->cache_table,
@ -150,6 +155,9 @@ pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
void void
pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg) pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
{ {
if (client->cache_table == NULL)
return;
if (pkg == NULL) if (pkg == NULL)
return; return;
@ -181,8 +189,16 @@ pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
} }
client->cache_count--; client->cache_count--;
if (client->cache_count > 0)
{
client->cache_table = pkgconf_reallocarray(client->cache_table, client->cache_table = pkgconf_reallocarray(client->cache_table,
client->cache_count, sizeof(void *)); client->cache_count, sizeof(void *));
}
else
{
free(client->cache_table);
client->cache_table = NULL;
}
} }
static inline void static inline void
@ -211,6 +227,9 @@ clear_dependency_matches(pkgconf_list_t *list)
void void
pkgconf_cache_free(pkgconf_client_t *client) pkgconf_cache_free(pkgconf_client_t *client)
{ {
if (client->cache_table == NULL)
return;
pkgconf_pkg_t **cache_table; pkgconf_pkg_t **cache_table;
size_t i, count; size_t i, count;
@ -235,6 +254,10 @@ pkgconf_cache_free(pkgconf_client_t *client)
pkgconf_pkg_t *pkg = cache_table[i]; pkgconf_pkg_t *pkg = cache_table[i];
pkgconf_pkg_free(client, pkg); pkgconf_pkg_free(client, pkg);
} }
free(cache_table);
free(client->cache_table);
client->cache_table = NULL;
client->cache_count = 0;
PKGCONF_TRACE(client, "cleared package cache"); PKGCONF_TRACE(client, "cleared package cache");
} }

View File

@ -98,6 +98,8 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
client->error_handler_data = error_handler_data; client->error_handler_data = error_handler_data;
client->error_handler = error_handler; client->error_handler = error_handler;
client->auditf = NULL; client->auditf = NULL;
client->cache_table = NULL;
client->cache_count = 0;
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
if (client->trace_handler == NULL) if (client->trace_handler == NULL)