&pb_dec_bytes,
&pb_dec_string,
&pb_dec_submessage,
- NULL /* extensions */
+ NULL, /* extensions */
+ &pb_dec_bytes /* PB_LTYPE_FIXED_LENGTH_BYTES */
};
/*******************************
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:
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)
* 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");
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");
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");
}
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;