mirror of https://gitee.com/openkylin/libvirt.git
hash: fix memory leak regression
Commit 1671d1d
introduced a memory leak in virHashFree, and
wholesale table corruption in virHashRemoveSet (elements not
requested to be freed are lost).
* src/util/hash.c (virHashFree): Free bucket array.
(virHashRemoveSet): Don't lose elements.
* tests/hashtest.c (testHashCheckForEachCount): New method.
(testHashCheckCount): Expose the bug.
This commit is contained in:
parent
41a7835fa0
commit
701bee0193
|
@ -269,6 +269,7 @@ virHashFree(virHashTablePtr table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VIR_FREE(table->table);
|
||||||
VIR_FREE(table);
|
VIR_FREE(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,13 +533,12 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data)
|
||||||
* virHashRemoveSet
|
* virHashRemoveSet
|
||||||
* @table: the hash table to process
|
* @table: the hash table to process
|
||||||
* @iter: callback to identify elements for removal
|
* @iter: callback to identify elements for removal
|
||||||
* @f: callback to free memory from element payload
|
|
||||||
* @data: opaque data to pass to the iterator
|
* @data: opaque data to pass to the iterator
|
||||||
*
|
*
|
||||||
* Iterates over all elements in the hash table, invoking the 'iter'
|
* Iterates over all elements in the hash table, invoking the 'iter'
|
||||||
* callback. If the callback returns a non-zero value, the element
|
* callback. If the callback returns a non-zero value, the element
|
||||||
* will be removed from the hash table & its payload passed to the
|
* will be removed from the hash table & its payload passed to the
|
||||||
* callback 'f' for de-allocation.
|
* data freer callback registered at creation.
|
||||||
*
|
*
|
||||||
* Returns number of items removed on success, -1 on failure
|
* Returns number of items removed on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
|
@ -562,7 +562,7 @@ int virHashRemoveSet(virHashTablePtr table,
|
||||||
while (*nextptr) {
|
while (*nextptr) {
|
||||||
virHashEntryPtr entry = *nextptr;
|
virHashEntryPtr entry = *nextptr;
|
||||||
if (!iter(entry->payload, entry->name, data)) {
|
if (!iter(entry->payload, entry->name, data)) {
|
||||||
*nextptr = entry->next;
|
nextptr = &entry->next;
|
||||||
} else {
|
} else {
|
||||||
count++;
|
count++;
|
||||||
if (table->dataFree)
|
if (table->dataFree)
|
||||||
|
|
|
@ -61,16 +61,31 @@ testHashInit(int size)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
testHashCheckForEachCount(void *payload ATTRIBUTE_UNUSED,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
testHashCheckCount(virHashTablePtr hash, int count)
|
testHashCheckCount(virHashTablePtr hash, int count)
|
||||||
{
|
{
|
||||||
|
int iter_count = 0;
|
||||||
|
|
||||||
if (virHashSize(hash) != count) {
|
if (virHashSize(hash) != count) {
|
||||||
testError("\nhash contains %d instead of %d elements\n",
|
testError("\nhash contains %d instead of %d elements\n",
|
||||||
virHashSize(hash), count);
|
virHashSize(hash), count);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iter_count = virHashForEach(hash, testHashCheckForEachCount, NULL);
|
||||||
|
if (count != iter_count) {
|
||||||
|
testError("\nhash claims to have %d elements but iteration finds %d\n",
|
||||||
|
count, iter_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue