Nanopb files

Dependents:   nanopb_V2 Message_generator LEX_Threaded_Programming_V3

Committer:
omatthews
Date:
Mon Aug 19 15:23:39 2019 +0000
Revision:
3:67ee10c4ae98
Parent:
2:d2c61a9be078
It works

Who changed what in which revision?

UserRevisionLine numberNew contents of line
intrinseca 0:c7beea49fc91 1 /* pb_decode.c -- decode a protobuf using minimal resources
intrinseca 0:c7beea49fc91 2 *
intrinseca 0:c7beea49fc91 3 * 2011 Petteri Aimonen <jpa@kapsi.fi>
intrinseca 0:c7beea49fc91 4 */
intrinseca 0:c7beea49fc91 5
omatthews 2:d2c61a9be078 6 /* Use the GCC warn_unused_result attribute to check that all return values
omatthews 2:d2c61a9be078 7 * are propagated correctly. On other compilers and gcc before 3.4.0 just
omatthews 2:d2c61a9be078 8 * ignore the annotation.
omatthews 2:d2c61a9be078 9 */
intrinseca 0:c7beea49fc91 10 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
intrinseca 0:c7beea49fc91 11 #define checkreturn
intrinseca 0:c7beea49fc91 12 #else
intrinseca 0:c7beea49fc91 13 #define checkreturn __attribute__((warn_unused_result))
intrinseca 0:c7beea49fc91 14 #endif
intrinseca 0:c7beea49fc91 15
intrinseca 0:c7beea49fc91 16 #include "pb.h"
intrinseca 0:c7beea49fc91 17 #include "pb_decode.h"
omatthews 2:d2c61a9be078 18 #include "pb_common.h"
omatthews 2:d2c61a9be078 19
omatthews 2:d2c61a9be078 20 /**************************************
omatthews 2:d2c61a9be078 21 * Declarations internal to this file *
omatthews 2:d2c61a9be078 22 **************************************/
intrinseca 0:c7beea49fc91 23
intrinseca 0:c7beea49fc91 24 typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn;
intrinseca 0:c7beea49fc91 25
omatthews 2:d2c61a9be078 26 static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
omatthews 2:d2c61a9be078 27 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
omatthews 2:d2c61a9be078 28 static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 29 static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 30 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 31 static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension);
omatthews 2:d2c61a9be078 32 static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
omatthews 2:d2c61a9be078 33 static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 34 static bool checkreturn find_extension_field(pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 35 static void pb_field_set_to_default(pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 36 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct);
omatthews 2:d2c61a9be078 37 static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 38 static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
omatthews 2:d2c61a9be078 39 static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 40 static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 41 static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 42 static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 43 static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 44 static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 45 static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 46 static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
omatthews 2:d2c61a9be078 47 static bool checkreturn pb_skip_varint(pb_istream_t *stream);
omatthews 2:d2c61a9be078 48 static bool checkreturn pb_skip_string(pb_istream_t *stream);
omatthews 2:d2c61a9be078 49
omatthews 2:d2c61a9be078 50 #ifdef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 51 static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
omatthews 2:d2c61a9be078 52 static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 53 static void pb_release_single_field(const pb_field_iter_t *iter);
omatthews 2:d2c61a9be078 54 #endif
omatthews 2:d2c61a9be078 55
omatthews 2:d2c61a9be078 56 #ifdef PB_WITHOUT_64BIT
omatthews 2:d2c61a9be078 57 #define pb_int64_t int32_t
omatthews 2:d2c61a9be078 58 #define pb_uint64_t uint32_t
omatthews 2:d2c61a9be078 59 #else
omatthews 2:d2c61a9be078 60 #define pb_int64_t int64_t
omatthews 2:d2c61a9be078 61 #define pb_uint64_t uint64_t
omatthews 2:d2c61a9be078 62 #endif
omatthews 2:d2c61a9be078 63
intrinseca 0:c7beea49fc91 64 /* --- Function pointers to field decoders ---
intrinseca 0:c7beea49fc91 65 * Order in the array must match pb_action_t LTYPE numbering.
intrinseca 0:c7beea49fc91 66 */
intrinseca 0:c7beea49fc91 67 static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
intrinseca 0:c7beea49fc91 68 &pb_dec_varint,
omatthews 2:d2c61a9be078 69 &pb_dec_uvarint,
intrinseca 0:c7beea49fc91 70 &pb_dec_svarint,
intrinseca 0:c7beea49fc91 71 &pb_dec_fixed32,
intrinseca 0:c7beea49fc91 72 &pb_dec_fixed64,
intrinseca 0:c7beea49fc91 73
intrinseca 0:c7beea49fc91 74 &pb_dec_bytes,
intrinseca 0:c7beea49fc91 75 &pb_dec_string,
omatthews 2:d2c61a9be078 76 &pb_dec_submessage,
omatthews 2:d2c61a9be078 77 NULL, /* extensions */
omatthews 2:d2c61a9be078 78 &pb_dec_fixed_length_bytes
intrinseca 0:c7beea49fc91 79 };
intrinseca 0:c7beea49fc91 80
omatthews 2:d2c61a9be078 81 /*******************************
omatthews 2:d2c61a9be078 82 * pb_istream_t implementation *
omatthews 2:d2c61a9be078 83 *******************************/
intrinseca 0:c7beea49fc91 84
omatthews 2:d2c61a9be078 85 static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
intrinseca 0:c7beea49fc91 86 {
omatthews 2:d2c61a9be078 87 size_t i;
omatthews 2:d2c61a9be078 88 const pb_byte_t *source = (const pb_byte_t*)stream->state;
omatthews 2:d2c61a9be078 89 stream->state = (pb_byte_t*)stream->state + count;
intrinseca 0:c7beea49fc91 90
intrinseca 0:c7beea49fc91 91 if (buf != NULL)
intrinseca 0:c7beea49fc91 92 {
omatthews 2:d2c61a9be078 93 for (i = 0; i < count; i++)
omatthews 2:d2c61a9be078 94 buf[i] = source[i];
intrinseca 0:c7beea49fc91 95 }
intrinseca 0:c7beea49fc91 96
intrinseca 0:c7beea49fc91 97 return true;
intrinseca 0:c7beea49fc91 98 }
intrinseca 0:c7beea49fc91 99
omatthews 2:d2c61a9be078 100 bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
intrinseca 0:c7beea49fc91 101 {
intrinseca 0:c7beea49fc91 102 #ifndef PB_BUFFER_ONLY
intrinseca 0:c7beea49fc91 103 if (buf == NULL && stream->callback != buf_read)
intrinseca 0:c7beea49fc91 104 {
intrinseca 0:c7beea49fc91 105 /* Skip input bytes */
omatthews 2:d2c61a9be078 106 pb_byte_t tmp[16];
intrinseca 0:c7beea49fc91 107 while (count > 16)
intrinseca 0:c7beea49fc91 108 {
intrinseca 0:c7beea49fc91 109 if (!pb_read(stream, tmp, 16))
intrinseca 0:c7beea49fc91 110 return false;
intrinseca 0:c7beea49fc91 111
intrinseca 0:c7beea49fc91 112 count -= 16;
intrinseca 0:c7beea49fc91 113 }
intrinseca 0:c7beea49fc91 114
intrinseca 0:c7beea49fc91 115 return pb_read(stream, tmp, count);
intrinseca 0:c7beea49fc91 116 }
intrinseca 0:c7beea49fc91 117 #endif
intrinseca 0:c7beea49fc91 118
intrinseca 0:c7beea49fc91 119 if (stream->bytes_left < count)
intrinseca 0:c7beea49fc91 120 PB_RETURN_ERROR(stream, "end-of-stream");
intrinseca 0:c7beea49fc91 121
intrinseca 0:c7beea49fc91 122 #ifndef PB_BUFFER_ONLY
intrinseca 0:c7beea49fc91 123 if (!stream->callback(stream, buf, count))
intrinseca 0:c7beea49fc91 124 PB_RETURN_ERROR(stream, "io error");
intrinseca 0:c7beea49fc91 125 #else
intrinseca 0:c7beea49fc91 126 if (!buf_read(stream, buf, count))
intrinseca 0:c7beea49fc91 127 return false;
intrinseca 0:c7beea49fc91 128 #endif
intrinseca 0:c7beea49fc91 129
intrinseca 0:c7beea49fc91 130 stream->bytes_left -= count;
intrinseca 0:c7beea49fc91 131 return true;
intrinseca 0:c7beea49fc91 132 }
intrinseca 0:c7beea49fc91 133
omatthews 2:d2c61a9be078 134 /* Read a single byte from input stream. buf may not be NULL.
omatthews 2:d2c61a9be078 135 * This is an optimization for the varint decoding. */
omatthews 2:d2c61a9be078 136 static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
omatthews 2:d2c61a9be078 137 {
omatthews 2:d2c61a9be078 138 if (stream->bytes_left == 0)
omatthews 2:d2c61a9be078 139 PB_RETURN_ERROR(stream, "end-of-stream");
omatthews 2:d2c61a9be078 140
omatthews 2:d2c61a9be078 141 #ifndef PB_BUFFER_ONLY
omatthews 2:d2c61a9be078 142 if (!stream->callback(stream, buf, 1))
omatthews 2:d2c61a9be078 143 PB_RETURN_ERROR(stream, "io error");
omatthews 2:d2c61a9be078 144 #else
omatthews 2:d2c61a9be078 145 *buf = *(const pb_byte_t*)stream->state;
omatthews 2:d2c61a9be078 146 stream->state = (pb_byte_t*)stream->state + 1;
omatthews 2:d2c61a9be078 147 #endif
omatthews 2:d2c61a9be078 148
omatthews 2:d2c61a9be078 149 stream->bytes_left--;
omatthews 2:d2c61a9be078 150
omatthews 2:d2c61a9be078 151 return true;
omatthews 2:d2c61a9be078 152 }
omatthews 2:d2c61a9be078 153
omatthews 2:d2c61a9be078 154 pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
intrinseca 0:c7beea49fc91 155 {
intrinseca 0:c7beea49fc91 156 pb_istream_t stream;
omatthews 2:d2c61a9be078 157 /* Cast away the const from buf without a compiler error. We are
omatthews 2:d2c61a9be078 158 * careful to use it only in a const manner in the callbacks.
omatthews 2:d2c61a9be078 159 */
omatthews 2:d2c61a9be078 160 union {
omatthews 2:d2c61a9be078 161 void *state;
omatthews 2:d2c61a9be078 162 const void *c_state;
omatthews 2:d2c61a9be078 163 } state;
intrinseca 0:c7beea49fc91 164 #ifdef PB_BUFFER_ONLY
intrinseca 0:c7beea49fc91 165 stream.callback = NULL;
intrinseca 0:c7beea49fc91 166 #else
intrinseca 0:c7beea49fc91 167 stream.callback = &buf_read;
intrinseca 0:c7beea49fc91 168 #endif
omatthews 2:d2c61a9be078 169 state.c_state = buf;
omatthews 2:d2c61a9be078 170 stream.state = state.state;
intrinseca 0:c7beea49fc91 171 stream.bytes_left = bufsize;
intrinseca 0:c7beea49fc91 172 #ifndef PB_NO_ERRMSG
intrinseca 0:c7beea49fc91 173 stream.errmsg = NULL;
intrinseca 0:c7beea49fc91 174 #endif
intrinseca 0:c7beea49fc91 175 return stream;
intrinseca 0:c7beea49fc91 176 }
intrinseca 0:c7beea49fc91 177
intrinseca 0:c7beea49fc91 178 /********************
intrinseca 0:c7beea49fc91 179 * Helper functions *
intrinseca 0:c7beea49fc91 180 ********************/
intrinseca 0:c7beea49fc91 181
omatthews 2:d2c61a9be078 182 static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof)
intrinseca 0:c7beea49fc91 183 {
omatthews 2:d2c61a9be078 184 pb_byte_t byte;
intrinseca 0:c7beea49fc91 185 uint32_t result;
intrinseca 0:c7beea49fc91 186
omatthews 2:d2c61a9be078 187 if (!pb_readbyte(stream, &byte))
omatthews 2:d2c61a9be078 188 {
omatthews 2:d2c61a9be078 189 if (stream->bytes_left == 0)
omatthews 2:d2c61a9be078 190 {
omatthews 2:d2c61a9be078 191 if (eof)
omatthews 2:d2c61a9be078 192 {
omatthews 2:d2c61a9be078 193 *eof = true;
omatthews 2:d2c61a9be078 194 }
omatthews 2:d2c61a9be078 195 }
omatthews 2:d2c61a9be078 196
intrinseca 0:c7beea49fc91 197 return false;
omatthews 2:d2c61a9be078 198 }
intrinseca 0:c7beea49fc91 199
omatthews 2:d2c61a9be078 200 if ((byte & 0x80) == 0)
intrinseca 0:c7beea49fc91 201 {
intrinseca 0:c7beea49fc91 202 /* Quick case, 1 byte value */
intrinseca 0:c7beea49fc91 203 result = byte;
intrinseca 0:c7beea49fc91 204 }
intrinseca 0:c7beea49fc91 205 else
intrinseca 0:c7beea49fc91 206 {
intrinseca 0:c7beea49fc91 207 /* Multibyte case */
omatthews 2:d2c61a9be078 208 uint_fast8_t bitpos = 7;
intrinseca 0:c7beea49fc91 209 result = byte & 0x7F;
intrinseca 0:c7beea49fc91 210
intrinseca 0:c7beea49fc91 211 do
intrinseca 0:c7beea49fc91 212 {
omatthews 2:d2c61a9be078 213 if (!pb_readbyte(stream, &byte))
intrinseca 0:c7beea49fc91 214 return false;
intrinseca 0:c7beea49fc91 215
omatthews 2:d2c61a9be078 216 if (bitpos >= 32)
omatthews 2:d2c61a9be078 217 {
omatthews 2:d2c61a9be078 218 /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
omatthews 2:d2c61a9be078 219 uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
omatthews 2:d2c61a9be078 220
omatthews 2:d2c61a9be078 221 if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension))
omatthews 2:d2c61a9be078 222 {
omatthews 2:d2c61a9be078 223 PB_RETURN_ERROR(stream, "varint overflow");
omatthews 2:d2c61a9be078 224 }
omatthews 2:d2c61a9be078 225 }
omatthews 2:d2c61a9be078 226 else
omatthews 2:d2c61a9be078 227 {
omatthews 2:d2c61a9be078 228 result |= (uint32_t)(byte & 0x7F) << bitpos;
omatthews 2:d2c61a9be078 229 }
omatthews 2:d2c61a9be078 230 bitpos = (uint_fast8_t)(bitpos + 7);
intrinseca 0:c7beea49fc91 231 } while (byte & 0x80);
omatthews 2:d2c61a9be078 232
omatthews 2:d2c61a9be078 233 if (bitpos == 35 && (byte & 0x70) != 0)
omatthews 2:d2c61a9be078 234 {
omatthews 2:d2c61a9be078 235 /* The last byte was at bitpos=28, so only bottom 4 bits fit. */
omatthews 2:d2c61a9be078 236 PB_RETURN_ERROR(stream, "varint overflow");
omatthews 2:d2c61a9be078 237 }
intrinseca 0:c7beea49fc91 238 }
intrinseca 0:c7beea49fc91 239
intrinseca 0:c7beea49fc91 240 *dest = result;
intrinseca 0:c7beea49fc91 241 return true;
intrinseca 0:c7beea49fc91 242 }
intrinseca 0:c7beea49fc91 243
omatthews 2:d2c61a9be078 244 bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
omatthews 2:d2c61a9be078 245 {
omatthews 2:d2c61a9be078 246 return pb_decode_varint32_eof(stream, dest, NULL);
omatthews 2:d2c61a9be078 247 }
omatthews 2:d2c61a9be078 248
omatthews 2:d2c61a9be078 249 #ifndef PB_WITHOUT_64BIT
intrinseca 0:c7beea49fc91 250 bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
intrinseca 0:c7beea49fc91 251 {
omatthews 2:d2c61a9be078 252 pb_byte_t byte;
omatthews 2:d2c61a9be078 253 uint_fast8_t bitpos = 0;
intrinseca 0:c7beea49fc91 254 uint64_t result = 0;
intrinseca 0:c7beea49fc91 255
intrinseca 0:c7beea49fc91 256 do
intrinseca 0:c7beea49fc91 257 {
intrinseca 0:c7beea49fc91 258 if (bitpos >= 64)
intrinseca 0:c7beea49fc91 259 PB_RETURN_ERROR(stream, "varint overflow");
intrinseca 0:c7beea49fc91 260
omatthews 2:d2c61a9be078 261 if (!pb_readbyte(stream, &byte))
intrinseca 0:c7beea49fc91 262 return false;
intrinseca 0:c7beea49fc91 263
intrinseca 0:c7beea49fc91 264 result |= (uint64_t)(byte & 0x7F) << bitpos;
omatthews 2:d2c61a9be078 265 bitpos = (uint_fast8_t)(bitpos + 7);
intrinseca 0:c7beea49fc91 266 } while (byte & 0x80);
intrinseca 0:c7beea49fc91 267
intrinseca 0:c7beea49fc91 268 *dest = result;
intrinseca 0:c7beea49fc91 269 return true;
intrinseca 0:c7beea49fc91 270 }
omatthews 2:d2c61a9be078 271 #endif
intrinseca 0:c7beea49fc91 272
intrinseca 0:c7beea49fc91 273 bool checkreturn pb_skip_varint(pb_istream_t *stream)
intrinseca 0:c7beea49fc91 274 {
omatthews 2:d2c61a9be078 275 pb_byte_t byte;
intrinseca 0:c7beea49fc91 276 do
intrinseca 0:c7beea49fc91 277 {
intrinseca 0:c7beea49fc91 278 if (!pb_read(stream, &byte, 1))
intrinseca 0:c7beea49fc91 279 return false;
intrinseca 0:c7beea49fc91 280 } while (byte & 0x80);
intrinseca 0:c7beea49fc91 281 return true;
intrinseca 0:c7beea49fc91 282 }
intrinseca 0:c7beea49fc91 283
intrinseca 0:c7beea49fc91 284 bool checkreturn pb_skip_string(pb_istream_t *stream)
intrinseca 0:c7beea49fc91 285 {
intrinseca 0:c7beea49fc91 286 uint32_t length;
intrinseca 0:c7beea49fc91 287 if (!pb_decode_varint32(stream, &length))
intrinseca 0:c7beea49fc91 288 return false;
intrinseca 0:c7beea49fc91 289
intrinseca 0:c7beea49fc91 290 return pb_read(stream, NULL, length);
intrinseca 0:c7beea49fc91 291 }
intrinseca 0:c7beea49fc91 292
intrinseca 0:c7beea49fc91 293 bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
intrinseca 0:c7beea49fc91 294 {
intrinseca 0:c7beea49fc91 295 uint32_t temp;
intrinseca 0:c7beea49fc91 296 *eof = false;
intrinseca 0:c7beea49fc91 297 *wire_type = (pb_wire_type_t) 0;
intrinseca 0:c7beea49fc91 298 *tag = 0;
intrinseca 0:c7beea49fc91 299
omatthews 2:d2c61a9be078 300 if (!pb_decode_varint32_eof(stream, &temp, eof))
intrinseca 0:c7beea49fc91 301 {
intrinseca 0:c7beea49fc91 302 return false;
intrinseca 0:c7beea49fc91 303 }
intrinseca 0:c7beea49fc91 304
intrinseca 0:c7beea49fc91 305 if (temp == 0)
intrinseca 0:c7beea49fc91 306 {
intrinseca 0:c7beea49fc91 307 *eof = true; /* Special feature: allow 0-terminated messages. */
intrinseca 0:c7beea49fc91 308 return false;
intrinseca 0:c7beea49fc91 309 }
intrinseca 0:c7beea49fc91 310
intrinseca 0:c7beea49fc91 311 *tag = temp >> 3;
intrinseca 0:c7beea49fc91 312 *wire_type = (pb_wire_type_t)(temp & 7);
intrinseca 0:c7beea49fc91 313 return true;
intrinseca 0:c7beea49fc91 314 }
intrinseca 0:c7beea49fc91 315
intrinseca 0:c7beea49fc91 316 bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
intrinseca 0:c7beea49fc91 317 {
intrinseca 0:c7beea49fc91 318 switch (wire_type)
intrinseca 0:c7beea49fc91 319 {
intrinseca 0:c7beea49fc91 320 case PB_WT_VARINT: return pb_skip_varint(stream);
intrinseca 0:c7beea49fc91 321 case PB_WT_64BIT: return pb_read(stream, NULL, 8);
intrinseca 0:c7beea49fc91 322 case PB_WT_STRING: return pb_skip_string(stream);
intrinseca 0:c7beea49fc91 323 case PB_WT_32BIT: return pb_read(stream, NULL, 4);
intrinseca 0:c7beea49fc91 324 default: PB_RETURN_ERROR(stream, "invalid wire_type");
intrinseca 0:c7beea49fc91 325 }
intrinseca 0:c7beea49fc91 326 }
intrinseca 0:c7beea49fc91 327
intrinseca 0:c7beea49fc91 328 /* Read a raw value to buffer, for the purpose of passing it to callback as
intrinseca 0:c7beea49fc91 329 * a substream. Size is maximum size on call, and actual size on return.
intrinseca 0:c7beea49fc91 330 */
omatthews 2:d2c61a9be078 331 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size)
intrinseca 0:c7beea49fc91 332 {
intrinseca 0:c7beea49fc91 333 size_t max_size = *size;
intrinseca 0:c7beea49fc91 334 switch (wire_type)
intrinseca 0:c7beea49fc91 335 {
intrinseca 0:c7beea49fc91 336 case PB_WT_VARINT:
intrinseca 0:c7beea49fc91 337 *size = 0;
intrinseca 0:c7beea49fc91 338 do
intrinseca 0:c7beea49fc91 339 {
intrinseca 0:c7beea49fc91 340 (*size)++;
intrinseca 0:c7beea49fc91 341 if (*size > max_size) return false;
intrinseca 0:c7beea49fc91 342 if (!pb_read(stream, buf, 1)) return false;
intrinseca 0:c7beea49fc91 343 } while (*buf++ & 0x80);
intrinseca 0:c7beea49fc91 344 return true;
intrinseca 0:c7beea49fc91 345
intrinseca 0:c7beea49fc91 346 case PB_WT_64BIT:
intrinseca 0:c7beea49fc91 347 *size = 8;
intrinseca 0:c7beea49fc91 348 return pb_read(stream, buf, 8);
intrinseca 0:c7beea49fc91 349
intrinseca 0:c7beea49fc91 350 case PB_WT_32BIT:
intrinseca 0:c7beea49fc91 351 *size = 4;
intrinseca 0:c7beea49fc91 352 return pb_read(stream, buf, 4);
intrinseca 0:c7beea49fc91 353
omatthews 2:d2c61a9be078 354 case PB_WT_STRING:
omatthews 2:d2c61a9be078 355 /* Calling read_raw_value with a PB_WT_STRING is an error.
omatthews 2:d2c61a9be078 356 * Explicitly handle this case and fallthrough to default to avoid
omatthews 2:d2c61a9be078 357 * compiler warnings.
omatthews 2:d2c61a9be078 358 */
omatthews 2:d2c61a9be078 359
intrinseca 0:c7beea49fc91 360 default: PB_RETURN_ERROR(stream, "invalid wire_type");
intrinseca 0:c7beea49fc91 361 }
intrinseca 0:c7beea49fc91 362 }
intrinseca 0:c7beea49fc91 363
intrinseca 0:c7beea49fc91 364 /* Decode string length from stream and return a substream with limited length.
intrinseca 0:c7beea49fc91 365 * Remember to close the substream using pb_close_string_substream().
intrinseca 0:c7beea49fc91 366 */
intrinseca 0:c7beea49fc91 367 bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
intrinseca 0:c7beea49fc91 368 {
intrinseca 0:c7beea49fc91 369 uint32_t size;
intrinseca 0:c7beea49fc91 370 if (!pb_decode_varint32(stream, &size))
intrinseca 0:c7beea49fc91 371 return false;
intrinseca 0:c7beea49fc91 372
intrinseca 0:c7beea49fc91 373 *substream = *stream;
intrinseca 0:c7beea49fc91 374 if (substream->bytes_left < size)
intrinseca 0:c7beea49fc91 375 PB_RETURN_ERROR(stream, "parent stream too short");
intrinseca 0:c7beea49fc91 376
intrinseca 0:c7beea49fc91 377 substream->bytes_left = size;
intrinseca 0:c7beea49fc91 378 stream->bytes_left -= size;
intrinseca 0:c7beea49fc91 379 return true;
intrinseca 0:c7beea49fc91 380 }
intrinseca 0:c7beea49fc91 381
omatthews 2:d2c61a9be078 382 bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream)
intrinseca 0:c7beea49fc91 383 {
omatthews 2:d2c61a9be078 384 if (substream->bytes_left) {
omatthews 2:d2c61a9be078 385 if (!pb_read(substream, NULL, substream->bytes_left))
omatthews 2:d2c61a9be078 386 return false;
omatthews 2:d2c61a9be078 387 }
omatthews 2:d2c61a9be078 388
intrinseca 0:c7beea49fc91 389 stream->state = substream->state;
intrinseca 0:c7beea49fc91 390
intrinseca 0:c7beea49fc91 391 #ifndef PB_NO_ERRMSG
intrinseca 0:c7beea49fc91 392 stream->errmsg = substream->errmsg;
intrinseca 0:c7beea49fc91 393 #endif
omatthews 2:d2c61a9be078 394 return true;
intrinseca 0:c7beea49fc91 395 }
intrinseca 0:c7beea49fc91 396
intrinseca 0:c7beea49fc91 397 /*************************
intrinseca 0:c7beea49fc91 398 * Decode a single field *
intrinseca 0:c7beea49fc91 399 *************************/
intrinseca 0:c7beea49fc91 400
omatthews 2:d2c61a9be078 401 static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
intrinseca 0:c7beea49fc91 402 {
omatthews 2:d2c61a9be078 403 pb_type_t type;
omatthews 2:d2c61a9be078 404 pb_decoder_t func;
intrinseca 0:c7beea49fc91 405
omatthews 2:d2c61a9be078 406 type = iter->pos->type;
omatthews 2:d2c61a9be078 407 func = PB_DECODERS[PB_LTYPE(type)];
omatthews 2:d2c61a9be078 408
omatthews 2:d2c61a9be078 409 switch (PB_HTYPE(type))
intrinseca 0:c7beea49fc91 410 {
intrinseca 0:c7beea49fc91 411 case PB_HTYPE_REQUIRED:
omatthews 2:d2c61a9be078 412 return func(stream, iter->pos, iter->pData);
intrinseca 0:c7beea49fc91 413
intrinseca 0:c7beea49fc91 414 case PB_HTYPE_OPTIONAL:
omatthews 2:d2c61a9be078 415 if (iter->pSize != iter->pData)
omatthews 2:d2c61a9be078 416 *(bool*)iter->pSize = true;
omatthews 2:d2c61a9be078 417 return func(stream, iter->pos, iter->pData);
intrinseca 0:c7beea49fc91 418
omatthews 2:d2c61a9be078 419 case PB_HTYPE_REPEATED:
intrinseca 0:c7beea49fc91 420 if (wire_type == PB_WT_STRING
omatthews 2:d2c61a9be078 421 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
intrinseca 0:c7beea49fc91 422 {
intrinseca 0:c7beea49fc91 423 /* Packed array */
intrinseca 0:c7beea49fc91 424 bool status = true;
omatthews 2:d2c61a9be078 425 pb_size_t *size = (pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 426
intrinseca 0:c7beea49fc91 427 pb_istream_t substream;
intrinseca 0:c7beea49fc91 428 if (!pb_make_string_substream(stream, &substream))
intrinseca 0:c7beea49fc91 429 return false;
omatthews 2:d2c61a9be078 430
omatthews 2:d2c61a9be078 431 while (substream.bytes_left > 0 && *size < iter->pos->array_size)
intrinseca 0:c7beea49fc91 432 {
omatthews 2:d2c61a9be078 433 void *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
omatthews 2:d2c61a9be078 434 if (!func(&substream, iter->pos, pItem))
intrinseca 0:c7beea49fc91 435 {
intrinseca 0:c7beea49fc91 436 status = false;
intrinseca 0:c7beea49fc91 437 break;
intrinseca 0:c7beea49fc91 438 }
intrinseca 0:c7beea49fc91 439 (*size)++;
intrinseca 0:c7beea49fc91 440 }
omatthews 2:d2c61a9be078 441
intrinseca 0:c7beea49fc91 442 if (substream.bytes_left != 0)
intrinseca 0:c7beea49fc91 443 PB_RETURN_ERROR(stream, "array overflow");
omatthews 2:d2c61a9be078 444 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 445 return false;
omatthews 2:d2c61a9be078 446
intrinseca 0:c7beea49fc91 447 return status;
intrinseca 0:c7beea49fc91 448 }
intrinseca 0:c7beea49fc91 449 else
intrinseca 0:c7beea49fc91 450 {
intrinseca 0:c7beea49fc91 451 /* Repeated field */
omatthews 2:d2c61a9be078 452 pb_size_t *size = (pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 453 char *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
omatthews 2:d2c61a9be078 454
omatthews 2:d2c61a9be078 455 if ((*size)++ >= iter->pos->array_size)
intrinseca 0:c7beea49fc91 456 PB_RETURN_ERROR(stream, "array overflow");
omatthews 2:d2c61a9be078 457
omatthews 2:d2c61a9be078 458 return func(stream, iter->pos, pItem);
omatthews 2:d2c61a9be078 459 }
omatthews 2:d2c61a9be078 460
omatthews 2:d2c61a9be078 461 case PB_HTYPE_ONEOF:
omatthews 2:d2c61a9be078 462 *(pb_size_t*)iter->pSize = iter->pos->tag;
omatthews 2:d2c61a9be078 463 if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
omatthews 2:d2c61a9be078 464 {
omatthews 2:d2c61a9be078 465 /* We memset to zero so that any callbacks are set to NULL.
omatthews 2:d2c61a9be078 466 * Then set any default values. */
omatthews 2:d2c61a9be078 467 memset(iter->pData, 0, iter->pos->data_size);
omatthews 2:d2c61a9be078 468 pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData);
omatthews 2:d2c61a9be078 469 }
omatthews 2:d2c61a9be078 470 return func(stream, iter->pos, iter->pData);
omatthews 2:d2c61a9be078 471
omatthews 2:d2c61a9be078 472 default:
omatthews 2:d2c61a9be078 473 PB_RETURN_ERROR(stream, "invalid field type");
omatthews 2:d2c61a9be078 474 }
omatthews 2:d2c61a9be078 475 }
omatthews 2:d2c61a9be078 476
omatthews 2:d2c61a9be078 477 #ifdef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 478 /* Allocate storage for the field and store the pointer at iter->pData.
omatthews 2:d2c61a9be078 479 * array_size is the number of entries to reserve in an array.
omatthews 2:d2c61a9be078 480 * Zero size is not allowed, use pb_free() for releasing.
omatthews 2:d2c61a9be078 481 */
omatthews 2:d2c61a9be078 482 static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size)
omatthews 2:d2c61a9be078 483 {
omatthews 2:d2c61a9be078 484 void *ptr = *(void**)pData;
omatthews 2:d2c61a9be078 485
omatthews 2:d2c61a9be078 486 if (data_size == 0 || array_size == 0)
omatthews 2:d2c61a9be078 487 PB_RETURN_ERROR(stream, "invalid size");
omatthews 2:d2c61a9be078 488
omatthews 2:d2c61a9be078 489 /* Check for multiplication overflows.
omatthews 2:d2c61a9be078 490 * This code avoids the costly division if the sizes are small enough.
omatthews 2:d2c61a9be078 491 * Multiplication is safe as long as only half of bits are set
omatthews 2:d2c61a9be078 492 * in either multiplicand.
omatthews 2:d2c61a9be078 493 */
omatthews 2:d2c61a9be078 494 {
omatthews 2:d2c61a9be078 495 const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
omatthews 2:d2c61a9be078 496 if (data_size >= check_limit || array_size >= check_limit)
omatthews 2:d2c61a9be078 497 {
omatthews 2:d2c61a9be078 498 const size_t size_max = (size_t)-1;
omatthews 2:d2c61a9be078 499 if (size_max / array_size < data_size)
omatthews 2:d2c61a9be078 500 {
omatthews 2:d2c61a9be078 501 PB_RETURN_ERROR(stream, "size too large");
omatthews 2:d2c61a9be078 502 }
omatthews 2:d2c61a9be078 503 }
omatthews 2:d2c61a9be078 504 }
omatthews 2:d2c61a9be078 505
omatthews 2:d2c61a9be078 506 /* Allocate new or expand previous allocation */
omatthews 2:d2c61a9be078 507 /* Note: on failure the old pointer will remain in the structure,
omatthews 2:d2c61a9be078 508 * the message must be freed by caller also on error return. */
omatthews 2:d2c61a9be078 509 ptr = pb_realloc(ptr, array_size * data_size);
omatthews 2:d2c61a9be078 510 if (ptr == NULL)
omatthews 2:d2c61a9be078 511 PB_RETURN_ERROR(stream, "realloc failed");
omatthews 2:d2c61a9be078 512
omatthews 2:d2c61a9be078 513 *(void**)pData = ptr;
omatthews 2:d2c61a9be078 514 return true;
omatthews 2:d2c61a9be078 515 }
omatthews 2:d2c61a9be078 516
omatthews 2:d2c61a9be078 517 /* Clear a newly allocated item in case it contains a pointer, or is a submessage. */
omatthews 2:d2c61a9be078 518 static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 519 {
omatthews 2:d2c61a9be078 520 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING ||
omatthews 2:d2c61a9be078 521 PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES)
omatthews 2:d2c61a9be078 522 {
omatthews 2:d2c61a9be078 523 *(void**)pItem = NULL;
omatthews 2:d2c61a9be078 524 }
omatthews 2:d2c61a9be078 525 else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
omatthews 2:d2c61a9be078 526 {
omatthews 2:d2c61a9be078 527 /* We memset to zero so that any callbacks are set to NULL.
omatthews 2:d2c61a9be078 528 * Then set any default values. */
omatthews 2:d2c61a9be078 529 memset(pItem, 0, iter->pos->data_size);
omatthews 2:d2c61a9be078 530 pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem);
omatthews 2:d2c61a9be078 531 }
omatthews 2:d2c61a9be078 532 }
omatthews 2:d2c61a9be078 533 #endif
omatthews 2:d2c61a9be078 534
omatthews 2:d2c61a9be078 535 static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 536 {
omatthews 2:d2c61a9be078 537 #ifndef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 538 PB_UNUSED(wire_type);
omatthews 2:d2c61a9be078 539 PB_UNUSED(iter);
omatthews 2:d2c61a9be078 540 PB_RETURN_ERROR(stream, "no malloc support");
omatthews 2:d2c61a9be078 541 #else
omatthews 2:d2c61a9be078 542 pb_type_t type;
omatthews 2:d2c61a9be078 543 pb_decoder_t func;
omatthews 2:d2c61a9be078 544
omatthews 2:d2c61a9be078 545 type = iter->pos->type;
omatthews 2:d2c61a9be078 546 func = PB_DECODERS[PB_LTYPE(type)];
omatthews 2:d2c61a9be078 547
omatthews 2:d2c61a9be078 548 switch (PB_HTYPE(type))
omatthews 2:d2c61a9be078 549 {
omatthews 2:d2c61a9be078 550 case PB_HTYPE_REQUIRED:
omatthews 2:d2c61a9be078 551 case PB_HTYPE_OPTIONAL:
omatthews 2:d2c61a9be078 552 case PB_HTYPE_ONEOF:
omatthews 2:d2c61a9be078 553 if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE &&
omatthews 2:d2c61a9be078 554 *(void**)iter->pData != NULL)
omatthews 2:d2c61a9be078 555 {
omatthews 2:d2c61a9be078 556 /* Duplicate field, have to release the old allocation first. */
omatthews 2:d2c61a9be078 557 pb_release_single_field(iter);
intrinseca 0:c7beea49fc91 558 }
intrinseca 0:c7beea49fc91 559
omatthews 2:d2c61a9be078 560 if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
omatthews 2:d2c61a9be078 561 {
omatthews 2:d2c61a9be078 562 *(pb_size_t*)iter->pSize = iter->pos->tag;
omatthews 2:d2c61a9be078 563 }
omatthews 2:d2c61a9be078 564
omatthews 2:d2c61a9be078 565 if (PB_LTYPE(type) == PB_LTYPE_STRING ||
omatthews 2:d2c61a9be078 566 PB_LTYPE(type) == PB_LTYPE_BYTES)
omatthews 2:d2c61a9be078 567 {
omatthews 2:d2c61a9be078 568 return func(stream, iter->pos, iter->pData);
omatthews 2:d2c61a9be078 569 }
omatthews 2:d2c61a9be078 570 else
intrinseca 0:c7beea49fc91 571 {
omatthews 2:d2c61a9be078 572 if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1))
omatthews 2:d2c61a9be078 573 return false;
omatthews 2:d2c61a9be078 574
omatthews 2:d2c61a9be078 575 initialize_pointer_field(*(void**)iter->pData, iter);
omatthews 2:d2c61a9be078 576 return func(stream, iter->pos, *(void**)iter->pData);
omatthews 2:d2c61a9be078 577 }
omatthews 2:d2c61a9be078 578
omatthews 2:d2c61a9be078 579 case PB_HTYPE_REPEATED:
omatthews 2:d2c61a9be078 580 if (wire_type == PB_WT_STRING
omatthews 2:d2c61a9be078 581 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
omatthews 2:d2c61a9be078 582 {
omatthews 2:d2c61a9be078 583 /* Packed array, multiple items come in at once. */
omatthews 2:d2c61a9be078 584 bool status = true;
omatthews 2:d2c61a9be078 585 pb_size_t *size = (pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 586 size_t allocated_size = *size;
omatthews 2:d2c61a9be078 587 void *pItem;
intrinseca 0:c7beea49fc91 588 pb_istream_t substream;
intrinseca 0:c7beea49fc91 589
intrinseca 0:c7beea49fc91 590 if (!pb_make_string_substream(stream, &substream))
intrinseca 0:c7beea49fc91 591 return false;
intrinseca 0:c7beea49fc91 592
intrinseca 0:c7beea49fc91 593 while (substream.bytes_left)
intrinseca 0:c7beea49fc91 594 {
omatthews 2:d2c61a9be078 595 if ((size_t)*size + 1 > allocated_size)
omatthews 2:d2c61a9be078 596 {
omatthews 2:d2c61a9be078 597 /* Allocate more storage. This tries to guess the
omatthews 2:d2c61a9be078 598 * number of remaining entries. Round the division
omatthews 2:d2c61a9be078 599 * upwards. */
omatthews 2:d2c61a9be078 600 allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1;
omatthews 2:d2c61a9be078 601
omatthews 2:d2c61a9be078 602 if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size))
omatthews 2:d2c61a9be078 603 {
omatthews 2:d2c61a9be078 604 status = false;
omatthews 2:d2c61a9be078 605 break;
omatthews 2:d2c61a9be078 606 }
omatthews 2:d2c61a9be078 607 }
omatthews 2:d2c61a9be078 608
omatthews 2:d2c61a9be078 609 /* Decode the array entry */
omatthews 2:d2c61a9be078 610 pItem = *(char**)iter->pData + iter->pos->data_size * (*size);
omatthews 2:d2c61a9be078 611 initialize_pointer_field(pItem, iter);
omatthews 2:d2c61a9be078 612 if (!func(&substream, iter->pos, pItem))
omatthews 2:d2c61a9be078 613 {
omatthews 2:d2c61a9be078 614 status = false;
omatthews 2:d2c61a9be078 615 break;
omatthews 2:d2c61a9be078 616 }
omatthews 2:d2c61a9be078 617
omatthews 2:d2c61a9be078 618 if (*size == PB_SIZE_MAX)
omatthews 2:d2c61a9be078 619 {
omatthews 2:d2c61a9be078 620 #ifndef PB_NO_ERRMSG
omatthews 2:d2c61a9be078 621 stream->errmsg = "too many array entries";
omatthews 2:d2c61a9be078 622 #endif
omatthews 2:d2c61a9be078 623 status = false;
omatthews 2:d2c61a9be078 624 break;
omatthews 2:d2c61a9be078 625 }
omatthews 2:d2c61a9be078 626
omatthews 2:d2c61a9be078 627 (*size)++;
intrinseca 0:c7beea49fc91 628 }
omatthews 2:d2c61a9be078 629 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 630 return false;
intrinseca 0:c7beea49fc91 631
omatthews 2:d2c61a9be078 632 return status;
intrinseca 0:c7beea49fc91 633 }
intrinseca 0:c7beea49fc91 634 else
intrinseca 0:c7beea49fc91 635 {
omatthews 2:d2c61a9be078 636 /* Normal repeated field, i.e. only one item at a time. */
omatthews 2:d2c61a9be078 637 pb_size_t *size = (pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 638 void *pItem;
omatthews 2:d2c61a9be078 639
omatthews 2:d2c61a9be078 640 if (*size == PB_SIZE_MAX)
omatthews 2:d2c61a9be078 641 PB_RETURN_ERROR(stream, "too many array entries");
intrinseca 0:c7beea49fc91 642
omatthews 2:d2c61a9be078 643 (*size)++;
omatthews 2:d2c61a9be078 644 if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size))
intrinseca 0:c7beea49fc91 645 return false;
omatthews 2:d2c61a9be078 646
omatthews 2:d2c61a9be078 647 pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1);
omatthews 2:d2c61a9be078 648 initialize_pointer_field(pItem, iter);
omatthews 2:d2c61a9be078 649 return func(stream, iter->pos, pItem);
intrinseca 0:c7beea49fc91 650 }
omatthews 2:d2c61a9be078 651
omatthews 2:d2c61a9be078 652 default:
omatthews 2:d2c61a9be078 653 PB_RETURN_ERROR(stream, "invalid field type");
omatthews 2:d2c61a9be078 654 }
omatthews 2:d2c61a9be078 655 #endif
omatthews 2:d2c61a9be078 656 }
omatthews 2:d2c61a9be078 657
omatthews 2:d2c61a9be078 658 static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 659 {
omatthews 2:d2c61a9be078 660 pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
omatthews 2:d2c61a9be078 661 #ifdef PB_OLD_CALLBACK_STYLE
omatthews 2:d2c61a9be078 662 void *arg;
omatthews 2:d2c61a9be078 663 #else
omatthews 2:d2c61a9be078 664 void **arg;
omatthews 2:d2c61a9be078 665 #endif
omatthews 2:d2c61a9be078 666
omatthews 2:d2c61a9be078 667 if (pCallback == NULL || pCallback->funcs.decode == NULL)
omatthews 2:d2c61a9be078 668 return pb_skip_field(stream, wire_type);
omatthews 2:d2c61a9be078 669
omatthews 2:d2c61a9be078 670 #ifdef PB_OLD_CALLBACK_STYLE
omatthews 2:d2c61a9be078 671 arg = pCallback->arg;
omatthews 2:d2c61a9be078 672 #else
omatthews 2:d2c61a9be078 673 arg = &(pCallback->arg);
omatthews 2:d2c61a9be078 674 #endif
omatthews 2:d2c61a9be078 675
omatthews 2:d2c61a9be078 676 if (wire_type == PB_WT_STRING)
omatthews 2:d2c61a9be078 677 {
omatthews 2:d2c61a9be078 678 pb_istream_t substream;
omatthews 2:d2c61a9be078 679
omatthews 2:d2c61a9be078 680 if (!pb_make_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 681 return false;
omatthews 2:d2c61a9be078 682
omatthews 2:d2c61a9be078 683 do
omatthews 2:d2c61a9be078 684 {
omatthews 2:d2c61a9be078 685 if (!pCallback->funcs.decode(&substream, iter->pos, arg))
omatthews 2:d2c61a9be078 686 PB_RETURN_ERROR(stream, "callback failed");
omatthews 2:d2c61a9be078 687 } while (substream.bytes_left);
omatthews 2:d2c61a9be078 688
omatthews 2:d2c61a9be078 689 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 690 return false;
omatthews 2:d2c61a9be078 691
omatthews 2:d2c61a9be078 692 return true;
omatthews 2:d2c61a9be078 693 }
omatthews 2:d2c61a9be078 694 else
omatthews 2:d2c61a9be078 695 {
omatthews 2:d2c61a9be078 696 /* Copy the single scalar value to stack.
omatthews 2:d2c61a9be078 697 * This is required so that we can limit the stream length,
omatthews 2:d2c61a9be078 698 * which in turn allows to use same callback for packed and
omatthews 2:d2c61a9be078 699 * not-packed fields. */
omatthews 2:d2c61a9be078 700 pb_istream_t substream;
omatthews 2:d2c61a9be078 701 pb_byte_t buffer[10];
omatthews 2:d2c61a9be078 702 size_t size = sizeof(buffer);
omatthews 2:d2c61a9be078 703
omatthews 2:d2c61a9be078 704 if (!read_raw_value(stream, wire_type, buffer, &size))
omatthews 2:d2c61a9be078 705 return false;
omatthews 2:d2c61a9be078 706 substream = pb_istream_from_buffer(buffer, size);
omatthews 2:d2c61a9be078 707
omatthews 2:d2c61a9be078 708 return pCallback->funcs.decode(&substream, iter->pos, arg);
omatthews 2:d2c61a9be078 709 }
omatthews 2:d2c61a9be078 710 }
omatthews 2:d2c61a9be078 711
omatthews 2:d2c61a9be078 712 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 713 {
omatthews 2:d2c61a9be078 714 #ifdef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 715 /* When decoding an oneof field, check if there is old data that must be
omatthews 2:d2c61a9be078 716 * released first. */
omatthews 2:d2c61a9be078 717 if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF)
omatthews 2:d2c61a9be078 718 {
omatthews 2:d2c61a9be078 719 if (!pb_release_union_field(stream, iter))
omatthews 2:d2c61a9be078 720 return false;
omatthews 2:d2c61a9be078 721 }
omatthews 2:d2c61a9be078 722 #endif
omatthews 2:d2c61a9be078 723
omatthews 2:d2c61a9be078 724 switch (PB_ATYPE(iter->pos->type))
omatthews 2:d2c61a9be078 725 {
omatthews 2:d2c61a9be078 726 case PB_ATYPE_STATIC:
omatthews 2:d2c61a9be078 727 return decode_static_field(stream, wire_type, iter);
omatthews 2:d2c61a9be078 728
omatthews 2:d2c61a9be078 729 case PB_ATYPE_POINTER:
omatthews 2:d2c61a9be078 730 return decode_pointer_field(stream, wire_type, iter);
omatthews 2:d2c61a9be078 731
omatthews 2:d2c61a9be078 732 case PB_ATYPE_CALLBACK:
omatthews 2:d2c61a9be078 733 return decode_callback_field(stream, wire_type, iter);
intrinseca 0:c7beea49fc91 734
intrinseca 0:c7beea49fc91 735 default:
intrinseca 0:c7beea49fc91 736 PB_RETURN_ERROR(stream, "invalid field type");
intrinseca 0:c7beea49fc91 737 }
intrinseca 0:c7beea49fc91 738 }
intrinseca 0:c7beea49fc91 739
omatthews 2:d2c61a9be078 740 static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension)
omatthews 2:d2c61a9be078 741 {
omatthews 2:d2c61a9be078 742 /* Fake a field iterator for the extension field.
omatthews 2:d2c61a9be078 743 * It is not actually safe to advance this iterator, but decode_field
omatthews 2:d2c61a9be078 744 * will not even try to. */
omatthews 2:d2c61a9be078 745 const pb_field_t *field = (const pb_field_t*)extension->type->arg;
omatthews 2:d2c61a9be078 746 (void)pb_field_iter_begin(iter, field, extension->dest);
omatthews 2:d2c61a9be078 747 iter->pData = extension->dest;
omatthews 2:d2c61a9be078 748 iter->pSize = &extension->found;
omatthews 2:d2c61a9be078 749
omatthews 2:d2c61a9be078 750 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 751 {
omatthews 2:d2c61a9be078 752 /* For pointer extensions, the pointer is stored directly
omatthews 2:d2c61a9be078 753 * in the extension structure. This avoids having an extra
omatthews 2:d2c61a9be078 754 * indirection. */
omatthews 2:d2c61a9be078 755 iter->pData = &extension->dest;
omatthews 2:d2c61a9be078 756 }
omatthews 2:d2c61a9be078 757 }
omatthews 2:d2c61a9be078 758
omatthews 2:d2c61a9be078 759 /* Default handler for extension fields. Expects a pb_field_t structure
omatthews 2:d2c61a9be078 760 * in extension->type->arg. */
omatthews 2:d2c61a9be078 761 static bool checkreturn default_extension_decoder(pb_istream_t *stream,
omatthews 2:d2c61a9be078 762 pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type)
omatthews 2:d2c61a9be078 763 {
omatthews 2:d2c61a9be078 764 const pb_field_t *field = (const pb_field_t*)extension->type->arg;
omatthews 2:d2c61a9be078 765 pb_field_iter_t iter;
omatthews 2:d2c61a9be078 766
omatthews 2:d2c61a9be078 767 if (field->tag != tag)
omatthews 2:d2c61a9be078 768 return true;
omatthews 2:d2c61a9be078 769
omatthews 2:d2c61a9be078 770 iter_from_extension(&iter, extension);
omatthews 2:d2c61a9be078 771 extension->found = true;
omatthews 2:d2c61a9be078 772 return decode_field(stream, wire_type, &iter);
omatthews 2:d2c61a9be078 773 }
omatthews 2:d2c61a9be078 774
omatthews 2:d2c61a9be078 775 /* Try to decode an unknown field as an extension field. Tries each extension
omatthews 2:d2c61a9be078 776 * decoder in turn, until one of them handles the field or loop ends. */
omatthews 2:d2c61a9be078 777 static bool checkreturn decode_extension(pb_istream_t *stream,
omatthews 2:d2c61a9be078 778 uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 779 {
omatthews 2:d2c61a9be078 780 pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
omatthews 2:d2c61a9be078 781 size_t pos = stream->bytes_left;
omatthews 2:d2c61a9be078 782
omatthews 2:d2c61a9be078 783 while (extension != NULL && pos == stream->bytes_left)
omatthews 2:d2c61a9be078 784 {
omatthews 2:d2c61a9be078 785 bool status;
omatthews 2:d2c61a9be078 786 if (extension->type->decode)
omatthews 2:d2c61a9be078 787 status = extension->type->decode(stream, extension, tag, wire_type);
omatthews 2:d2c61a9be078 788 else
omatthews 2:d2c61a9be078 789 status = default_extension_decoder(stream, extension, tag, wire_type);
omatthews 2:d2c61a9be078 790
omatthews 2:d2c61a9be078 791 if (!status)
omatthews 2:d2c61a9be078 792 return false;
omatthews 2:d2c61a9be078 793
omatthews 2:d2c61a9be078 794 extension = extension->next;
omatthews 2:d2c61a9be078 795 }
omatthews 2:d2c61a9be078 796
omatthews 2:d2c61a9be078 797 return true;
omatthews 2:d2c61a9be078 798 }
omatthews 2:d2c61a9be078 799
omatthews 2:d2c61a9be078 800 /* Step through the iterator until an extension field is found or until all
omatthews 2:d2c61a9be078 801 * entries have been checked. There can be only one extension field per
omatthews 2:d2c61a9be078 802 * message. Returns false if no extension field is found. */
omatthews 2:d2c61a9be078 803 static bool checkreturn find_extension_field(pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 804 {
omatthews 2:d2c61a9be078 805 const pb_field_t *start = iter->pos;
omatthews 2:d2c61a9be078 806
omatthews 2:d2c61a9be078 807 do {
omatthews 2:d2c61a9be078 808 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION)
omatthews 2:d2c61a9be078 809 return true;
omatthews 2:d2c61a9be078 810 (void)pb_field_iter_next(iter);
omatthews 2:d2c61a9be078 811 } while (iter->pos != start);
omatthews 2:d2c61a9be078 812
omatthews 2:d2c61a9be078 813 return false;
omatthews 2:d2c61a9be078 814 }
omatthews 2:d2c61a9be078 815
intrinseca 0:c7beea49fc91 816 /* Initialize message fields to default values, recursively */
omatthews 2:d2c61a9be078 817 static void pb_field_set_to_default(pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 818 {
omatthews 2:d2c61a9be078 819 pb_type_t type;
omatthews 2:d2c61a9be078 820 type = iter->pos->type;
omatthews 2:d2c61a9be078 821
omatthews 2:d2c61a9be078 822 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
omatthews 2:d2c61a9be078 823 {
omatthews 2:d2c61a9be078 824 pb_extension_t *ext = *(pb_extension_t* const *)iter->pData;
omatthews 2:d2c61a9be078 825 while (ext != NULL)
omatthews 2:d2c61a9be078 826 {
omatthews 2:d2c61a9be078 827 pb_field_iter_t ext_iter;
omatthews 2:d2c61a9be078 828 ext->found = false;
omatthews 2:d2c61a9be078 829 iter_from_extension(&ext_iter, ext);
omatthews 2:d2c61a9be078 830 pb_field_set_to_default(&ext_iter);
omatthews 2:d2c61a9be078 831 ext = ext->next;
omatthews 2:d2c61a9be078 832 }
omatthews 2:d2c61a9be078 833 }
omatthews 2:d2c61a9be078 834 else if (PB_ATYPE(type) == PB_ATYPE_STATIC)
omatthews 2:d2c61a9be078 835 {
omatthews 2:d2c61a9be078 836 bool init_data = true;
omatthews 2:d2c61a9be078 837 if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData)
omatthews 2:d2c61a9be078 838 {
omatthews 2:d2c61a9be078 839 /* Set has_field to false. Still initialize the optional field
omatthews 2:d2c61a9be078 840 * itself also. */
omatthews 2:d2c61a9be078 841 *(bool*)iter->pSize = false;
omatthews 2:d2c61a9be078 842 }
omatthews 2:d2c61a9be078 843 else if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
omatthews 2:d2c61a9be078 844 PB_HTYPE(type) == PB_HTYPE_ONEOF)
omatthews 2:d2c61a9be078 845 {
omatthews 2:d2c61a9be078 846 /* REPEATED: Set array count to 0, no need to initialize contents.
omatthews 2:d2c61a9be078 847 ONEOF: Set which_field to 0. */
omatthews 2:d2c61a9be078 848 *(pb_size_t*)iter->pSize = 0;
omatthews 2:d2c61a9be078 849 init_data = false;
omatthews 2:d2c61a9be078 850 }
omatthews 2:d2c61a9be078 851
omatthews 2:d2c61a9be078 852 if (init_data)
omatthews 2:d2c61a9be078 853 {
omatthews 2:d2c61a9be078 854 if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
omatthews 2:d2c61a9be078 855 {
omatthews 2:d2c61a9be078 856 /* Initialize submessage to defaults */
omatthews 2:d2c61a9be078 857 pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData);
omatthews 2:d2c61a9be078 858 }
omatthews 2:d2c61a9be078 859 else if (iter->pos->ptr != NULL)
omatthews 2:d2c61a9be078 860 {
omatthews 2:d2c61a9be078 861 /* Initialize to default value */
omatthews 2:d2c61a9be078 862 memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size);
omatthews 2:d2c61a9be078 863 }
omatthews 2:d2c61a9be078 864 else
omatthews 2:d2c61a9be078 865 {
omatthews 2:d2c61a9be078 866 /* Initialize to zeros */
omatthews 2:d2c61a9be078 867 memset(iter->pData, 0, iter->pos->data_size);
omatthews 2:d2c61a9be078 868 }
omatthews 2:d2c61a9be078 869 }
omatthews 2:d2c61a9be078 870 }
omatthews 2:d2c61a9be078 871 else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 872 {
omatthews 2:d2c61a9be078 873 /* Initialize the pointer to NULL. */
omatthews 2:d2c61a9be078 874 *(void**)iter->pData = NULL;
omatthews 2:d2c61a9be078 875
omatthews 2:d2c61a9be078 876 /* Initialize array count to 0. */
omatthews 2:d2c61a9be078 877 if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
omatthews 2:d2c61a9be078 878 PB_HTYPE(type) == PB_HTYPE_ONEOF)
omatthews 2:d2c61a9be078 879 {
omatthews 2:d2c61a9be078 880 *(pb_size_t*)iter->pSize = 0;
omatthews 2:d2c61a9be078 881 }
omatthews 2:d2c61a9be078 882 }
omatthews 2:d2c61a9be078 883 else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
omatthews 2:d2c61a9be078 884 {
omatthews 2:d2c61a9be078 885 /* Don't overwrite callback */
omatthews 2:d2c61a9be078 886 }
omatthews 2:d2c61a9be078 887 }
omatthews 2:d2c61a9be078 888
intrinseca 0:c7beea49fc91 889 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
intrinseca 0:c7beea49fc91 890 {
omatthews 2:d2c61a9be078 891 pb_field_iter_t iter;
omatthews 2:d2c61a9be078 892
omatthews 2:d2c61a9be078 893 if (!pb_field_iter_begin(&iter, fields, dest_struct))
omatthews 2:d2c61a9be078 894 return; /* Empty message type */
intrinseca 0:c7beea49fc91 895
intrinseca 0:c7beea49fc91 896 do
intrinseca 0:c7beea49fc91 897 {
omatthews 2:d2c61a9be078 898 pb_field_set_to_default(&iter);
omatthews 2:d2c61a9be078 899 } while (pb_field_iter_next(&iter));
intrinseca 0:c7beea49fc91 900 }
intrinseca 0:c7beea49fc91 901
intrinseca 0:c7beea49fc91 902 /*********************
intrinseca 0:c7beea49fc91 903 * Decode all fields *
intrinseca 0:c7beea49fc91 904 *********************/
intrinseca 0:c7beea49fc91 905
intrinseca 0:c7beea49fc91 906 bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
intrinseca 0:c7beea49fc91 907 {
omatthews 2:d2c61a9be078 908 uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0};
omatthews 2:d2c61a9be078 909 const uint32_t allbits = ~(uint32_t)0;
omatthews 2:d2c61a9be078 910 uint32_t extension_range_start = 0;
omatthews 2:d2c61a9be078 911 pb_field_iter_t iter;
omatthews 2:d2c61a9be078 912
omatthews 2:d2c61a9be078 913 /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed
omatthews 2:d2c61a9be078 914 * count field. This can only handle _one_ repeated fixed count field that
omatthews 2:d2c61a9be078 915 * is unpacked and unordered among other (non repeated fixed count) fields.
omatthews 2:d2c61a9be078 916 */
omatthews 2:d2c61a9be078 917 const pb_field_t *fixed_count_field = NULL;
omatthews 2:d2c61a9be078 918 pb_size_t fixed_count_size = 0;
omatthews 2:d2c61a9be078 919
omatthews 2:d2c61a9be078 920 /* Return value ignored, as empty message types will be correctly handled by
omatthews 2:d2c61a9be078 921 * pb_field_iter_find() anyway. */
omatthews 2:d2c61a9be078 922 (void)pb_field_iter_begin(&iter, fields, dest_struct);
omatthews 2:d2c61a9be078 923
intrinseca 0:c7beea49fc91 924 while (stream->bytes_left)
intrinseca 0:c7beea49fc91 925 {
intrinseca 0:c7beea49fc91 926 uint32_t tag;
intrinseca 0:c7beea49fc91 927 pb_wire_type_t wire_type;
intrinseca 0:c7beea49fc91 928 bool eof;
omatthews 2:d2c61a9be078 929
intrinseca 0:c7beea49fc91 930 if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
intrinseca 0:c7beea49fc91 931 {
intrinseca 0:c7beea49fc91 932 if (eof)
intrinseca 0:c7beea49fc91 933 break;
intrinseca 0:c7beea49fc91 934 else
intrinseca 0:c7beea49fc91 935 return false;
intrinseca 0:c7beea49fc91 936 }
omatthews 2:d2c61a9be078 937
omatthews 2:d2c61a9be078 938 if (!pb_field_iter_find(&iter, tag))
intrinseca 0:c7beea49fc91 939 {
omatthews 2:d2c61a9be078 940 /* No match found, check if it matches an extension. */
omatthews 2:d2c61a9be078 941 if (tag >= extension_range_start)
omatthews 2:d2c61a9be078 942 {
omatthews 2:d2c61a9be078 943 if (!find_extension_field(&iter))
omatthews 2:d2c61a9be078 944 extension_range_start = (uint32_t)-1;
omatthews 2:d2c61a9be078 945 else
omatthews 2:d2c61a9be078 946 extension_range_start = iter.pos->tag;
omatthews 2:d2c61a9be078 947
omatthews 2:d2c61a9be078 948 if (tag >= extension_range_start)
omatthews 2:d2c61a9be078 949 {
omatthews 2:d2c61a9be078 950 size_t pos = stream->bytes_left;
omatthews 2:d2c61a9be078 951
omatthews 2:d2c61a9be078 952 if (!decode_extension(stream, tag, wire_type, &iter))
omatthews 2:d2c61a9be078 953 return false;
omatthews 2:d2c61a9be078 954
omatthews 2:d2c61a9be078 955 if (pos != stream->bytes_left)
omatthews 2:d2c61a9be078 956 {
omatthews 2:d2c61a9be078 957 /* The field was handled */
omatthews 2:d2c61a9be078 958 continue;
omatthews 2:d2c61a9be078 959 }
omatthews 2:d2c61a9be078 960 }
omatthews 2:d2c61a9be078 961 }
omatthews 2:d2c61a9be078 962
intrinseca 0:c7beea49fc91 963 /* No match found, skip data */
intrinseca 0:c7beea49fc91 964 if (!pb_skip_field(stream, wire_type))
intrinseca 0:c7beea49fc91 965 return false;
intrinseca 0:c7beea49fc91 966 continue;
intrinseca 0:c7beea49fc91 967 }
omatthews 2:d2c61a9be078 968
omatthews 2:d2c61a9be078 969 /* If a repeated fixed count field was found, get size from
omatthews 2:d2c61a9be078 970 * 'fixed_count_field' as there is no counter contained in the struct.
omatthews 2:d2c61a9be078 971 */
omatthews 2:d2c61a9be078 972 if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED
omatthews 2:d2c61a9be078 973 && iter.pSize == iter.pData)
omatthews 2:d2c61a9be078 974 {
omatthews 2:d2c61a9be078 975 if (fixed_count_field != iter.pos) {
omatthews 2:d2c61a9be078 976 /* If the new fixed count field does not match the previous one,
omatthews 2:d2c61a9be078 977 * check that the previous one is NULL or that it finished
omatthews 2:d2c61a9be078 978 * receiving all the expected data.
omatthews 2:d2c61a9be078 979 */
omatthews 2:d2c61a9be078 980 if (fixed_count_field != NULL &&
omatthews 2:d2c61a9be078 981 fixed_count_size != fixed_count_field->array_size)
omatthews 2:d2c61a9be078 982 {
omatthews 2:d2c61a9be078 983 PB_RETURN_ERROR(stream, "wrong size for fixed count field");
omatthews 2:d2c61a9be078 984 }
omatthews 2:d2c61a9be078 985
omatthews 2:d2c61a9be078 986 fixed_count_field = iter.pos;
omatthews 2:d2c61a9be078 987 fixed_count_size = 0;
omatthews 2:d2c61a9be078 988 }
omatthews 2:d2c61a9be078 989
omatthews 2:d2c61a9be078 990 iter.pSize = &fixed_count_size;
omatthews 2:d2c61a9be078 991 }
omatthews 2:d2c61a9be078 992
omatthews 2:d2c61a9be078 993 if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED
intrinseca 0:c7beea49fc91 994 && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
intrinseca 0:c7beea49fc91 995 {
omatthews 2:d2c61a9be078 996 uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31));
omatthews 2:d2c61a9be078 997 fields_seen[iter.required_field_index >> 5] |= tmp;
intrinseca 0:c7beea49fc91 998 }
omatthews 2:d2c61a9be078 999
intrinseca 0:c7beea49fc91 1000 if (!decode_field(stream, wire_type, &iter))
intrinseca 0:c7beea49fc91 1001 return false;
intrinseca 0:c7beea49fc91 1002 }
omatthews 2:d2c61a9be078 1003
omatthews 2:d2c61a9be078 1004 /* Check that all elements of the last decoded fixed count field were present. */
omatthews 2:d2c61a9be078 1005 if (fixed_count_field != NULL &&
omatthews 2:d2c61a9be078 1006 fixed_count_size != fixed_count_field->array_size)
omatthews 2:d2c61a9be078 1007 {
omatthews 2:d2c61a9be078 1008 PB_RETURN_ERROR(stream, "wrong size for fixed count field");
omatthews 2:d2c61a9be078 1009 }
omatthews 2:d2c61a9be078 1010
intrinseca 0:c7beea49fc91 1011 /* Check that all required fields were present. */
intrinseca 0:c7beea49fc91 1012 {
intrinseca 0:c7beea49fc91 1013 /* First figure out the number of required fields by
intrinseca 0:c7beea49fc91 1014 * seeking to the end of the field array. Usually we
intrinseca 0:c7beea49fc91 1015 * are already close to end after decoding.
intrinseca 0:c7beea49fc91 1016 */
intrinseca 0:c7beea49fc91 1017 unsigned req_field_count;
intrinseca 0:c7beea49fc91 1018 pb_type_t last_type;
intrinseca 0:c7beea49fc91 1019 unsigned i;
intrinseca 0:c7beea49fc91 1020 do {
intrinseca 0:c7beea49fc91 1021 req_field_count = iter.required_field_index;
omatthews 2:d2c61a9be078 1022 last_type = iter.pos->type;
omatthews 2:d2c61a9be078 1023 } while (pb_field_iter_next(&iter));
intrinseca 0:c7beea49fc91 1024
intrinseca 0:c7beea49fc91 1025 /* Fixup if last field was also required. */
omatthews 2:d2c61a9be078 1026 if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0)
intrinseca 0:c7beea49fc91 1027 req_field_count++;
intrinseca 0:c7beea49fc91 1028
omatthews 2:d2c61a9be078 1029 if (req_field_count > PB_MAX_REQUIRED_FIELDS)
omatthews 2:d2c61a9be078 1030 req_field_count = PB_MAX_REQUIRED_FIELDS;
omatthews 2:d2c61a9be078 1031
omatthews 2:d2c61a9be078 1032 if (req_field_count > 0)
intrinseca 0:c7beea49fc91 1033 {
omatthews 2:d2c61a9be078 1034 /* Check the whole words */
omatthews 2:d2c61a9be078 1035 for (i = 0; i < (req_field_count >> 5); i++)
omatthews 2:d2c61a9be078 1036 {
omatthews 2:d2c61a9be078 1037 if (fields_seen[i] != allbits)
omatthews 2:d2c61a9be078 1038 PB_RETURN_ERROR(stream, "missing required field");
omatthews 2:d2c61a9be078 1039 }
omatthews 2:d2c61a9be078 1040
omatthews 2:d2c61a9be078 1041 /* Check the remaining bits (if any) */
omatthews 2:d2c61a9be078 1042 if ((req_field_count & 31) != 0)
omatthews 2:d2c61a9be078 1043 {
omatthews 2:d2c61a9be078 1044 if (fields_seen[req_field_count >> 5] !=
omatthews 2:d2c61a9be078 1045 (allbits >> (32 - (req_field_count & 31))))
omatthews 2:d2c61a9be078 1046 {
omatthews 2:d2c61a9be078 1047 PB_RETURN_ERROR(stream, "missing required field");
omatthews 2:d2c61a9be078 1048 }
omatthews 2:d2c61a9be078 1049 }
intrinseca 0:c7beea49fc91 1050 }
intrinseca 0:c7beea49fc91 1051 }
intrinseca 0:c7beea49fc91 1052
intrinseca 0:c7beea49fc91 1053 return true;
intrinseca 0:c7beea49fc91 1054 }
intrinseca 0:c7beea49fc91 1055
intrinseca 0:c7beea49fc91 1056 bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
intrinseca 0:c7beea49fc91 1057 {
omatthews 2:d2c61a9be078 1058 bool status;
intrinseca 0:c7beea49fc91 1059 pb_message_set_to_defaults(fields, dest_struct);
omatthews 2:d2c61a9be078 1060 status = pb_decode_noinit(stream, fields, dest_struct);
omatthews 2:d2c61a9be078 1061
omatthews 2:d2c61a9be078 1062 #ifdef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 1063 if (!status)
omatthews 2:d2c61a9be078 1064 pb_release(fields, dest_struct);
omatthews 2:d2c61a9be078 1065 #endif
omatthews 2:d2c61a9be078 1066
omatthews 2:d2c61a9be078 1067 return status;
omatthews 2:d2c61a9be078 1068 }
omatthews 2:d2c61a9be078 1069
omatthews 2:d2c61a9be078 1070 bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
omatthews 2:d2c61a9be078 1071 {
omatthews 2:d2c61a9be078 1072 pb_istream_t substream;
omatthews 2:d2c61a9be078 1073 bool status;
omatthews 2:d2c61a9be078 1074
omatthews 2:d2c61a9be078 1075 if (!pb_make_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 1076 return false;
omatthews 2:d2c61a9be078 1077
omatthews 2:d2c61a9be078 1078 status = pb_decode_noinit(&substream, fields, dest_struct);
omatthews 2:d2c61a9be078 1079
omatthews 2:d2c61a9be078 1080 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 1081 return false;
omatthews 2:d2c61a9be078 1082 return status;
omatthews 2:d2c61a9be078 1083 }
omatthews 2:d2c61a9be078 1084
omatthews 2:d2c61a9be078 1085 bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
omatthews 2:d2c61a9be078 1086 {
omatthews 2:d2c61a9be078 1087 pb_istream_t substream;
omatthews 2:d2c61a9be078 1088 bool status;
omatthews 2:d2c61a9be078 1089
omatthews 2:d2c61a9be078 1090 if (!pb_make_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 1091 return false;
omatthews 2:d2c61a9be078 1092
omatthews 2:d2c61a9be078 1093 status = pb_decode(&substream, fields, dest_struct);
omatthews 2:d2c61a9be078 1094
omatthews 2:d2c61a9be078 1095 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 1096 return false;
omatthews 2:d2c61a9be078 1097 return status;
omatthews 2:d2c61a9be078 1098 }
omatthews 2:d2c61a9be078 1099
omatthews 2:d2c61a9be078 1100 bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
omatthews 2:d2c61a9be078 1101 {
omatthews 2:d2c61a9be078 1102 /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */
omatthews 2:d2c61a9be078 1103 return pb_decode(stream, fields, dest_struct);
omatthews 2:d2c61a9be078 1104 }
omatthews 2:d2c61a9be078 1105
omatthews 2:d2c61a9be078 1106 #ifdef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 1107 /* Given an oneof field, if there has already been a field inside this oneof,
omatthews 2:d2c61a9be078 1108 * release it before overwriting with a different one. */
omatthews 2:d2c61a9be078 1109 static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 1110 {
omatthews 2:d2c61a9be078 1111 pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */
omatthews 2:d2c61a9be078 1112 pb_size_t new_tag = iter->pos->tag; /* New which_ value */
omatthews 2:d2c61a9be078 1113
omatthews 2:d2c61a9be078 1114 if (old_tag == 0)
omatthews 2:d2c61a9be078 1115 return true; /* Ok, no old data in union */
omatthews 2:d2c61a9be078 1116
omatthews 2:d2c61a9be078 1117 if (old_tag == new_tag)
omatthews 2:d2c61a9be078 1118 return true; /* Ok, old data is of same type => merge */
omatthews 2:d2c61a9be078 1119
omatthews 2:d2c61a9be078 1120 /* Release old data. The find can fail if the message struct contains
omatthews 2:d2c61a9be078 1121 * invalid data. */
omatthews 2:d2c61a9be078 1122 if (!pb_field_iter_find(iter, old_tag))
omatthews 2:d2c61a9be078 1123 PB_RETURN_ERROR(stream, "invalid union tag");
omatthews 2:d2c61a9be078 1124
omatthews 2:d2c61a9be078 1125 pb_release_single_field(iter);
omatthews 2:d2c61a9be078 1126
omatthews 2:d2c61a9be078 1127 /* Restore iterator to where it should be.
omatthews 2:d2c61a9be078 1128 * This shouldn't fail unless the pb_field_t structure is corrupted. */
omatthews 2:d2c61a9be078 1129 if (!pb_field_iter_find(iter, new_tag))
omatthews 2:d2c61a9be078 1130 PB_RETURN_ERROR(stream, "iterator error");
omatthews 2:d2c61a9be078 1131
omatthews 2:d2c61a9be078 1132 return true;
intrinseca 0:c7beea49fc91 1133 }
intrinseca 0:c7beea49fc91 1134
omatthews 2:d2c61a9be078 1135 static void pb_release_single_field(const pb_field_iter_t *iter)
omatthews 2:d2c61a9be078 1136 {
omatthews 2:d2c61a9be078 1137 pb_type_t type;
omatthews 2:d2c61a9be078 1138 type = iter->pos->type;
omatthews 2:d2c61a9be078 1139
omatthews 2:d2c61a9be078 1140 if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
omatthews 2:d2c61a9be078 1141 {
omatthews 2:d2c61a9be078 1142 if (*(pb_size_t*)iter->pSize != iter->pos->tag)
omatthews 2:d2c61a9be078 1143 return; /* This is not the current field in the union */
omatthews 2:d2c61a9be078 1144 }
omatthews 2:d2c61a9be078 1145
omatthews 2:d2c61a9be078 1146 /* Release anything contained inside an extension or submsg.
omatthews 2:d2c61a9be078 1147 * This has to be done even if the submsg itself is statically
omatthews 2:d2c61a9be078 1148 * allocated. */
omatthews 2:d2c61a9be078 1149 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
omatthews 2:d2c61a9be078 1150 {
omatthews 2:d2c61a9be078 1151 /* Release fields from all extensions in the linked list */
omatthews 2:d2c61a9be078 1152 pb_extension_t *ext = *(pb_extension_t**)iter->pData;
omatthews 2:d2c61a9be078 1153 while (ext != NULL)
omatthews 2:d2c61a9be078 1154 {
omatthews 2:d2c61a9be078 1155 pb_field_iter_t ext_iter;
omatthews 2:d2c61a9be078 1156 iter_from_extension(&ext_iter, ext);
omatthews 2:d2c61a9be078 1157 pb_release_single_field(&ext_iter);
omatthews 2:d2c61a9be078 1158 ext = ext->next;
omatthews 2:d2c61a9be078 1159 }
omatthews 2:d2c61a9be078 1160 }
omatthews 2:d2c61a9be078 1161 else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && PB_ATYPE(type) != PB_ATYPE_CALLBACK)
omatthews 2:d2c61a9be078 1162 {
omatthews 2:d2c61a9be078 1163 /* Release fields in submessage or submsg array */
omatthews 2:d2c61a9be078 1164 void *pItem = iter->pData;
omatthews 2:d2c61a9be078 1165 pb_size_t count = 1;
omatthews 2:d2c61a9be078 1166
omatthews 2:d2c61a9be078 1167 if (PB_ATYPE(type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 1168 {
omatthews 2:d2c61a9be078 1169 pItem = *(void**)iter->pData;
omatthews 2:d2c61a9be078 1170 }
omatthews 2:d2c61a9be078 1171
omatthews 2:d2c61a9be078 1172 if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
omatthews 2:d2c61a9be078 1173 {
omatthews 2:d2c61a9be078 1174 if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) {
omatthews 2:d2c61a9be078 1175 /* No _count field so use size of the array */
omatthews 2:d2c61a9be078 1176 count = iter->pos->array_size;
omatthews 2:d2c61a9be078 1177 } else {
omatthews 2:d2c61a9be078 1178 count = *(pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 1179 }
omatthews 2:d2c61a9be078 1180
omatthews 2:d2c61a9be078 1181 if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size)
omatthews 2:d2c61a9be078 1182 {
omatthews 2:d2c61a9be078 1183 /* Protect against corrupted _count fields */
omatthews 2:d2c61a9be078 1184 count = iter->pos->array_size;
omatthews 2:d2c61a9be078 1185 }
omatthews 2:d2c61a9be078 1186 }
omatthews 2:d2c61a9be078 1187
omatthews 2:d2c61a9be078 1188 if (pItem)
omatthews 2:d2c61a9be078 1189 {
omatthews 2:d2c61a9be078 1190 while (count--)
omatthews 2:d2c61a9be078 1191 {
omatthews 2:d2c61a9be078 1192 pb_release((const pb_field_t*)iter->pos->ptr, pItem);
omatthews 2:d2c61a9be078 1193 pItem = (char*)pItem + iter->pos->data_size;
omatthews 2:d2c61a9be078 1194 }
omatthews 2:d2c61a9be078 1195 }
omatthews 2:d2c61a9be078 1196 }
omatthews 2:d2c61a9be078 1197
omatthews 2:d2c61a9be078 1198 if (PB_ATYPE(type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 1199 {
omatthews 2:d2c61a9be078 1200 if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
omatthews 2:d2c61a9be078 1201 (PB_LTYPE(type) == PB_LTYPE_STRING ||
omatthews 2:d2c61a9be078 1202 PB_LTYPE(type) == PB_LTYPE_BYTES))
omatthews 2:d2c61a9be078 1203 {
omatthews 2:d2c61a9be078 1204 /* Release entries in repeated string or bytes array */
omatthews 2:d2c61a9be078 1205 void **pItem = *(void***)iter->pData;
omatthews 2:d2c61a9be078 1206 pb_size_t count = *(pb_size_t*)iter->pSize;
omatthews 2:d2c61a9be078 1207 while (count--)
omatthews 2:d2c61a9be078 1208 {
omatthews 2:d2c61a9be078 1209 pb_free(*pItem);
omatthews 2:d2c61a9be078 1210 *pItem++ = NULL;
omatthews 2:d2c61a9be078 1211 }
omatthews 2:d2c61a9be078 1212 }
omatthews 2:d2c61a9be078 1213
omatthews 2:d2c61a9be078 1214 if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
omatthews 2:d2c61a9be078 1215 {
omatthews 2:d2c61a9be078 1216 /* We are going to release the array, so set the size to 0 */
omatthews 2:d2c61a9be078 1217 *(pb_size_t*)iter->pSize = 0;
omatthews 2:d2c61a9be078 1218 }
omatthews 2:d2c61a9be078 1219
omatthews 2:d2c61a9be078 1220 /* Release main item */
omatthews 2:d2c61a9be078 1221 pb_free(*(void**)iter->pData);
omatthews 2:d2c61a9be078 1222 *(void**)iter->pData = NULL;
omatthews 2:d2c61a9be078 1223 }
omatthews 2:d2c61a9be078 1224 }
omatthews 2:d2c61a9be078 1225
omatthews 2:d2c61a9be078 1226 void pb_release(const pb_field_t fields[], void *dest_struct)
omatthews 2:d2c61a9be078 1227 {
omatthews 2:d2c61a9be078 1228 pb_field_iter_t iter;
omatthews 2:d2c61a9be078 1229
omatthews 2:d2c61a9be078 1230 if (!dest_struct)
omatthews 2:d2c61a9be078 1231 return; /* Ignore NULL pointers, similar to free() */
omatthews 2:d2c61a9be078 1232
omatthews 2:d2c61a9be078 1233 if (!pb_field_iter_begin(&iter, fields, dest_struct))
omatthews 2:d2c61a9be078 1234 return; /* Empty message type */
omatthews 2:d2c61a9be078 1235
omatthews 2:d2c61a9be078 1236 do
omatthews 2:d2c61a9be078 1237 {
omatthews 2:d2c61a9be078 1238 pb_release_single_field(&iter);
omatthews 2:d2c61a9be078 1239 } while (pb_field_iter_next(&iter));
omatthews 2:d2c61a9be078 1240 }
omatthews 2:d2c61a9be078 1241 #endif
omatthews 2:d2c61a9be078 1242
intrinseca 0:c7beea49fc91 1243 /* Field decoders */
intrinseca 0:c7beea49fc91 1244
omatthews 2:d2c61a9be078 1245 bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest)
intrinseca 0:c7beea49fc91 1246 {
omatthews 2:d2c61a9be078 1247 pb_uint64_t value;
intrinseca 0:c7beea49fc91 1248 if (!pb_decode_varint(stream, &value))
intrinseca 0:c7beea49fc91 1249 return false;
intrinseca 0:c7beea49fc91 1250
intrinseca 0:c7beea49fc91 1251 if (value & 1)
omatthews 2:d2c61a9be078 1252 *dest = (pb_int64_t)(~(value >> 1));
intrinseca 0:c7beea49fc91 1253 else
omatthews 2:d2c61a9be078 1254 *dest = (pb_int64_t)(value >> 1);
intrinseca 0:c7beea49fc91 1255
intrinseca 0:c7beea49fc91 1256 return true;
intrinseca 0:c7beea49fc91 1257 }
intrinseca 0:c7beea49fc91 1258
intrinseca 0:c7beea49fc91 1259 bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
intrinseca 0:c7beea49fc91 1260 {
omatthews 2:d2c61a9be078 1261 pb_byte_t bytes[4];
omatthews 2:d2c61a9be078 1262
omatthews 2:d2c61a9be078 1263 if (!pb_read(stream, bytes, 4))
omatthews 2:d2c61a9be078 1264 return false;
intrinseca 0:c7beea49fc91 1265
omatthews 2:d2c61a9be078 1266 *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) |
omatthews 2:d2c61a9be078 1267 ((uint32_t)bytes[1] << 8) |
omatthews 2:d2c61a9be078 1268 ((uint32_t)bytes[2] << 16) |
omatthews 2:d2c61a9be078 1269 ((uint32_t)bytes[3] << 24);
omatthews 2:d2c61a9be078 1270 return true;
omatthews 2:d2c61a9be078 1271 }
omatthews 2:d2c61a9be078 1272
omatthews 2:d2c61a9be078 1273 #ifndef PB_WITHOUT_64BIT
omatthews 2:d2c61a9be078 1274 bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
omatthews 2:d2c61a9be078 1275 {
omatthews 2:d2c61a9be078 1276 pb_byte_t bytes[8];
omatthews 2:d2c61a9be078 1277
omatthews 2:d2c61a9be078 1278 if (!pb_read(stream, bytes, 8))
intrinseca 0:c7beea49fc91 1279 return false;
intrinseca 0:c7beea49fc91 1280
omatthews 2:d2c61a9be078 1281 *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) |
omatthews 2:d2c61a9be078 1282 ((uint64_t)bytes[1] << 8) |
omatthews 2:d2c61a9be078 1283 ((uint64_t)bytes[2] << 16) |
omatthews 2:d2c61a9be078 1284 ((uint64_t)bytes[3] << 24) |
omatthews 2:d2c61a9be078 1285 ((uint64_t)bytes[4] << 32) |
omatthews 2:d2c61a9be078 1286 ((uint64_t)bytes[5] << 40) |
omatthews 2:d2c61a9be078 1287 ((uint64_t)bytes[6] << 48) |
omatthews 2:d2c61a9be078 1288 ((uint64_t)bytes[7] << 56);
omatthews 2:d2c61a9be078 1289
intrinseca 0:c7beea49fc91 1290 return true;
intrinseca 0:c7beea49fc91 1291 }
omatthews 2:d2c61a9be078 1292 #endif
intrinseca 0:c7beea49fc91 1293
omatthews 2:d2c61a9be078 1294 static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1295 {
omatthews 2:d2c61a9be078 1296 pb_uint64_t value;
omatthews 2:d2c61a9be078 1297 pb_int64_t svalue;
omatthews 2:d2c61a9be078 1298 pb_int64_t clamped;
omatthews 2:d2c61a9be078 1299 if (!pb_decode_varint(stream, &value))
intrinseca 0:c7beea49fc91 1300 return false;
intrinseca 0:c7beea49fc91 1301
omatthews 2:d2c61a9be078 1302 /* See issue 97: Google's C++ protobuf allows negative varint values to
omatthews 2:d2c61a9be078 1303 * be cast as int32_t, instead of the int64_t that should be used when
omatthews 2:d2c61a9be078 1304 * encoding. Previous nanopb versions had a bug in encoding. In order to
omatthews 2:d2c61a9be078 1305 * not break decoding of such messages, we cast <=32 bit fields to
omatthews 2:d2c61a9be078 1306 * int32_t first to get the sign correct.
omatthews 2:d2c61a9be078 1307 */
omatthews 2:d2c61a9be078 1308 if (field->data_size == sizeof(pb_int64_t))
omatthews 2:d2c61a9be078 1309 svalue = (pb_int64_t)value;
omatthews 2:d2c61a9be078 1310 else
omatthews 2:d2c61a9be078 1311 svalue = (int32_t)value;
omatthews 2:d2c61a9be078 1312
omatthews 2:d2c61a9be078 1313 /* Cast to the proper field size, while checking for overflows */
omatthews 2:d2c61a9be078 1314 if (field->data_size == sizeof(pb_int64_t))
omatthews 2:d2c61a9be078 1315 clamped = *(pb_int64_t*)dest = svalue;
omatthews 2:d2c61a9be078 1316 else if (field->data_size == sizeof(int32_t))
omatthews 2:d2c61a9be078 1317 clamped = *(int32_t*)dest = (int32_t)svalue;
omatthews 2:d2c61a9be078 1318 else if (field->data_size == sizeof(int_least16_t))
omatthews 2:d2c61a9be078 1319 clamped = *(int_least16_t*)dest = (int_least16_t)svalue;
omatthews 2:d2c61a9be078 1320 else if (field->data_size == sizeof(int_least8_t))
omatthews 2:d2c61a9be078 1321 clamped = *(int_least8_t*)dest = (int_least8_t)svalue;
omatthews 2:d2c61a9be078 1322 else
omatthews 2:d2c61a9be078 1323 PB_RETURN_ERROR(stream, "invalid data_size");
omatthews 2:d2c61a9be078 1324
omatthews 2:d2c61a9be078 1325 if (clamped != svalue)
omatthews 2:d2c61a9be078 1326 PB_RETURN_ERROR(stream, "integer too large");
omatthews 2:d2c61a9be078 1327
intrinseca 0:c7beea49fc91 1328 return true;
intrinseca 0:c7beea49fc91 1329 }
intrinseca 0:c7beea49fc91 1330
omatthews 2:d2c61a9be078 1331 static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1332 {
omatthews 2:d2c61a9be078 1333 pb_uint64_t value, clamped;
omatthews 2:d2c61a9be078 1334 if (!pb_decode_varint(stream, &value))
omatthews 2:d2c61a9be078 1335 return false;
intrinseca 0:c7beea49fc91 1336
omatthews 2:d2c61a9be078 1337 /* Cast to the proper field size, while checking for overflows */
omatthews 2:d2c61a9be078 1338 if (field->data_size == sizeof(pb_uint64_t))
omatthews 2:d2c61a9be078 1339 clamped = *(pb_uint64_t*)dest = value;
omatthews 2:d2c61a9be078 1340 else if (field->data_size == sizeof(uint32_t))
omatthews 2:d2c61a9be078 1341 clamped = *(uint32_t*)dest = (uint32_t)value;
omatthews 2:d2c61a9be078 1342 else if (field->data_size == sizeof(uint_least16_t))
omatthews 2:d2c61a9be078 1343 clamped = *(uint_least16_t*)dest = (uint_least16_t)value;
omatthews 2:d2c61a9be078 1344 else if (field->data_size == sizeof(uint_least8_t))
omatthews 2:d2c61a9be078 1345 clamped = *(uint_least8_t*)dest = (uint_least8_t)value;
omatthews 2:d2c61a9be078 1346 else
omatthews 2:d2c61a9be078 1347 PB_RETURN_ERROR(stream, "invalid data_size");
intrinseca 0:c7beea49fc91 1348
omatthews 2:d2c61a9be078 1349 if (clamped != value)
omatthews 2:d2c61a9be078 1350 PB_RETURN_ERROR(stream, "integer too large");
omatthews 2:d2c61a9be078 1351
omatthews 2:d2c61a9be078 1352 return true;
intrinseca 0:c7beea49fc91 1353 }
intrinseca 0:c7beea49fc91 1354
omatthews 2:d2c61a9be078 1355 static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1356 {
omatthews 2:d2c61a9be078 1357 pb_int64_t value, clamped;
omatthews 2:d2c61a9be078 1358 if (!pb_decode_svarint(stream, &value))
omatthews 2:d2c61a9be078 1359 return false;
intrinseca 0:c7beea49fc91 1360
omatthews 2:d2c61a9be078 1361 /* Cast to the proper field size, while checking for overflows */
omatthews 2:d2c61a9be078 1362 if (field->data_size == sizeof(pb_int64_t))
omatthews 2:d2c61a9be078 1363 clamped = *(pb_int64_t*)dest = value;
omatthews 2:d2c61a9be078 1364 else if (field->data_size == sizeof(int32_t))
omatthews 2:d2c61a9be078 1365 clamped = *(int32_t*)dest = (int32_t)value;
omatthews 2:d2c61a9be078 1366 else if (field->data_size == sizeof(int_least16_t))
omatthews 2:d2c61a9be078 1367 clamped = *(int_least16_t*)dest = (int_least16_t)value;
omatthews 2:d2c61a9be078 1368 else if (field->data_size == sizeof(int_least8_t))
omatthews 2:d2c61a9be078 1369 clamped = *(int_least8_t*)dest = (int_least8_t)value;
omatthews 2:d2c61a9be078 1370 else
omatthews 2:d2c61a9be078 1371 PB_RETURN_ERROR(stream, "invalid data_size");
omatthews 2:d2c61a9be078 1372
omatthews 2:d2c61a9be078 1373 if (clamped != value)
omatthews 2:d2c61a9be078 1374 PB_RETURN_ERROR(stream, "integer too large");
intrinseca 0:c7beea49fc91 1375
omatthews 2:d2c61a9be078 1376 return true;
intrinseca 0:c7beea49fc91 1377 }
intrinseca 0:c7beea49fc91 1378
omatthews 2:d2c61a9be078 1379 static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1380 {
omatthews 2:d2c61a9be078 1381 PB_UNUSED(field);
intrinseca 0:c7beea49fc91 1382 return pb_decode_fixed32(stream, dest);
intrinseca 0:c7beea49fc91 1383 }
intrinseca 0:c7beea49fc91 1384
omatthews 2:d2c61a9be078 1385 static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1386 {
omatthews 2:d2c61a9be078 1387 PB_UNUSED(field);
omatthews 2:d2c61a9be078 1388 #ifndef PB_WITHOUT_64BIT
intrinseca 0:c7beea49fc91 1389 return pb_decode_fixed64(stream, dest);
omatthews 2:d2c61a9be078 1390 #else
omatthews 2:d2c61a9be078 1391 PB_UNUSED(dest);
omatthews 2:d2c61a9be078 1392 PB_RETURN_ERROR(stream, "no 64bit support");
omatthews 2:d2c61a9be078 1393 #endif
intrinseca 0:c7beea49fc91 1394 }
intrinseca 0:c7beea49fc91 1395
omatthews 2:d2c61a9be078 1396 static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1397 {
omatthews 2:d2c61a9be078 1398 uint32_t size;
omatthews 2:d2c61a9be078 1399 size_t alloc_size;
omatthews 2:d2c61a9be078 1400 pb_bytes_array_t *bdest;
intrinseca 0:c7beea49fc91 1401
omatthews 2:d2c61a9be078 1402 if (!pb_decode_varint32(stream, &size))
intrinseca 0:c7beea49fc91 1403 return false;
intrinseca 0:c7beea49fc91 1404
omatthews 2:d2c61a9be078 1405 if (size > PB_SIZE_MAX)
intrinseca 0:c7beea49fc91 1406 PB_RETURN_ERROR(stream, "bytes overflow");
intrinseca 0:c7beea49fc91 1407
omatthews 2:d2c61a9be078 1408 alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size);
omatthews 2:d2c61a9be078 1409 if (size > alloc_size)
omatthews 2:d2c61a9be078 1410 PB_RETURN_ERROR(stream, "size too large");
omatthews 2:d2c61a9be078 1411
omatthews 2:d2c61a9be078 1412 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 1413 {
omatthews 2:d2c61a9be078 1414 #ifndef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 1415 PB_RETURN_ERROR(stream, "no malloc support");
omatthews 2:d2c61a9be078 1416 #else
omatthews 2:d2c61a9be078 1417 if (!allocate_field(stream, dest, alloc_size, 1))
omatthews 2:d2c61a9be078 1418 return false;
omatthews 2:d2c61a9be078 1419 bdest = *(pb_bytes_array_t**)dest;
omatthews 2:d2c61a9be078 1420 #endif
omatthews 2:d2c61a9be078 1421 }
omatthews 2:d2c61a9be078 1422 else
omatthews 2:d2c61a9be078 1423 {
omatthews 2:d2c61a9be078 1424 if (alloc_size > field->data_size)
omatthews 2:d2c61a9be078 1425 PB_RETURN_ERROR(stream, "bytes overflow");
omatthews 2:d2c61a9be078 1426 bdest = (pb_bytes_array_t*)dest;
omatthews 2:d2c61a9be078 1427 }
omatthews 2:d2c61a9be078 1428
omatthews 2:d2c61a9be078 1429 bdest->size = (pb_size_t)size;
omatthews 2:d2c61a9be078 1430 return pb_read(stream, bdest->bytes, size);
intrinseca 0:c7beea49fc91 1431 }
intrinseca 0:c7beea49fc91 1432
omatthews 2:d2c61a9be078 1433 static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1434 {
intrinseca 0:c7beea49fc91 1435 uint32_t size;
omatthews 2:d2c61a9be078 1436 size_t alloc_size;
intrinseca 0:c7beea49fc91 1437 bool status;
intrinseca 0:c7beea49fc91 1438 if (!pb_decode_varint32(stream, &size))
intrinseca 0:c7beea49fc91 1439 return false;
intrinseca 0:c7beea49fc91 1440
omatthews 2:d2c61a9be078 1441 /* Space for null terminator */
omatthews 2:d2c61a9be078 1442 alloc_size = size + 1;
omatthews 2:d2c61a9be078 1443
omatthews 2:d2c61a9be078 1444 if (alloc_size < size)
omatthews 2:d2c61a9be078 1445 PB_RETURN_ERROR(stream, "size too large");
intrinseca 0:c7beea49fc91 1446
omatthews 2:d2c61a9be078 1447 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
omatthews 2:d2c61a9be078 1448 {
omatthews 2:d2c61a9be078 1449 #ifndef PB_ENABLE_MALLOC
omatthews 2:d2c61a9be078 1450 PB_RETURN_ERROR(stream, "no malloc support");
omatthews 2:d2c61a9be078 1451 #else
omatthews 2:d2c61a9be078 1452 if (!allocate_field(stream, dest, alloc_size, 1))
omatthews 2:d2c61a9be078 1453 return false;
omatthews 2:d2c61a9be078 1454 dest = *(void**)dest;
omatthews 2:d2c61a9be078 1455 #endif
omatthews 2:d2c61a9be078 1456 }
omatthews 2:d2c61a9be078 1457 else
omatthews 2:d2c61a9be078 1458 {
omatthews 2:d2c61a9be078 1459 if (alloc_size > field->data_size)
omatthews 2:d2c61a9be078 1460 PB_RETURN_ERROR(stream, "string overflow");
omatthews 2:d2c61a9be078 1461 }
omatthews 2:d2c61a9be078 1462
omatthews 2:d2c61a9be078 1463 status = pb_read(stream, (pb_byte_t*)dest, size);
omatthews 2:d2c61a9be078 1464 *((pb_byte_t*)dest + size) = 0;
intrinseca 0:c7beea49fc91 1465 return status;
intrinseca 0:c7beea49fc91 1466 }
intrinseca 0:c7beea49fc91 1467
omatthews 2:d2c61a9be078 1468 static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
intrinseca 0:c7beea49fc91 1469 {
intrinseca 0:c7beea49fc91 1470 bool status;
intrinseca 0:c7beea49fc91 1471 pb_istream_t substream;
intrinseca 0:c7beea49fc91 1472 const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr;
intrinseca 0:c7beea49fc91 1473
intrinseca 0:c7beea49fc91 1474 if (!pb_make_string_substream(stream, &substream))
intrinseca 0:c7beea49fc91 1475 return false;
intrinseca 0:c7beea49fc91 1476
intrinseca 0:c7beea49fc91 1477 if (field->ptr == NULL)
intrinseca 0:c7beea49fc91 1478 PB_RETURN_ERROR(stream, "invalid field descriptor");
intrinseca 0:c7beea49fc91 1479
intrinseca 0:c7beea49fc91 1480 /* New array entries need to be initialized, while required and optional
intrinseca 0:c7beea49fc91 1481 * submessages have already been initialized in the top-level pb_decode. */
omatthews 2:d2c61a9be078 1482 if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
intrinseca 0:c7beea49fc91 1483 status = pb_decode(&substream, submsg_fields, dest);
intrinseca 0:c7beea49fc91 1484 else
intrinseca 0:c7beea49fc91 1485 status = pb_decode_noinit(&substream, submsg_fields, dest);
intrinseca 0:c7beea49fc91 1486
omatthews 2:d2c61a9be078 1487 if (!pb_close_string_substream(stream, &substream))
omatthews 2:d2c61a9be078 1488 return false;
intrinseca 0:c7beea49fc91 1489 return status;
intrinseca 0:c7beea49fc91 1490 }
omatthews 2:d2c61a9be078 1491
omatthews 2:d2c61a9be078 1492 static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
omatthews 2:d2c61a9be078 1493 {
omatthews 2:d2c61a9be078 1494 uint32_t size;
omatthews 2:d2c61a9be078 1495
omatthews 2:d2c61a9be078 1496 if (!pb_decode_varint32(stream, &size))
omatthews 2:d2c61a9be078 1497 return false;
omatthews 2:d2c61a9be078 1498
omatthews 2:d2c61a9be078 1499 if (size > PB_SIZE_MAX)
omatthews 2:d2c61a9be078 1500 PB_RETURN_ERROR(stream, "bytes overflow");
omatthews 2:d2c61a9be078 1501
omatthews 2:d2c61a9be078 1502 if (size == 0)
omatthews 2:d2c61a9be078 1503 {
omatthews 2:d2c61a9be078 1504 /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */
omatthews 2:d2c61a9be078 1505 memset(dest, 0, field->data_size);
omatthews 2:d2c61a9be078 1506 return true;
omatthews 2:d2c61a9be078 1507 }
omatthews 2:d2c61a9be078 1508
omatthews 2:d2c61a9be078 1509 if (size != field->data_size)
omatthews 2:d2c61a9be078 1510 PB_RETURN_ERROR(stream, "incorrect fixed length bytes size");
omatthews 2:d2c61a9be078 1511
omatthews 2:d2c61a9be078 1512 return pb_read(stream, (pb_byte_t*)dest, field->data_size);
omatthews 2:d2c61a9be078 1513 }