summaryrefslogtreecommitdiffstats
path: root/pb_decode.c
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2014-06-02 21:12:38 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2014-06-02 21:12:38 +0300
commit99bc1d4f97710cc71612869d3d7e0f501a4626ff (patch)
treedf58f9ca664ed5713812f14a7b4fe52ca21f9324 /pb_decode.c
parent8a857a7f7519414c2294cc9f3286ebe5dba5a6f3 (diff)
Make clearer that size = 0 in allocate_field() is not allowed.
Back in design phase the code used realloc() for freeing the memory also. However, this is not entirely portable, and therefore the finished implementation used free() separately. There were some remnants of the size = 0 code in the allocate_field() code, which made it somewhat confusing. This change makes it clearer that size = 0 is not allowed (and not used by nanopb).
Diffstat (limited to 'pb_decode.c')
-rw-r--r--pb_decode.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/pb_decode.c b/pb_decode.c
index 8b782a6f..4e187256 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -471,36 +471,31 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
#ifdef PB_ENABLE_MALLOC
/* Allocate storage for the field and store the pointer at iter->pData.
* array_size is the number of entries to reserve in an array.
+ * Zero size is not allowed, use pb_free() for releasing.
*/
static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size)
{
void *ptr = *(void**)pData;
- /* Check for multiplication overflows. */
- size_t size = 0;
- if (data_size > 0 && array_size > 0)
+ /* Check for multiplication overflows.
+ * This code avoids the costly division if the sizes are small enough.
+ * Multiplication is safe as long as only half of bits are set
+ * in either multiplicand.
+ */
+ const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
+ if (data_size >= check_limit || array_size >= check_limit)
{
- /* Avoid the costly division if the sizes are small enough.
- * Multiplication is safe as long as only half of bits are set
- * in either multiplicand.
- */
- const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
- if (data_size >= check_limit || array_size >= check_limit)
+ const size_t size_max = (size_t)-1;
+ if (size_max / array_size < data_size)
{
- const size_t size_max = (size_t)-1;
- if (size_max / array_size < data_size)
- {
- PB_RETURN_ERROR(stream, "size too large");
- }
+ PB_RETURN_ERROR(stream, "size too large");
}
-
- size = array_size * data_size;
}
/* Allocate new or expand previous allocation */
/* Note: on failure the old pointer will remain in the structure,
* the message must be freed by caller also on error return. */
- ptr = pb_realloc(ptr, size);
+ ptr = pb_realloc(ptr, array_size * data_size);
if (ptr == NULL)
PB_RETURN_ERROR(stream, "realloc failed");