X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=pb_decode.c;h=1fcc4e5a5d93ec9946bb6d4071f8386432b861b2;hb=af848f61abff7d1ef972a140fc72eeeb2ed00e2e;hp=b7a0093ed0a2f0bcef43805dccb25cad4d01d4f3;hpb=fa45589d5736d2ce7f37ddd03daad2c638e38848;p=apps%2Fagl-service-can-low-level.git diff --git a/pb_decode.c b/pb_decode.c index b7a0093e..1fcc4e5a 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -24,7 +24,6 @@ typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); -static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); @@ -65,7 +64,8 @@ static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { &pb_dec_bytes, &pb_dec_string, &pb_dec_submessage, - NULL /* extensions */ + NULL, /* extensions */ + &pb_dec_bytes /* PB_LTYPE_FIXED_LENGTH_BYTES */ }; /******************************* @@ -74,13 +74,14 @@ static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { + size_t i; const pb_byte_t *source = (const pb_byte_t*)stream->state; stream->state = (pb_byte_t*)stream->state + count; if (buf != NULL) { - while (count--) - *buf++ = *source++; + for (i = 0; i < count; i++) + buf[i] = source[i]; } return true; @@ -168,7 +169,7 @@ pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) * Helper functions * ********************/ -static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) { pb_byte_t byte; uint32_t result; @@ -359,7 +360,8 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t return func(stream, iter->pos, iter->pData); case PB_HTYPE_OPTIONAL: - *(bool*)iter->pSize = true; + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; return func(stream, iter->pos, iter->pData); case PB_HTYPE_REPEATED: @@ -1035,6 +1037,12 @@ static void pb_release_single_field(const pb_field_iter_t *iter) if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { count = *(pb_size_t*)iter->pSize; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + { + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } } if (pItem) @@ -1155,19 +1163,22 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *fi * not break decoding of such messages, we cast <=32 bit fields to * int32_t first to get the sign correct. */ - if (field->data_size == 8) + if (field->data_size == sizeof(int64_t)) svalue = (int64_t)value; else svalue = (int32_t)value; - switch (field->data_size) - { - case 1: clamped = *(int8_t*)dest = (int8_t)svalue; break; - case 2: clamped = *(int16_t*)dest = (int16_t)svalue; break; - case 4: clamped = *(int32_t*)dest = (int32_t)svalue; break; - case 8: clamped = *(int64_t*)dest = svalue; break; - default: PB_RETURN_ERROR(stream, "invalid data_size"); - } + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(int64_t)) + clamped = *(int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); if (clamped != svalue) PB_RETURN_ERROR(stream, "integer too large"); @@ -1181,14 +1192,17 @@ static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *f if (!pb_decode_varint(stream, &value)) return false; - switch (field->data_size) - { - case 1: clamped = *(uint_least8_t*)dest = (uint_least8_t)value; break; - case 2: clamped = *(uint_least16_t*)dest = (uint_least16_t)value; break; - case 4: clamped = *(uint32_t*)dest = (uint32_t)value; break; - case 8: clamped = *(uint64_t*)dest = value; break; - default: PB_RETURN_ERROR(stream, "invalid data_size"); - } + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(uint64_t)) + clamped = *(uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); if (clamped != value) PB_RETURN_ERROR(stream, "integer too large"); @@ -1202,14 +1216,17 @@ static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *f if (!pb_decode_svarint(stream, &value)) return false; - switch (field->data_size) - { - case 1: clamped = *(int_least8_t*)dest = (int_least8_t)value; break; - case 2: clamped = *(int_least16_t*)dest = (int_least16_t)value; break; - case 4: clamped = *(int32_t*)dest = (int32_t)value; break; - case 8: clamped = *(int64_t*)dest = value; break; - default: PB_RETURN_ERROR(stream, "invalid data_size"); - } + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(int64_t)) + clamped = *(int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); if (clamped != value) PB_RETURN_ERROR(stream, "integer too large"); @@ -1257,6 +1274,12 @@ static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *fie } else { + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED_LENGTH_BYTES) { + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect inline bytes size"); + return pb_read(stream, (pb_byte_t*)dest, field->data_size); + } + if (alloc_size > field->data_size) PB_RETURN_ERROR(stream, "bytes overflow"); bdest = (pb_bytes_array_t*)dest;