aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2014-09-06 18:21:58 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2014-09-11 19:22:57 +0300
commit13a07e35b6b5f813078bde6a1a17d05f017bf714 (patch)
tree612468a4d0602ba3f25b810b023526ac65c5eb48
parent0dce9ef635f8af1b9aa07a43f610295bca8954da (diff)
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().
-rw-r--r--pb_decode.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/pb_decode.c b/pb_decode.c
index 5d211023..ecd46dc1 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -895,22 +895,27 @@ void pb_release(const pb_field_t fields[], void *dest_struct)
pb_free(*pItem);
*pItem++ = NULL;
}
+ *(pb_size_t*)iter.pSize = 0;
}
else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
{
/* Release fields in submessages */
void *pItem = *(void**)iter.pData;
- pb_size_t count = (pItem ? 1 : 0);
-
- if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
- {
- count = *(pb_size_t*)iter.pSize;
- }
-
- while (count--)
+ if (pItem)
{
- pb_release((const pb_field_t*)iter.pos->ptr, pItem);
- pItem = (uint8_t*)pItem + iter.pos->data_size;
+ 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;
+ }
}
}