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:
65
pb_decode.c
65
pb_decode.c
@@ -928,6 +928,47 @@ static void pb_release_single_field(const pb_field_iter_t *iter)
|
|||||||
pb_type_t type;
|
pb_type_t type;
|
||||||
type = iter->pos->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_ATYPE(type) == PB_ATYPE_POINTER)
|
||||||
{
|
{
|
||||||
if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
|
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);
|
pb_free(*pItem);
|
||||||
*pItem++ = NULL;
|
*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 */
|
/* We are going to release the array, so set the size to 0 */
|
||||||
void *pItem = *(void**)iter->pData;
|
*(pb_size_t*)iter->pSize = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release main item */
|
/* Release main item */
|
||||||
|
|||||||
Reference in New Issue
Block a user