Update to nanopb 0.4.4

This commit is contained in:
Kevin Hester
2020-12-11 08:31:41 +08:00
parent 091e953ed4
commit c361c1fab7
9 changed files with 556 additions and 460 deletions

View File

@@ -24,19 +24,17 @@
static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
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 check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field);
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter);
static bool checkreturn find_extension_field(pb_field_iter_t *iter);
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension);
static bool pb_field_set_to_default(pb_field_iter_t *field);
static bool pb_message_set_to_defaults(pb_field_iter_t *iter);
static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field);
@@ -59,6 +57,8 @@ static void pb_release_single_field(pb_field_iter_t *field);
#define pb_uint64_t uint64_t
#endif
#define PB_WT_PACKED ((pb_wire_type_t)0xFF)
typedef struct {
uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32];
} pb_fields_seen_t;
@@ -139,7 +139,7 @@ static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
return true;
}
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen)
{
pb_istream_t stream;
/* Cast away the const from buf without a compiler error. We are
@@ -156,7 +156,7 @@ pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
#endif
state.c_state = buf;
stream.state = state.state;
stream.bytes_left = bufsize;
stream.bytes_left = msglen;
#ifndef PB_NO_ERRMSG
stream.errmsg = NULL;
#endif
@@ -205,8 +205,10 @@ static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *d
{
/* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension))
bool valid_extension = ((byte & 0x7F) == 0x00 ||
((result >> 31) != 0 && byte == sign_extension));
if (bitpos >= 64 || !valid_extension)
{
PB_RETURN_ERROR(stream, "varint overflow");
}
@@ -388,61 +390,70 @@ bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *s
* Decode a single field *
*************************/
static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field)
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
{
switch (PB_LTYPE(field->type))
{
case PB_LTYPE_BOOL:
case PB_LTYPE_VARINT:
case PB_LTYPE_UVARINT:
case PB_LTYPE_SVARINT:
return wire_type == PB_WT_VARINT;
if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
PB_RETURN_ERROR(stream, "wrong wire type");
case PB_LTYPE_FIXED32:
return wire_type == PB_WT_32BIT;
case PB_LTYPE_FIXED64:
return wire_type == PB_WT_64BIT;
case PB_LTYPE_BYTES:
case PB_LTYPE_STRING:
case PB_LTYPE_SUBMESSAGE:
case PB_LTYPE_SUBMSG_W_CB:
case PB_LTYPE_FIXED_LENGTH_BYTES:
return wire_type == PB_WT_STRING;
default:
return false;
}
}
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field)
{
switch (PB_LTYPE(field->type))
{
case PB_LTYPE_BOOL:
return pb_dec_bool(stream, field);
case PB_LTYPE_VARINT:
case PB_LTYPE_UVARINT:
case PB_LTYPE_SVARINT:
if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_dec_varint(stream, field);
case PB_LTYPE_FIXED32:
if (wire_type != PB_WT_32BIT && wire_type != PB_WT_PACKED)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_decode_fixed32(stream, field->pData);
case PB_LTYPE_FIXED64:
return pb_dec_fixed(stream, field);
if (wire_type != PB_WT_64BIT && wire_type != PB_WT_PACKED)
PB_RETURN_ERROR(stream, "wrong wire type");
#ifdef PB_CONVERT_DOUBLE_FLOAT
if (field->data_size == sizeof(float))
{
return pb_decode_double_as_float(stream, (float*)field->pData);
}
#endif
#ifdef PB_WITHOUT_64BIT
PB_RETURN_ERROR(stream, "invalid data_size");
#else
return pb_decode_fixed64(stream, field->pData);
#endif
case PB_LTYPE_BYTES:
if (wire_type != PB_WT_STRING)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_dec_bytes(stream, field);
case PB_LTYPE_STRING:
if (wire_type != PB_WT_STRING)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_dec_string(stream, field);
case PB_LTYPE_SUBMESSAGE:
case PB_LTYPE_SUBMSG_W_CB:
if (wire_type != PB_WT_STRING)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_dec_submessage(stream, field);
case PB_LTYPE_FIXED_LENGTH_BYTES:
if (wire_type != PB_WT_STRING)
PB_RETURN_ERROR(stream, "wrong wire type");
return pb_dec_fixed_length_bytes(stream, field);
default:
@@ -455,18 +466,12 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
switch (PB_HTYPE(field->type))
{
case PB_HTYPE_REQUIRED:
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
case PB_HTYPE_OPTIONAL:
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
if (field->pSize != NULL)
*(bool*)field->pSize = true;
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
case PB_HTYPE_REPEATED:
if (wire_type == PB_WT_STRING
@@ -483,7 +488,7 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
while (substream.bytes_left > 0 && *size < field->array_size)
{
if (!decode_basic_field(&substream, field))
if (!decode_basic_field(&substream, PB_WT_PACKED, field))
{
status = false;
break;
@@ -505,18 +510,15 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
pb_size_t *size = (pb_size_t*)field->pSize;
field->pData = (char*)field->pField + field->data_size * (*size);
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
if ((*size)++ >= field->array_size)
PB_RETURN_ERROR(stream, "array overflow");
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
}
case PB_HTYPE_ONEOF:
*(pb_size_t*)field->pSize = field->tag;
if (PB_LTYPE_IS_SUBMSG(field->type))
if (PB_LTYPE_IS_SUBMSG(field->type) &&
*(pb_size_t*)field->pSize != field->tag)
{
/* We memset to zero so that any callbacks are set to NULL.
* This is because the callbacks might otherwise have values
@@ -526,12 +528,14 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
* that can set the fields before submessage is decoded.
* pb_dec_submessage() will set any default values. */
memset(field->pData, 0, (size_t)field->data_size);
/* Set default values for the submessage fields. */
if (!pb_field_set_to_default(field))
PB_RETURN_ERROR(stream, "failed to set defaults");
}
*(pb_size_t*)field->pSize = field->tag;
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
default:
PB_RETURN_ERROR(stream, "invalid field type");
@@ -599,14 +603,8 @@ static void initialize_pointer_field(void *pItem, pb_field_iter_t *field)
else if (PB_LTYPE_IS_SUBMSG(field->type))
{
/* We memset to zero so that any callbacks are set to NULL.
* Then set any default values. */
pb_field_iter_t submsg_iter;
* Default values will be set by pb_dec_submessage(). */
memset(pItem, 0, field->data_size);
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, pItem))
{
(void)pb_message_set_to_defaults(&submsg_iter);
}
}
}
#endif
@@ -623,9 +621,6 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
case PB_HTYPE_REQUIRED:
case PB_HTYPE_OPTIONAL:
case PB_HTYPE_ONEOF:
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL)
{
/* Duplicate field, have to release the old allocation first. */
@@ -643,7 +638,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
{
/* pb_dec_string and pb_dec_bytes handle allocation themselves */
field->pData = field->pField;
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
}
else
{
@@ -652,7 +647,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
field->pData = *(void**)field->pField;
initialize_pointer_field(field->pData, field);
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
}
case PB_HTYPE_REPEATED:
@@ -700,7 +695,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
/* Decode the array entry */
field->pData = *(char**)field->pField + field->data_size * (*size);
initialize_pointer_field(field->pData, field);
if (!decode_basic_field(&substream, field))
if (!decode_basic_field(&substream, PB_WT_PACKED, field))
{
status = false;
break;
@@ -721,16 +716,13 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
if (*size == PB_SIZE_MAX)
PB_RETURN_ERROR(stream, "too many array entries");
if (!check_wire_type(wire_type, field))
PB_RETURN_ERROR(stream, "wrong wire type");
if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1)))
return false;
field->pData = *(char**)field->pField + field->data_size * (*size);
(*size)++;
initialize_pointer_field(field->pData, field);
return decode_basic_field(stream, field);
return decode_basic_field(stream, wire_type, field);
}
default:
@@ -821,7 +813,7 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
if (!pb_field_iter_begin_extension(&iter, extension))
PB_RETURN_ERROR(stream, "invalid extension");
if (iter.tag != tag)
if (iter.tag != tag || !iter.message)
return true;
extension->found = true;
@@ -831,9 +823,8 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
/* Try to decode an unknown field as an extension field. Tries each extension
* decoder in turn, until one of them handles the field or loop ends. */
static bool checkreturn decode_extension(pb_istream_t *stream,
uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter)
uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension)
{
pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
size_t pos = stream->bytes_left;
while (extension != NULL && pos == stream->bytes_left)
@@ -853,22 +844,6 @@ static bool checkreturn decode_extension(pb_istream_t *stream,
return true;
}
/* Step through the iterator until an extension field is found or until all
* entries have been checked. There can be only one extension field per
* message. Returns false if no extension field is found. */
static bool checkreturn find_extension_field(pb_field_iter_t *iter)
{
pb_size_t start = iter->index;
do {
if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
return true;
(void)pb_field_iter_next(iter);
} while (iter->index != start);
return false;
}
/* Initialize message fields to default values, recursively */
static bool pb_field_set_to_default(pb_field_iter_t *field)
{
@@ -910,9 +885,14 @@ static bool pb_field_set_to_default(pb_field_iter_t *field)
if (init_data)
{
if (PB_LTYPE_IS_SUBMSG(field->type))
if (PB_LTYPE_IS_SUBMSG(field->type) &&
(field->submsg_desc->default_value != NULL ||
field->submsg_desc->field_callback != NULL ||
field->submsg_desc->submsg_info[0] != NULL))
{
/* Initialize submessage to defaults */
/* Initialize submessage to defaults.
* Only needed if it has default values
* or callback/submessage fields. */
pb_field_iter_t submsg_iter;
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
{
@@ -989,6 +969,7 @@ static bool pb_message_set_to_defaults(pb_field_iter_t *iter)
static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags)
{
uint32_t extension_range_start = 0;
pb_extension_t *extensions = NULL;
/* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed
* count field. This can only handle _one_ repeated fixed count field that
@@ -1040,25 +1021,31 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t
if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
{
/* No match found, check if it matches an extension. */
if (extension_range_start == 0)
{
if (pb_field_iter_find_extension(&iter))
{
extensions = *(pb_extension_t* const *)iter.pData;
extension_range_start = iter.tag;
}
if (!extensions)
{
extension_range_start = (uint32_t)-1;
}
}
if (tag >= extension_range_start)
{
if (!find_extension_field(&iter))
extension_range_start = (uint32_t)-1;
else
extension_range_start = iter.tag;
size_t pos = stream->bytes_left;
if (tag >= extension_range_start)
if (!decode_extension(stream, tag, wire_type, extensions))
return false;
if (pos != stream->bytes_left)
{
size_t pos = stream->bytes_left;
if (!decode_extension(stream, tag, wire_type, &iter))
return false;
if (pos != stream->bytes_left)
{
/* The field was handled */
continue;
}
/* The field was handled */
continue;
}
}
@@ -1112,27 +1099,15 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t
/* Check that all required fields were present. */
{
/* First figure out the number of required fields by
* seeking to the end of the field array. Usually we
* are already close to end after decoding.
*/
pb_size_t req_field_count;
pb_type_t last_type;
pb_size_t i;
do {
req_field_count = iter.required_field_index;
last_type = iter.type;
} while (pb_field_iter_next(&iter));
/* Fixup if last field was also required. */
if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.tag != 0)
req_field_count++;
if (req_field_count > PB_MAX_REQUIRED_FIELDS)
req_field_count = PB_MAX_REQUIRED_FIELDS;
pb_size_t req_field_count = iter.descriptor->required_field_count;
if (req_field_count > 0)
{
pb_size_t i;
if (req_field_count > PB_MAX_REQUIRED_FIELDS)
req_field_count = PB_MAX_REQUIRED_FIELDS;
/* Check the whole words */
for (i = 0; i < (req_field_count >> 5); i++)
{
@@ -1277,7 +1252,7 @@ static void pb_release_single_field(pb_field_iter_t *field)
if (field->pData)
{
while (count--)
for (; count > 0; count--)
{
pb_release(field->submsg_desc, field->pData);
field->pData = (char*)field->pData + field->data_size;
@@ -1294,7 +1269,7 @@ static void pb_release_single_field(pb_field_iter_t *field)
/* Release entries in repeated string or bytes array */
void **pItem = *(void***)field->pField;
pb_size_t count = *(pb_size_t*)field->pSize;
while (count--)
for (; count > 0; count--)
{
pb_free(*pItem);
*pItem++ = NULL;
@@ -1454,7 +1429,7 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_
/* See issue 97: Google's C++ protobuf allows negative varint values to
* be cast as int32_t, instead of the int64_t that should be used when
* encoding. Previous nanopb versions had a bug in encoding. In order to
* encoding. Nanopb versions before 0.2.5 had a bug in encoding. In order to
* not break decoding of such messages, we cast <=32 bit fields to
* int32_t first to get the sign correct.
*/
@@ -1483,31 +1458,6 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_
}
}
static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field)
{
#ifdef PB_CONVERT_DOUBLE_FLOAT
if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
{
return pb_decode_double_as_float(stream, (float*)field->pData);
}
#endif
if (field->data_size == sizeof(uint32_t))
{
return pb_decode_fixed32(stream, field->pData);
}
#ifndef PB_WITHOUT_64BIT
else if (field->data_size == sizeof(uint64_t))
{
return pb_decode_fixed64(stream, field->pData);
}
#endif
else
{
PB_RETURN_ERROR(stream, "invalid data_size");
}
}
static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field)
{
uint32_t size;
@@ -1601,6 +1551,7 @@ static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field)
{
bool status = true;
bool submsg_consumed = false;
pb_istream_t substream;
if (!pb_make_string_substream(stream, &substream))
@@ -1609,19 +1560,6 @@ static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_i
if (field->submsg_desc == NULL)
PB_RETURN_ERROR(stream, "invalid field descriptor");
/* New array entries need to be initialized, while required and optional
* submessages have already been initialized in the top-level pb_decode. */
if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED ||
PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
{
pb_field_iter_t submsg_iter;
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
{
if (!pb_message_set_to_defaults(&submsg_iter))
PB_RETURN_ERROR(stream, "failed to set defaults");
}
}
/* Submessages can have a separate message-level callback that is called
* before decoding the message. Typically it is used to set callback fields
* inside oneofs. */
@@ -1632,13 +1570,28 @@ static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_i
if (callback->funcs.decode)
{
status = callback->funcs.decode(&substream, field, &callback->arg);
if (substream.bytes_left == 0)
{
submsg_consumed = true;
}
}
}
/* Now decode the submessage contents */
if (status)
if (status && !submsg_consumed)
{
status = pb_decode_inner(&substream, field->submsg_desc, field->pData, 0);
unsigned int flags = 0;
/* Static required/optional fields are already initialized by top-level
* pb_decode(), no need to initialize them again. */
if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
PB_HTYPE(field->type) != PB_HTYPE_REPEATED)
{
flags = PB_DECODE_NOINIT;
}
status = pb_decode_inner(&substream, field->submsg_desc, field->pData, flags);
}
if (!pb_close_string_substream(stream, &substream))
@@ -1692,37 +1645,41 @@ bool pb_decode_double_as_float(pb_istream_t *stream, float *dest)
{
/* Special value */
exponent = 128;
}
else if (exponent > 127)
{
/* Too large, convert to infinity */
exponent = 128;
mantissa = 0;
}
else if (exponent < -150)
{
/* Too small, convert to zero */
exponent = -127;
mantissa = 0;
}
else if (exponent < -126)
{
/* Denormalized */
mantissa |= 0x1000000;
mantissa >>= (-126 - exponent);
exponent = -127;
}
/* Round off mantissa */
mantissa = (mantissa + 1) >> 1;
/* Check if mantissa went over 2.0 */
if (mantissa & 0x800000)
{
exponent += 1;
mantissa &= 0x7FFFFF;
mantissa >>= 1;
}
else
{
if (exponent > 127)
{
/* Too large, convert to infinity */
exponent = 128;
mantissa = 0;
}
else if (exponent < -150)
{
/* Too small, convert to zero */
exponent = -127;
mantissa = 0;
}
else if (exponent < -126)
{
/* Denormalized */
mantissa |= 0x1000000;
mantissa >>= (-126 - exponent);
exponent = -127;
}
/* Round off mantissa */
mantissa = (mantissa + 1) >> 1;
/* Check if mantissa went over 2.0 */
if (mantissa & 0x800000)
{
exponent += 1;
mantissa &= 0x7FFFFF;
mantissa >>= 1;
}
}
/* Combine fields */
out.i = mantissa;