X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=pb_decode.c;h=8b782a6f2407049e5088940fdf3ccc0ebabea52b;hb=8a857a7f7519414c2294cc9f3286ebe5dba5a6f3;hp=7938d70b8e052f8604309cbfa443def7ceed2499;hpb=ab62402059ff3752660ffc9f292cf210aef59be0;p=apps%2Fagl-service-can-low-level.git diff --git a/pb_decode.c b/pb_decode.c index 7938d70b..8b782a6f 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -13,7 +13,6 @@ #define checkreturn __attribute__((warn_unused_result)) #endif -#define NANOPB_INTERNALS #include "pb.h" #include "pb_decode.h" @@ -130,7 +129,7 @@ bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count) * This is an optimization for the varint decoding. */ static bool checkreturn pb_readbyte(pb_istream_t *stream, uint8_t *buf) { - if (!stream->bytes_left) + if (stream->bytes_left == 0) PB_RETURN_ERROR(stream, "end-of-stream"); #ifndef PB_BUFFER_ONLY @@ -174,7 +173,7 @@ static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) if (!pb_readbyte(stream, &byte)) return false; - if (!(byte & 0x80)) + if ((byte & 0x80) == 0) { /* Quick case, 1 byte value */ result = byte; @@ -397,7 +396,7 @@ static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag) { return true; } - pb_field_next(iter); + (void)pb_field_next(iter); } while (iter->field_index != start); return false; @@ -435,7 +434,7 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t if (!pb_make_string_substream(stream, &substream)) return false; - while (substream.bytes_left && *size < iter->pos->array_size) + while (substream.bytes_left > 0 && *size < iter->pos->array_size) { void *pItem = (uint8_t*)iter->pData + iter->pos->data_size * (*size); if (!func(&substream, iter->pos, pItem)) @@ -471,16 +470,37 @@ 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. */ + * array_size is the number of entries to reserve in an array. + */ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) { void *ptr = *(void**)pData; - size_t size = array_size * data_size; + + /* Check for multiplication overflows. */ + size_t size = 0; + if (data_size > 0 && array_size > 0) + { + /* 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) + { + 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 = realloc(ptr, size); + ptr = pb_realloc(ptr, size); if (ptr == NULL) PB_RETURN_ERROR(stream, "realloc failed"); @@ -671,7 +691,6 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream, { const pb_field_t *field = (const pb_field_t*)extension->type->arg; pb_field_iterator_t iter; - bool dummy; if (field->tag != tag) return true; @@ -682,7 +701,7 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream, iter.required_field_index = 0; iter.dest_struct = extension->dest; iter.pData = extension->dest; - iter.pSize = &dummy; + iter.pSize = &extension->found; return decode_field(stream, wire_type, &iter); } @@ -695,7 +714,7 @@ static bool checkreturn decode_extension(pb_istream_t *stream, pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; size_t pos = stream->bytes_left; - while (extension && pos == stream->bytes_left) + while (extension != NULL && pos == stream->bytes_left) { bool status; if (extension->type->decode) @@ -722,7 +741,7 @@ static bool checkreturn find_extension_field(pb_field_iterator_t *iter) do { if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) return true; - pb_field_next(iter); + (void)pb_field_next(iter); } while (iter->field_index != start); return false; @@ -798,7 +817,7 @@ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_str bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { - uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */ + uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t extension_range_start = 0; pb_field_iterator_t iter; @@ -874,7 +893,7 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[ } while (pb_field_next(&iter)); /* Fixup if last field was also required. */ - if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag) + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) req_field_count++; /* Check the whole bytes */ @@ -945,7 +964,7 @@ void pb_release(const pb_field_t fields[], void *dest_struct) size_t count = *(size_t*)iter.pSize; while (count--) { - free(*pItem); + pb_free(*pItem); *pItem++ = NULL; } } @@ -968,7 +987,7 @@ void pb_release(const pb_field_t fields[], void *dest_struct) } /* Release main item */ - free(*(void**)iter.pData); + pb_free(*(void**)iter.pData); *(void**)iter.pData = NULL; } } while (pb_field_next(&iter)); @@ -1033,7 +1052,7 @@ bool pb_decode_fixed64(pb_istream_t *stream, void *dest) #endif } -bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint64_t value; if (!pb_decode_varint(stream, &value)) @@ -1051,7 +1070,7 @@ bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, vo return true; } -bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint64_t value; if (!pb_decode_varint(stream, &value)) @@ -1067,7 +1086,7 @@ bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, v return true; } -bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) { int64_t value; if (!pb_decode_svarint(stream, &value)) @@ -1083,19 +1102,19 @@ bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, v return true; } -bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) { UNUSED(field); return pb_decode_fixed32(stream, dest); } -bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) { UNUSED(field); return pb_decode_fixed64(stream, dest); } -bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint32_t size; pb_bytes_array_t *bdest; @@ -1124,7 +1143,7 @@ bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, voi return pb_read(stream, bdest->bytes, size); } -bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint32_t size; size_t alloc_size; @@ -1156,7 +1175,7 @@ bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, vo return status; } -bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) { bool status; pb_istream_t substream;