Don't use SIZE_MAX macro, as it is not in C89.
[apps/agl-service-can-low-level.git] / pb_decode.c
index 1213336..8b782a6 100644 (file)
@@ -13,7 +13,6 @@
     #define checkreturn __attribute__((warn_unused_result))
 #endif
 
-#define NANOPB_INTERNALS
 #include "pb.h"
 #include "pb_decode.h"
 
@@ -471,11 +470,32 @@ 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,
@@ -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);
 }
@@ -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;