From: Petteri Aimonen Date: Fri, 26 Dec 2014 21:14:39 +0000 (+0200) Subject: Fix memory leaks with PB_ENABLE_MALLOC and certain submessage type combinations. X-Git-Tag: 5.0.2~186^2~176 X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=88b2efe0477f4f9e313b5d7307dfd347b6893376;p=apps%2Fagl-service-can-low-level.git 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 --- diff --git a/pb_decode.c b/pb_decode.c index f0fa1cce..367f073b 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -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 */