diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2014-06-02 21:12:38 +0300 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2014-06-02 21:12:38 +0300 |
commit | 99bc1d4f97710cc71612869d3d7e0f501a4626ff (patch) | |
tree | df58f9ca664ed5713812f14a7b4fe52ca21f9324 /pb_decode.c | |
parent | 8a857a7f7519414c2294cc9f3286ebe5dba5a6f3 (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.c | 29 |
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"); |