Add just-to-be-sure check to allocate_field().

This check will help to detect bugs earlier, and is quite lightweight
compared to malloc() anyway.
This commit is contained in:
Petteri Aimonen
2014-09-08 17:33:05 +03:00
parent 5e3edb5415
commit d0466bdf43

View File

@@ -45,6 +45,7 @@ static bool checkreturn pb_skip_varint(pb_istream_t *stream);
static bool checkreturn pb_skip_string(pb_istream_t *stream); static bool checkreturn pb_skip_string(pb_istream_t *stream);
#ifdef PB_ENABLE_MALLOC #ifdef PB_ENABLE_MALLOC
static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
static void pb_release_single_field(const pb_field_iter_t *iter); static void pb_release_single_field(const pb_field_iter_t *iter);
#endif #endif
@@ -404,11 +405,15 @@ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t
{ {
void *ptr = *(void**)pData; void *ptr = *(void**)pData;
if (data_size == 0 || array_size == 0)
PB_RETURN_ERROR(stream, "invalid size");
/* Check for multiplication overflows. /* Check for multiplication overflows.
* This code avoids the costly division if the sizes are small enough. * This code avoids the costly division if the sizes are small enough.
* Multiplication is safe as long as only half of bits are set * Multiplication is safe as long as only half of bits are set
* in either multiplicand. * in either multiplicand.
*/ */
{
const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
if (data_size >= check_limit || array_size >= check_limit) if (data_size >= check_limit || array_size >= check_limit)
{ {
@@ -418,6 +423,7 @@ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t
PB_RETURN_ERROR(stream, "size too large"); PB_RETURN_ERROR(stream, "size too large");
} }
} }
}
/* Allocate new or expand previous allocation */ /* Allocate new or expand previous allocation */
/* Note: on failure the old pointer will remain in the structure, /* Note: on failure the old pointer will remain in the structure,