/src/fluent-bit/lib/librdkafka-2.8.0/src/nanopb/pb_common.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. |
2 | | * |
3 | | * 2014 Petteri Aimonen <jpa@kapsi.fi> |
4 | | */ |
5 | | |
6 | | #include "nanopb/pb_common.h" |
7 | | |
8 | | static bool load_descriptor_values(pb_field_iter_t *iter) |
9 | 0 | { |
10 | 0 | uint32_t word0; |
11 | 0 | uint32_t data_offset; |
12 | 0 | int_least8_t size_offset; |
13 | |
|
14 | 0 | if (iter->index >= iter->descriptor->field_count) |
15 | 0 | return false; |
16 | | |
17 | 0 | word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); |
18 | 0 | iter->type = (pb_type_t)((word0 >> 8) & 0xFF); |
19 | |
|
20 | 0 | switch(word0 & 3) |
21 | 0 | { |
22 | 0 | case 0: { |
23 | | /* 1-word format */ |
24 | 0 | iter->array_size = 1; |
25 | 0 | iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); |
26 | 0 | size_offset = (int_least8_t)((word0 >> 24) & 0x0F); |
27 | 0 | data_offset = (word0 >> 16) & 0xFF; |
28 | 0 | iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); |
29 | 0 | break; |
30 | 0 | } |
31 | | |
32 | 0 | case 1: { |
33 | | /* 2-word format */ |
34 | 0 | uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); |
35 | |
|
36 | 0 | iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); |
37 | 0 | iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6)); |
38 | 0 | size_offset = (int_least8_t)((word0 >> 28) & 0x0F); |
39 | 0 | data_offset = word1 & 0xFFFF; |
40 | 0 | iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); |
41 | 0 | break; |
42 | 0 | } |
43 | | |
44 | 0 | case 2: { |
45 | | /* 4-word format */ |
46 | 0 | uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); |
47 | 0 | uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); |
48 | 0 | uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); |
49 | |
|
50 | 0 | iter->array_size = (pb_size_t)(word0 >> 16); |
51 | 0 | iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); |
52 | 0 | size_offset = (int_least8_t)(word1 & 0xFF); |
53 | 0 | data_offset = word2; |
54 | 0 | iter->data_size = (pb_size_t)word3; |
55 | 0 | break; |
56 | 0 | } |
57 | | |
58 | 0 | default: { |
59 | | /* 8-word format */ |
60 | 0 | uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); |
61 | 0 | uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); |
62 | 0 | uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); |
63 | 0 | uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]); |
64 | |
|
65 | 0 | iter->array_size = (pb_size_t)word4; |
66 | 0 | iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); |
67 | 0 | size_offset = (int_least8_t)(word1 & 0xFF); |
68 | 0 | data_offset = word2; |
69 | 0 | iter->data_size = (pb_size_t)word3; |
70 | 0 | break; |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | 0 | if (!iter->message) |
75 | 0 | { |
76 | | /* Avoid doing arithmetic on null pointers, it is undefined */ |
77 | 0 | iter->pField = NULL; |
78 | 0 | iter->pSize = NULL; |
79 | 0 | } |
80 | 0 | else |
81 | 0 | { |
82 | 0 | iter->pField = (char*)iter->message + data_offset; |
83 | |
|
84 | 0 | if (size_offset) |
85 | 0 | { |
86 | 0 | iter->pSize = (char*)iter->pField - size_offset; |
87 | 0 | } |
88 | 0 | else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && |
89 | 0 | (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || |
90 | 0 | PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) |
91 | 0 | { |
92 | | /* Fixed count array */ |
93 | 0 | iter->pSize = &iter->array_size; |
94 | 0 | } |
95 | 0 | else |
96 | 0 | { |
97 | 0 | iter->pSize = NULL; |
98 | 0 | } |
99 | |
|
100 | 0 | if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) |
101 | 0 | { |
102 | 0 | iter->pData = *(void**)iter->pField; |
103 | 0 | } |
104 | 0 | else |
105 | 0 | { |
106 | 0 | iter->pData = iter->pField; |
107 | 0 | } |
108 | 0 | } |
109 | |
|
110 | 0 | if (PB_LTYPE_IS_SUBMSG(iter->type)) |
111 | 0 | { |
112 | 0 | iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index]; |
113 | 0 | } |
114 | 0 | else |
115 | 0 | { |
116 | 0 | iter->submsg_desc = NULL; |
117 | 0 | } |
118 | |
|
119 | 0 | return true; |
120 | 0 | } |
121 | | |
122 | | static void advance_iterator(pb_field_iter_t *iter) |
123 | 0 | { |
124 | 0 | iter->index++; |
125 | |
|
126 | 0 | if (iter->index >= iter->descriptor->field_count) |
127 | 0 | { |
128 | | /* Restart */ |
129 | 0 | iter->index = 0; |
130 | 0 | iter->field_info_index = 0; |
131 | 0 | iter->submessage_index = 0; |
132 | 0 | iter->required_field_index = 0; |
133 | 0 | } |
134 | 0 | else |
135 | 0 | { |
136 | | /* Increment indexes based on previous field type. |
137 | | * All field info formats have the following fields: |
138 | | * - lowest 2 bits tell the amount of words in the descriptor (2^n words) |
139 | | * - bits 2..7 give the lowest bits of tag number. |
140 | | * - bits 8..15 give the field type. |
141 | | */ |
142 | 0 | uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); |
143 | 0 | pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; |
144 | 0 | pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); |
145 | | |
146 | | /* Add to fields. |
147 | | * The cast to pb_size_t is needed to avoid -Wconversion warning. |
148 | | * Because the data is is constants from generator, there is no danger of overflow. |
149 | | */ |
150 | 0 | iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len); |
151 | 0 | iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED)); |
152 | 0 | iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type)); |
153 | 0 | } |
154 | 0 | } |
155 | | |
156 | | bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message) |
157 | 0 | { |
158 | 0 | memset(iter, 0, sizeof(*iter)); |
159 | |
|
160 | 0 | iter->descriptor = desc; |
161 | 0 | iter->message = message; |
162 | |
|
163 | 0 | return load_descriptor_values(iter); |
164 | 0 | } |
165 | | |
166 | | bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension) |
167 | 0 | { |
168 | 0 | const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg; |
169 | 0 | bool status; |
170 | |
|
171 | 0 | uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); |
172 | 0 | if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) |
173 | 0 | { |
174 | | /* For pointer extensions, the pointer is stored directly |
175 | | * in the extension structure. This avoids having an extra |
176 | | * indirection. */ |
177 | 0 | status = pb_field_iter_begin(iter, msg, &extension->dest); |
178 | 0 | } |
179 | 0 | else |
180 | 0 | { |
181 | 0 | status = pb_field_iter_begin(iter, msg, extension->dest); |
182 | 0 | } |
183 | |
|
184 | 0 | iter->pSize = &extension->found; |
185 | 0 | return status; |
186 | 0 | } |
187 | | |
188 | | bool pb_field_iter_next(pb_field_iter_t *iter) |
189 | 0 | { |
190 | 0 | advance_iterator(iter); |
191 | 0 | (void)load_descriptor_values(iter); |
192 | 0 | return iter->index != 0; |
193 | 0 | } |
194 | | |
195 | | bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) |
196 | 0 | { |
197 | 0 | if (iter->tag == tag) |
198 | 0 | { |
199 | 0 | return true; /* Nothing to do, correct field already. */ |
200 | 0 | } |
201 | 0 | else if (tag > iter->descriptor->largest_tag) |
202 | 0 | { |
203 | 0 | return false; |
204 | 0 | } |
205 | 0 | else |
206 | 0 | { |
207 | 0 | pb_size_t start = iter->index; |
208 | 0 | uint32_t fieldinfo; |
209 | |
|
210 | 0 | if (tag < iter->tag) |
211 | 0 | { |
212 | | /* Fields are in tag number order, so we know that tag is between |
213 | | * 0 and our start position. Setting index to end forces |
214 | | * advance_iterator() call below to restart from beginning. */ |
215 | 0 | iter->index = iter->descriptor->field_count; |
216 | 0 | } |
217 | |
|
218 | 0 | do |
219 | 0 | { |
220 | | /* Advance iterator but don't load values yet */ |
221 | 0 | advance_iterator(iter); |
222 | | |
223 | | /* Do fast check for tag number match */ |
224 | 0 | fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); |
225 | |
|
226 | 0 | if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) |
227 | 0 | { |
228 | | /* Good candidate, check further */ |
229 | 0 | (void)load_descriptor_values(iter); |
230 | |
|
231 | 0 | if (iter->tag == tag && |
232 | 0 | PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) |
233 | 0 | { |
234 | | /* Found it */ |
235 | 0 | return true; |
236 | 0 | } |
237 | 0 | } |
238 | 0 | } while (iter->index != start); |
239 | | |
240 | | /* Searched all the way back to start, and found nothing. */ |
241 | 0 | (void)load_descriptor_values(iter); |
242 | 0 | return false; |
243 | 0 | } |
244 | 0 | } |
245 | | |
246 | | bool pb_field_iter_find_extension(pb_field_iter_t *iter) |
247 | 0 | { |
248 | 0 | if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) |
249 | 0 | { |
250 | 0 | return true; |
251 | 0 | } |
252 | 0 | else |
253 | 0 | { |
254 | 0 | pb_size_t start = iter->index; |
255 | 0 | uint32_t fieldinfo; |
256 | |
|
257 | 0 | do |
258 | 0 | { |
259 | | /* Advance iterator but don't load values yet */ |
260 | 0 | advance_iterator(iter); |
261 | | |
262 | | /* Do fast check for field type */ |
263 | 0 | fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); |
264 | |
|
265 | 0 | if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION) |
266 | 0 | { |
267 | 0 | return load_descriptor_values(iter); |
268 | 0 | } |
269 | 0 | } while (iter->index != start); |
270 | | |
271 | | /* Searched all the way back to start, and found nothing. */ |
272 | 0 | (void)load_descriptor_values(iter); |
273 | 0 | return false; |
274 | 0 | } |
275 | 0 | } |
276 | | |
277 | | static void *pb_const_cast(const void *p) |
278 | 0 | { |
279 | | /* Note: this casts away const, in order to use the common field iterator |
280 | | * logic for both encoding and decoding. The cast is done using union |
281 | | * to avoid spurious compiler warnings. */ |
282 | 0 | union { |
283 | 0 | void *p1; |
284 | 0 | const void *p2; |
285 | 0 | } t; |
286 | 0 | t.p2 = p; |
287 | 0 | return t.p1; |
288 | 0 | } |
289 | | |
290 | | bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message) |
291 | 0 | { |
292 | 0 | return pb_field_iter_begin(iter, desc, pb_const_cast(message)); |
293 | 0 | } |
294 | | |
295 | | bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension) |
296 | 0 | { |
297 | 0 | return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension)); |
298 | 0 | } |
299 | | |
300 | | bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) |
301 | 0 | { |
302 | 0 | if (field->data_size == sizeof(pb_callback_t)) |
303 | 0 | { |
304 | 0 | pb_callback_t *pCallback = (pb_callback_t*)field->pData; |
305 | |
|
306 | 0 | if (pCallback != NULL) |
307 | 0 | { |
308 | 0 | if (istream != NULL && pCallback->funcs.decode != NULL) |
309 | 0 | { |
310 | 0 | return pCallback->funcs.decode(istream, field, &pCallback->arg); |
311 | 0 | } |
312 | | |
313 | 0 | if (ostream != NULL && pCallback->funcs.encode != NULL) |
314 | 0 | { |
315 | 0 | return pCallback->funcs.encode(ostream, field, &pCallback->arg); |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | | |
320 | 0 | return true; /* Success, but didn't do anything */ |
321 | |
|
322 | 0 | } |
323 | | |
324 | | #ifdef PB_VALIDATE_UTF8 |
325 | | |
326 | | /* This function checks whether a string is valid UTF-8 text. |
327 | | * |
328 | | * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c |
329 | | * Original copyright: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> 2005-03-30 |
330 | | * Licensed under "Short code license", which allows use under MIT license or |
331 | | * any compatible with it. |
332 | | */ |
333 | | |
334 | | bool pb_validate_utf8(const char *str) |
335 | | { |
336 | | const pb_byte_t *s = (const pb_byte_t*)str; |
337 | | while (*s) |
338 | | { |
339 | | if (*s < 0x80) |
340 | | { |
341 | | /* 0xxxxxxx */ |
342 | | s++; |
343 | | } |
344 | | else if ((s[0] & 0xe0) == 0xc0) |
345 | | { |
346 | | /* 110XXXXx 10xxxxxx */ |
347 | | if ((s[1] & 0xc0) != 0x80 || |
348 | | (s[0] & 0xfe) == 0xc0) /* overlong? */ |
349 | | return false; |
350 | | else |
351 | | s += 2; |
352 | | } |
353 | | else if ((s[0] & 0xf0) == 0xe0) |
354 | | { |
355 | | /* 1110XXXX 10Xxxxxx 10xxxxxx */ |
356 | | if ((s[1] & 0xc0) != 0x80 || |
357 | | (s[2] & 0xc0) != 0x80 || |
358 | | (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ |
359 | | (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ |
360 | | (s[0] == 0xef && s[1] == 0xbf && |
361 | | (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ |
362 | | return false; |
363 | | else |
364 | | s += 3; |
365 | | } |
366 | | else if ((s[0] & 0xf8) == 0xf0) |
367 | | { |
368 | | /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ |
369 | | if ((s[1] & 0xc0) != 0x80 || |
370 | | (s[2] & 0xc0) != 0x80 || |
371 | | (s[3] & 0xc0) != 0x80 || |
372 | | (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ |
373 | | (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ |
374 | | return false; |
375 | | else |
376 | | s += 4; |
377 | | } |
378 | | else |
379 | | { |
380 | | return false; |
381 | | } |
382 | | } |
383 | | |
384 | | return true; |
385 | | } |
386 | | |
387 | | #endif |
388 | | |