Fix crash in pb_release() if called twice on same message.

There was a double-free bug in pb_release() because it didn't set size fields
to zero after deallocation. Most commonly this happens if pb_decode() fails,
internally calls pb_release() and then application code also calls pb_release().
This commit is contained in:
Petteri Aimonen
2014-09-06 18:21:58 +03:00
parent 2f05a35b5f
commit b7add1e577

View File

@@ -962,22 +962,27 @@ void pb_release(const pb_field_t fields[], void *dest_struct)
pb_free(*pItem); pb_free(*pItem);
*pItem++ = NULL; *pItem++ = NULL;
} }
*(pb_size_t*)iter.pSize = 0;
} }
else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
{ {
/* Release fields in submessages */ /* Release fields in submessages */
void *pItem = *(void**)iter.pData; void *pItem = *(void**)iter.pData;
size_t count = (pItem ? 1 : 0); if (pItem)
if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
{ {
count = *(size_t*)iter.pSize; pb_size_t count = 1;
}
while (count--) if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
{ {
pb_release((const pb_field_t*)iter.pos->ptr, pItem); count = *(pb_size_t*)iter.pSize;
pItem = (uint8_t*)pItem + iter.pos->data_size; *(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;
}
} }
} }