Fix memory leaks with PB_ENABLE_MALLOC and certain submessage type combinations.

There was a memory leak when:

1) A statically allocated submessage or
2) an extension field submessage

contained

A) a pointer-type field or
B) a submessage that further contained a pointer-type field.

This was because pb_release() didn't recurse into non-pointer fields.

Update issue 138
Status: FixedInGit
This commit is contained in:
Petteri Aimonen
2014-12-26 23:14:39 +02:00
parent 5008830488
commit 88b2efe047

View File

@@ -928,6 +928,47 @@ static void pb_release_single_field(const pb_field_iter_t *iter)
pb_type_t type;
type = iter->pos->type;
/* Release anything contained inside an extension or submsg.
* This has to be done even if the submsg itself is statically
* allocated. */
if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
{
/* Release fields from all extensions in the linked list */
pb_extension_t *ext = *(pb_extension_t**)iter->pData;
while (ext != NULL)
{
pb_field_iter_t ext_iter;
iter_from_extension(&ext_iter, ext);
pb_release_single_field(&ext_iter);
ext = ext->next;
}
}
else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
{
/* Release fields in submessage or submsg array */
void *pItem = iter->pData;
pb_size_t count = 1;
if (PB_ATYPE(type) == PB_ATYPE_POINTER)
{
pItem = *(void**)iter->pData;
}
if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
{
count = *(pb_size_t*)iter->pSize;
}
if (pItem)
{
while (count--)
{
pb_release((const pb_field_t*)iter->pos->ptr, pItem);
pItem = (uint8_t*)pItem + iter->pos->data_size;
}
}
}
if (PB_ATYPE(type) == PB_ATYPE_POINTER)
{
if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
@@ -942,28 +983,12 @@ static void pb_release_single_field(const pb_field_iter_t *iter)
pb_free(*pItem);
*pItem++ = NULL;
}
*(pb_size_t*)iter->pSize = 0;
}
else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
{
/* Release fields in submessages */
void *pItem = *(void**)iter->pData;
if (pItem)
{
pb_size_t count = 1;
if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
{
count = *(pb_size_t*)iter->pSize;
*(pb_size_t*)iter->pSize = 0;
}
while (count--)
{
pb_release((const pb_field_t*)iter->pos->ptr, pItem);
pItem = (uint8_t*)pItem + iter->pos->data_size;
}
}
/* We are going to release the array, so set the size to 0 */
*(pb_size_t*)iter->pSize = 0;
}
/* Release main item */