1*c8d645caSAndroid Build Coastguard Worker /* Fuzz testing for the nanopb core.
2*c8d645caSAndroid Build Coastguard Worker * Attempts to verify all the properties defined in the security model document.
3*c8d645caSAndroid Build Coastguard Worker */
4*c8d645caSAndroid Build Coastguard Worker
5*c8d645caSAndroid Build Coastguard Worker #include <pb_decode.h>
6*c8d645caSAndroid Build Coastguard Worker #include <pb_encode.h>
7*c8d645caSAndroid Build Coastguard Worker #include <stdio.h>
8*c8d645caSAndroid Build Coastguard Worker #include <stdlib.h>
9*c8d645caSAndroid Build Coastguard Worker #include <string.h>
10*c8d645caSAndroid Build Coastguard Worker #include <assert.h>
11*c8d645caSAndroid Build Coastguard Worker #include <time.h>
12*c8d645caSAndroid Build Coastguard Worker #include <malloc_wrappers.h>
13*c8d645caSAndroid Build Coastguard Worker #include "alltypes_static.pb.h"
14*c8d645caSAndroid Build Coastguard Worker #include "alltypes_pointer.pb.h"
15*c8d645caSAndroid Build Coastguard Worker
16*c8d645caSAndroid Build Coastguard Worker static uint64_t random_seed;
17*c8d645caSAndroid Build Coastguard Worker
18*c8d645caSAndroid Build Coastguard Worker /* Uses xorshift64 here instead of rand() for both speed and
19*c8d645caSAndroid Build Coastguard Worker * reproducibility across platforms. */
rand_word()20*c8d645caSAndroid Build Coastguard Worker static uint32_t rand_word()
21*c8d645caSAndroid Build Coastguard Worker {
22*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed >> 12;
23*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed << 25;
24*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed >> 27;
25*c8d645caSAndroid Build Coastguard Worker return random_seed * 2685821657736338717ULL;
26*c8d645caSAndroid Build Coastguard Worker }
27*c8d645caSAndroid Build Coastguard Worker
28*c8d645caSAndroid Build Coastguard Worker /* Get a random integer in range, with approximately flat distribution. */
rand_int(int min,int max)29*c8d645caSAndroid Build Coastguard Worker static int rand_int(int min, int max)
30*c8d645caSAndroid Build Coastguard Worker {
31*c8d645caSAndroid Build Coastguard Worker return rand_word() % (max + 1 - min) + min;
32*c8d645caSAndroid Build Coastguard Worker }
33*c8d645caSAndroid Build Coastguard Worker
rand_bool()34*c8d645caSAndroid Build Coastguard Worker static bool rand_bool()
35*c8d645caSAndroid Build Coastguard Worker {
36*c8d645caSAndroid Build Coastguard Worker return rand_word() & 1;
37*c8d645caSAndroid Build Coastguard Worker }
38*c8d645caSAndroid Build Coastguard Worker
39*c8d645caSAndroid Build Coastguard Worker /* Get a random byte, with skewed distribution.
40*c8d645caSAndroid Build Coastguard Worker * Important corner cases like 0xFF, 0x00 and 0xFE occur more
41*c8d645caSAndroid Build Coastguard Worker * often than other values. */
rand_byte()42*c8d645caSAndroid Build Coastguard Worker static uint8_t rand_byte()
43*c8d645caSAndroid Build Coastguard Worker {
44*c8d645caSAndroid Build Coastguard Worker uint32_t w = rand_word();
45*c8d645caSAndroid Build Coastguard Worker uint8_t b = w & 0xFF;
46*c8d645caSAndroid Build Coastguard Worker if (w & 0x100000)
47*c8d645caSAndroid Build Coastguard Worker b >>= (w >> 8) & 7;
48*c8d645caSAndroid Build Coastguard Worker if (w & 0x200000)
49*c8d645caSAndroid Build Coastguard Worker b <<= (w >> 12) & 7;
50*c8d645caSAndroid Build Coastguard Worker if (w & 0x400000)
51*c8d645caSAndroid Build Coastguard Worker b ^= 0xFF;
52*c8d645caSAndroid Build Coastguard Worker return b;
53*c8d645caSAndroid Build Coastguard Worker }
54*c8d645caSAndroid Build Coastguard Worker
55*c8d645caSAndroid Build Coastguard Worker /* Get a random length, with skewed distribution.
56*c8d645caSAndroid Build Coastguard Worker * Favors the shorter lengths, but always atleast 1. */
rand_len(size_t max)57*c8d645caSAndroid Build Coastguard Worker static size_t rand_len(size_t max)
58*c8d645caSAndroid Build Coastguard Worker {
59*c8d645caSAndroid Build Coastguard Worker uint32_t w = rand_word();
60*c8d645caSAndroid Build Coastguard Worker size_t s;
61*c8d645caSAndroid Build Coastguard Worker if (w & 0x800000)
62*c8d645caSAndroid Build Coastguard Worker w &= 3;
63*c8d645caSAndroid Build Coastguard Worker else if (w & 0x400000)
64*c8d645caSAndroid Build Coastguard Worker w &= 15;
65*c8d645caSAndroid Build Coastguard Worker else if (w & 0x200000)
66*c8d645caSAndroid Build Coastguard Worker w &= 255;
67*c8d645caSAndroid Build Coastguard Worker
68*c8d645caSAndroid Build Coastguard Worker s = (w % max);
69*c8d645caSAndroid Build Coastguard Worker if (s == 0)
70*c8d645caSAndroid Build Coastguard Worker s = 1;
71*c8d645caSAndroid Build Coastguard Worker
72*c8d645caSAndroid Build Coastguard Worker return s;
73*c8d645caSAndroid Build Coastguard Worker }
74*c8d645caSAndroid Build Coastguard Worker
75*c8d645caSAndroid Build Coastguard Worker /* Fills a buffer with random data with skewed distribution. */
rand_fill(uint8_t * buf,size_t count)76*c8d645caSAndroid Build Coastguard Worker static void rand_fill(uint8_t *buf, size_t count)
77*c8d645caSAndroid Build Coastguard Worker {
78*c8d645caSAndroid Build Coastguard Worker while (count--)
79*c8d645caSAndroid Build Coastguard Worker *buf++ = rand_byte();
80*c8d645caSAndroid Build Coastguard Worker }
81*c8d645caSAndroid Build Coastguard Worker
82*c8d645caSAndroid Build Coastguard Worker /* Fill with random protobuf-like data */
rand_fill_protobuf(uint8_t * buf,size_t min_bytes,size_t max_bytes,int min_tag)83*c8d645caSAndroid Build Coastguard Worker static size_t rand_fill_protobuf(uint8_t *buf, size_t min_bytes, size_t max_bytes, int min_tag)
84*c8d645caSAndroid Build Coastguard Worker {
85*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf, max_bytes);
86*c8d645caSAndroid Build Coastguard Worker
87*c8d645caSAndroid Build Coastguard Worker while(stream.bytes_written < min_bytes)
88*c8d645caSAndroid Build Coastguard Worker {
89*c8d645caSAndroid Build Coastguard Worker pb_wire_type_t wt = rand_int(0, 3);
90*c8d645caSAndroid Build Coastguard Worker if (wt == 3) wt = 5; /* Gap in values */
91*c8d645caSAndroid Build Coastguard Worker
92*c8d645caSAndroid Build Coastguard Worker if (!pb_encode_tag(&stream, wt, rand_int(min_tag, min_tag + 512)))
93*c8d645caSAndroid Build Coastguard Worker break;
94*c8d645caSAndroid Build Coastguard Worker
95*c8d645caSAndroid Build Coastguard Worker if (wt == PB_WT_VARINT)
96*c8d645caSAndroid Build Coastguard Worker {
97*c8d645caSAndroid Build Coastguard Worker uint64_t value;
98*c8d645caSAndroid Build Coastguard Worker rand_fill((uint8_t*)&value, sizeof(value));
99*c8d645caSAndroid Build Coastguard Worker pb_encode_varint(&stream, value);
100*c8d645caSAndroid Build Coastguard Worker }
101*c8d645caSAndroid Build Coastguard Worker else if (wt == PB_WT_64BIT)
102*c8d645caSAndroid Build Coastguard Worker {
103*c8d645caSAndroid Build Coastguard Worker uint64_t value;
104*c8d645caSAndroid Build Coastguard Worker rand_fill((uint8_t*)&value, sizeof(value));
105*c8d645caSAndroid Build Coastguard Worker pb_encode_fixed64(&stream, &value);
106*c8d645caSAndroid Build Coastguard Worker }
107*c8d645caSAndroid Build Coastguard Worker else if (wt == PB_WT_32BIT)
108*c8d645caSAndroid Build Coastguard Worker {
109*c8d645caSAndroid Build Coastguard Worker uint32_t value;
110*c8d645caSAndroid Build Coastguard Worker rand_fill((uint8_t*)&value, sizeof(value));
111*c8d645caSAndroid Build Coastguard Worker pb_encode_fixed32(&stream, &value);
112*c8d645caSAndroid Build Coastguard Worker }
113*c8d645caSAndroid Build Coastguard Worker else if (wt == PB_WT_STRING)
114*c8d645caSAndroid Build Coastguard Worker {
115*c8d645caSAndroid Build Coastguard Worker size_t len;
116*c8d645caSAndroid Build Coastguard Worker uint8_t *buf;
117*c8d645caSAndroid Build Coastguard Worker
118*c8d645caSAndroid Build Coastguard Worker if (min_bytes > stream.bytes_written)
119*c8d645caSAndroid Build Coastguard Worker len = rand_len(min_bytes - stream.bytes_written);
120*c8d645caSAndroid Build Coastguard Worker else
121*c8d645caSAndroid Build Coastguard Worker len = 0;
122*c8d645caSAndroid Build Coastguard Worker
123*c8d645caSAndroid Build Coastguard Worker buf = malloc(len);
124*c8d645caSAndroid Build Coastguard Worker pb_encode_varint(&stream, len);
125*c8d645caSAndroid Build Coastguard Worker rand_fill(buf, len);
126*c8d645caSAndroid Build Coastguard Worker pb_write(&stream, buf, len);
127*c8d645caSAndroid Build Coastguard Worker free(buf);
128*c8d645caSAndroid Build Coastguard Worker }
129*c8d645caSAndroid Build Coastguard Worker }
130*c8d645caSAndroid Build Coastguard Worker
131*c8d645caSAndroid Build Coastguard Worker return stream.bytes_written;
132*c8d645caSAndroid Build Coastguard Worker }
133*c8d645caSAndroid Build Coastguard Worker
134*c8d645caSAndroid Build Coastguard Worker /* Given a buffer of data, mess it up a bit */
rand_mess(uint8_t * buf,size_t count)135*c8d645caSAndroid Build Coastguard Worker static void rand_mess(uint8_t *buf, size_t count)
136*c8d645caSAndroid Build Coastguard Worker {
137*c8d645caSAndroid Build Coastguard Worker int m = rand_int(0, 3);
138*c8d645caSAndroid Build Coastguard Worker
139*c8d645caSAndroid Build Coastguard Worker if (m == 0)
140*c8d645caSAndroid Build Coastguard Worker {
141*c8d645caSAndroid Build Coastguard Worker /* Replace random substring */
142*c8d645caSAndroid Build Coastguard Worker int s = rand_int(0, count - 1);
143*c8d645caSAndroid Build Coastguard Worker int l = rand_len(count - s);
144*c8d645caSAndroid Build Coastguard Worker rand_fill(buf + s, l);
145*c8d645caSAndroid Build Coastguard Worker }
146*c8d645caSAndroid Build Coastguard Worker else if (m == 1)
147*c8d645caSAndroid Build Coastguard Worker {
148*c8d645caSAndroid Build Coastguard Worker /* Swap random bytes */
149*c8d645caSAndroid Build Coastguard Worker int a = rand_int(0, count - 1);
150*c8d645caSAndroid Build Coastguard Worker int b = rand_int(0, count - 1);
151*c8d645caSAndroid Build Coastguard Worker int x = buf[a];
152*c8d645caSAndroid Build Coastguard Worker buf[a] = buf[b];
153*c8d645caSAndroid Build Coastguard Worker buf[b] = x;
154*c8d645caSAndroid Build Coastguard Worker }
155*c8d645caSAndroid Build Coastguard Worker else if (m == 2)
156*c8d645caSAndroid Build Coastguard Worker {
157*c8d645caSAndroid Build Coastguard Worker /* Duplicate substring */
158*c8d645caSAndroid Build Coastguard Worker int s = rand_int(0, count - 2);
159*c8d645caSAndroid Build Coastguard Worker int l = rand_len((count - s) / 2);
160*c8d645caSAndroid Build Coastguard Worker memcpy(buf + s + l, buf + s, l);
161*c8d645caSAndroid Build Coastguard Worker }
162*c8d645caSAndroid Build Coastguard Worker else if (m == 3)
163*c8d645caSAndroid Build Coastguard Worker {
164*c8d645caSAndroid Build Coastguard Worker /* Add random protobuf noise */
165*c8d645caSAndroid Build Coastguard Worker int s = rand_int(0, count - 1);
166*c8d645caSAndroid Build Coastguard Worker int l = rand_len(count - s);
167*c8d645caSAndroid Build Coastguard Worker rand_fill_protobuf(buf + s, l, count - s, 1);
168*c8d645caSAndroid Build Coastguard Worker }
169*c8d645caSAndroid Build Coastguard Worker }
170*c8d645caSAndroid Build Coastguard Worker
171*c8d645caSAndroid Build Coastguard Worker /* Some default data to put in the message */
172*c8d645caSAndroid Build Coastguard Worker static const alltypes_static_AllTypes initval = alltypes_static_AllTypes_init_default;
173*c8d645caSAndroid Build Coastguard Worker
174*c8d645caSAndroid Build Coastguard Worker /* Check the invariants defined in security model on decoded structure */
sanity_check_static(alltypes_static_AllTypes * msg)175*c8d645caSAndroid Build Coastguard Worker static void sanity_check_static(alltypes_static_AllTypes *msg)
176*c8d645caSAndroid Build Coastguard Worker {
177*c8d645caSAndroid Build Coastguard Worker bool truebool = true;
178*c8d645caSAndroid Build Coastguard Worker bool falsebool = false;
179*c8d645caSAndroid Build Coastguard Worker
180*c8d645caSAndroid Build Coastguard Worker /* TODO: Add more checks, or rather, generate them automatically */
181*c8d645caSAndroid Build Coastguard Worker assert(strlen(msg->req_string) < sizeof(msg->req_string));
182*c8d645caSAndroid Build Coastguard Worker assert(strlen(msg->opt_string) < sizeof(msg->opt_string));
183*c8d645caSAndroid Build Coastguard Worker if (msg->rep_string_count > 0)
184*c8d645caSAndroid Build Coastguard Worker {
185*c8d645caSAndroid Build Coastguard Worker assert(strlen(msg->rep_string[0]) < sizeof(msg->rep_string[0]));
186*c8d645caSAndroid Build Coastguard Worker }
187*c8d645caSAndroid Build Coastguard Worker assert(memcmp(&msg->req_bool, &truebool, sizeof(bool)) == 0 ||
188*c8d645caSAndroid Build Coastguard Worker memcmp(&msg->req_bool, &falsebool, sizeof(bool)) == 0);
189*c8d645caSAndroid Build Coastguard Worker assert(memcmp(&msg->has_opt_bool, &truebool, sizeof(bool)) == 0 ||
190*c8d645caSAndroid Build Coastguard Worker memcmp(&msg->has_opt_bool, &falsebool, sizeof(bool)) == 0);
191*c8d645caSAndroid Build Coastguard Worker assert(memcmp(&msg->opt_bool, &truebool, sizeof(bool)) == 0 ||
192*c8d645caSAndroid Build Coastguard Worker memcmp(&msg->opt_bool, &falsebool, sizeof(bool)) == 0);
193*c8d645caSAndroid Build Coastguard Worker assert(msg->rep_bool_count <= pb_arraysize(alltypes_static_AllTypes, rep_bool));
194*c8d645caSAndroid Build Coastguard Worker if (msg->rep_bool_count > 0)
195*c8d645caSAndroid Build Coastguard Worker {
196*c8d645caSAndroid Build Coastguard Worker assert(memcmp(&msg->rep_bool[0], &truebool, sizeof(bool)) == 0 ||
197*c8d645caSAndroid Build Coastguard Worker memcmp(&msg->rep_bool[0], &falsebool, sizeof(bool)) == 0);
198*c8d645caSAndroid Build Coastguard Worker }
199*c8d645caSAndroid Build Coastguard Worker }
200*c8d645caSAndroid Build Coastguard Worker
201*c8d645caSAndroid Build Coastguard Worker #define BUFSIZE 4096
202*c8d645caSAndroid Build Coastguard Worker
do_static_encode(uint8_t * buffer,size_t * msglen)203*c8d645caSAndroid Build Coastguard Worker static bool do_static_encode(uint8_t *buffer, size_t *msglen)
204*c8d645caSAndroid Build Coastguard Worker {
205*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream;
206*c8d645caSAndroid Build Coastguard Worker bool status;
207*c8d645caSAndroid Build Coastguard Worker
208*c8d645caSAndroid Build Coastguard Worker /* Allocate a message and fill it with defaults */
209*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg = malloc_with_check(sizeof(alltypes_static_AllTypes));
210*c8d645caSAndroid Build Coastguard Worker memcpy(msg, &initval, sizeof(initval));
211*c8d645caSAndroid Build Coastguard Worker
212*c8d645caSAndroid Build Coastguard Worker /* Apply randomness to the data before encoding */
213*c8d645caSAndroid Build Coastguard Worker while (rand_int(0, 7))
214*c8d645caSAndroid Build Coastguard Worker rand_mess((uint8_t*)msg, sizeof(alltypes_static_AllTypes));
215*c8d645caSAndroid Build Coastguard Worker
216*c8d645caSAndroid Build Coastguard Worker stream = pb_ostream_from_buffer(buffer, BUFSIZE);
217*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg);
218*c8d645caSAndroid Build Coastguard Worker assert(stream.bytes_written <= BUFSIZE);
219*c8d645caSAndroid Build Coastguard Worker assert(stream.bytes_written <= alltypes_static_AllTypes_size);
220*c8d645caSAndroid Build Coastguard Worker
221*c8d645caSAndroid Build Coastguard Worker *msglen = stream.bytes_written;
222*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_static_AllTypes_fields, msg);
223*c8d645caSAndroid Build Coastguard Worker free_with_check(msg);
224*c8d645caSAndroid Build Coastguard Worker
225*c8d645caSAndroid Build Coastguard Worker return status;
226*c8d645caSAndroid Build Coastguard Worker }
227*c8d645caSAndroid Build Coastguard Worker
228*c8d645caSAndroid Build Coastguard Worker /* Append or prepend protobuf noise */
do_protobuf_noise(uint8_t * buffer,size_t * msglen)229*c8d645caSAndroid Build Coastguard Worker static void do_protobuf_noise(uint8_t *buffer, size_t *msglen)
230*c8d645caSAndroid Build Coastguard Worker {
231*c8d645caSAndroid Build Coastguard Worker int m = rand_int(0, 2);
232*c8d645caSAndroid Build Coastguard Worker size_t max_size = BUFSIZE - 32 - *msglen;
233*c8d645caSAndroid Build Coastguard Worker if (m == 1)
234*c8d645caSAndroid Build Coastguard Worker {
235*c8d645caSAndroid Build Coastguard Worker /* Prepend */
236*c8d645caSAndroid Build Coastguard Worker uint8_t *tmp = malloc_with_check(BUFSIZE);
237*c8d645caSAndroid Build Coastguard Worker size_t s = rand_fill_protobuf(tmp, rand_len(max_size), BUFSIZE - *msglen, 512);
238*c8d645caSAndroid Build Coastguard Worker memmove(buffer + s, buffer, *msglen);
239*c8d645caSAndroid Build Coastguard Worker memcpy(buffer, tmp, s);
240*c8d645caSAndroid Build Coastguard Worker free_with_check(tmp);
241*c8d645caSAndroid Build Coastguard Worker *msglen += s;
242*c8d645caSAndroid Build Coastguard Worker }
243*c8d645caSAndroid Build Coastguard Worker else if (m == 2)
244*c8d645caSAndroid Build Coastguard Worker {
245*c8d645caSAndroid Build Coastguard Worker /* Append */
246*c8d645caSAndroid Build Coastguard Worker size_t s = rand_fill_protobuf(buffer + *msglen, rand_len(max_size), BUFSIZE - *msglen, 512);
247*c8d645caSAndroid Build Coastguard Worker *msglen += s;
248*c8d645caSAndroid Build Coastguard Worker }
249*c8d645caSAndroid Build Coastguard Worker }
250*c8d645caSAndroid Build Coastguard Worker
do_static_decode(uint8_t * buffer,size_t msglen,bool assert_success)251*c8d645caSAndroid Build Coastguard Worker static bool do_static_decode(uint8_t *buffer, size_t msglen, bool assert_success)
252*c8d645caSAndroid Build Coastguard Worker {
253*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream;
254*c8d645caSAndroid Build Coastguard Worker bool status;
255*c8d645caSAndroid Build Coastguard Worker
256*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg = malloc_with_check(sizeof(alltypes_static_AllTypes));
257*c8d645caSAndroid Build Coastguard Worker rand_fill((uint8_t*)msg, sizeof(alltypes_static_AllTypes));
258*c8d645caSAndroid Build Coastguard Worker stream = pb_istream_from_buffer(buffer, msglen);
259*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg);
260*c8d645caSAndroid Build Coastguard Worker
261*c8d645caSAndroid Build Coastguard Worker if (status)
262*c8d645caSAndroid Build Coastguard Worker {
263*c8d645caSAndroid Build Coastguard Worker sanity_check_static(msg);
264*c8d645caSAndroid Build Coastguard Worker }
265*c8d645caSAndroid Build Coastguard Worker
266*c8d645caSAndroid Build Coastguard Worker if (!status && assert_success)
267*c8d645caSAndroid Build Coastguard Worker {
268*c8d645caSAndroid Build Coastguard Worker /* Anything that was successfully encoded, should be decodeable.
269*c8d645caSAndroid Build Coastguard Worker * One exception: strings without null terminator are encoded up
270*c8d645caSAndroid Build Coastguard Worker * to end of buffer, but refused on decode because the terminator
271*c8d645caSAndroid Build Coastguard Worker * would not fit. */
272*c8d645caSAndroid Build Coastguard Worker if (strcmp(stream.errmsg, "string overflow") != 0)
273*c8d645caSAndroid Build Coastguard Worker assert(status);
274*c8d645caSAndroid Build Coastguard Worker }
275*c8d645caSAndroid Build Coastguard Worker
276*c8d645caSAndroid Build Coastguard Worker free_with_check(msg);
277*c8d645caSAndroid Build Coastguard Worker return status;
278*c8d645caSAndroid Build Coastguard Worker }
279*c8d645caSAndroid Build Coastguard Worker
do_pointer_decode(uint8_t * buffer,size_t msglen,bool assert_success)280*c8d645caSAndroid Build Coastguard Worker static bool do_pointer_decode(uint8_t *buffer, size_t msglen, bool assert_success)
281*c8d645caSAndroid Build Coastguard Worker {
282*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream;
283*c8d645caSAndroid Build Coastguard Worker bool status;
284*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg;
285*c8d645caSAndroid Build Coastguard Worker
286*c8d645caSAndroid Build Coastguard Worker msg = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
287*c8d645caSAndroid Build Coastguard Worker memset(msg, 0, sizeof(alltypes_pointer_AllTypes));
288*c8d645caSAndroid Build Coastguard Worker stream = pb_istream_from_buffer(buffer, msglen);
289*c8d645caSAndroid Build Coastguard Worker
290*c8d645caSAndroid Build Coastguard Worker assert(get_alloc_count() == 0);
291*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg);
292*c8d645caSAndroid Build Coastguard Worker
293*c8d645caSAndroid Build Coastguard Worker if (assert_success)
294*c8d645caSAndroid Build Coastguard Worker assert(status);
295*c8d645caSAndroid Build Coastguard Worker
296*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg);
297*c8d645caSAndroid Build Coastguard Worker assert(get_alloc_count() == 0);
298*c8d645caSAndroid Build Coastguard Worker
299*c8d645caSAndroid Build Coastguard Worker free_with_check(msg);
300*c8d645caSAndroid Build Coastguard Worker
301*c8d645caSAndroid Build Coastguard Worker return status;
302*c8d645caSAndroid Build Coastguard Worker }
303*c8d645caSAndroid Build Coastguard Worker
304*c8d645caSAndroid Build Coastguard Worker /* Do a decode -> encode -> decode -> encode roundtrip */
do_static_roundtrip(uint8_t * buffer,size_t msglen)305*c8d645caSAndroid Build Coastguard Worker static void do_static_roundtrip(uint8_t *buffer, size_t msglen)
306*c8d645caSAndroid Build Coastguard Worker {
307*c8d645caSAndroid Build Coastguard Worker bool status;
308*c8d645caSAndroid Build Coastguard Worker uint8_t *buf2 = malloc_with_check(BUFSIZE);
309*c8d645caSAndroid Build Coastguard Worker uint8_t *buf3 = malloc_with_check(BUFSIZE);
310*c8d645caSAndroid Build Coastguard Worker size_t msglen2, msglen3;
311*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_static_AllTypes));
312*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_static_AllTypes));
313*c8d645caSAndroid Build Coastguard Worker memset(msg1, 0, sizeof(alltypes_static_AllTypes));
314*c8d645caSAndroid Build Coastguard Worker memset(msg2, 0, sizeof(alltypes_static_AllTypes));
315*c8d645caSAndroid Build Coastguard Worker
316*c8d645caSAndroid Build Coastguard Worker {
317*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
318*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg1);
319*c8d645caSAndroid Build Coastguard Worker assert(status);
320*c8d645caSAndroid Build Coastguard Worker sanity_check_static(msg1);
321*c8d645caSAndroid Build Coastguard Worker }
322*c8d645caSAndroid Build Coastguard Worker
323*c8d645caSAndroid Build Coastguard Worker {
324*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
325*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg1);
326*c8d645caSAndroid Build Coastguard Worker assert(status);
327*c8d645caSAndroid Build Coastguard Worker msglen2 = stream.bytes_written;
328*c8d645caSAndroid Build Coastguard Worker }
329*c8d645caSAndroid Build Coastguard Worker
330*c8d645caSAndroid Build Coastguard Worker {
331*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
332*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg2);
333*c8d645caSAndroid Build Coastguard Worker assert(status);
334*c8d645caSAndroid Build Coastguard Worker sanity_check_static(msg2);
335*c8d645caSAndroid Build Coastguard Worker }
336*c8d645caSAndroid Build Coastguard Worker
337*c8d645caSAndroid Build Coastguard Worker {
338*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
339*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg2);
340*c8d645caSAndroid Build Coastguard Worker assert(status);
341*c8d645caSAndroid Build Coastguard Worker msglen3 = stream.bytes_written;
342*c8d645caSAndroid Build Coastguard Worker }
343*c8d645caSAndroid Build Coastguard Worker
344*c8d645caSAndroid Build Coastguard Worker assert(msglen2 == msglen3);
345*c8d645caSAndroid Build Coastguard Worker assert(memcmp(buf2, buf3, msglen2) == 0);
346*c8d645caSAndroid Build Coastguard Worker
347*c8d645caSAndroid Build Coastguard Worker free_with_check(msg1);
348*c8d645caSAndroid Build Coastguard Worker free_with_check(msg2);
349*c8d645caSAndroid Build Coastguard Worker free_with_check(buf2);
350*c8d645caSAndroid Build Coastguard Worker free_with_check(buf3);
351*c8d645caSAndroid Build Coastguard Worker }
352*c8d645caSAndroid Build Coastguard Worker
353*c8d645caSAndroid Build Coastguard Worker /* Do decode -> encode -> decode -> encode roundtrip */
do_pointer_roundtrip(uint8_t * buffer,size_t msglen)354*c8d645caSAndroid Build Coastguard Worker static void do_pointer_roundtrip(uint8_t *buffer, size_t msglen)
355*c8d645caSAndroid Build Coastguard Worker {
356*c8d645caSAndroid Build Coastguard Worker bool status;
357*c8d645caSAndroid Build Coastguard Worker uint8_t *buf2 = malloc_with_check(BUFSIZE);
358*c8d645caSAndroid Build Coastguard Worker uint8_t *buf3 = malloc_with_check(BUFSIZE);
359*c8d645caSAndroid Build Coastguard Worker size_t msglen2, msglen3;
360*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
361*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
362*c8d645caSAndroid Build Coastguard Worker memset(msg1, 0, sizeof(alltypes_pointer_AllTypes));
363*c8d645caSAndroid Build Coastguard Worker memset(msg2, 0, sizeof(alltypes_pointer_AllTypes));
364*c8d645caSAndroid Build Coastguard Worker
365*c8d645caSAndroid Build Coastguard Worker {
366*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
367*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg1);
368*c8d645caSAndroid Build Coastguard Worker assert(status);
369*c8d645caSAndroid Build Coastguard Worker }
370*c8d645caSAndroid Build Coastguard Worker
371*c8d645caSAndroid Build Coastguard Worker {
372*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
373*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg1);
374*c8d645caSAndroid Build Coastguard Worker assert(status);
375*c8d645caSAndroid Build Coastguard Worker msglen2 = stream.bytes_written;
376*c8d645caSAndroid Build Coastguard Worker }
377*c8d645caSAndroid Build Coastguard Worker
378*c8d645caSAndroid Build Coastguard Worker {
379*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
380*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg2);
381*c8d645caSAndroid Build Coastguard Worker assert(status);
382*c8d645caSAndroid Build Coastguard Worker }
383*c8d645caSAndroid Build Coastguard Worker
384*c8d645caSAndroid Build Coastguard Worker {
385*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
386*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg2);
387*c8d645caSAndroid Build Coastguard Worker assert(status);
388*c8d645caSAndroid Build Coastguard Worker msglen3 = stream.bytes_written;
389*c8d645caSAndroid Build Coastguard Worker }
390*c8d645caSAndroid Build Coastguard Worker
391*c8d645caSAndroid Build Coastguard Worker assert(msglen2 == msglen3);
392*c8d645caSAndroid Build Coastguard Worker assert(memcmp(buf2, buf3, msglen2) == 0);
393*c8d645caSAndroid Build Coastguard Worker
394*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg1);
395*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg2);
396*c8d645caSAndroid Build Coastguard Worker free_with_check(msg1);
397*c8d645caSAndroid Build Coastguard Worker free_with_check(msg2);
398*c8d645caSAndroid Build Coastguard Worker free_with_check(buf2);
399*c8d645caSAndroid Build Coastguard Worker free_with_check(buf3);
400*c8d645caSAndroid Build Coastguard Worker }
401*c8d645caSAndroid Build Coastguard Worker
run_iteration()402*c8d645caSAndroid Build Coastguard Worker static void run_iteration()
403*c8d645caSAndroid Build Coastguard Worker {
404*c8d645caSAndroid Build Coastguard Worker uint8_t *buffer = malloc_with_check(BUFSIZE);
405*c8d645caSAndroid Build Coastguard Worker size_t msglen;
406*c8d645caSAndroid Build Coastguard Worker bool status;
407*c8d645caSAndroid Build Coastguard Worker
408*c8d645caSAndroid Build Coastguard Worker rand_fill(buffer, BUFSIZE);
409*c8d645caSAndroid Build Coastguard Worker
410*c8d645caSAndroid Build Coastguard Worker if (do_static_encode(buffer, &msglen))
411*c8d645caSAndroid Build Coastguard Worker {
412*c8d645caSAndroid Build Coastguard Worker do_protobuf_noise(buffer, &msglen);
413*c8d645caSAndroid Build Coastguard Worker
414*c8d645caSAndroid Build Coastguard Worker status = do_static_decode(buffer, msglen, true);
415*c8d645caSAndroid Build Coastguard Worker
416*c8d645caSAndroid Build Coastguard Worker if (status)
417*c8d645caSAndroid Build Coastguard Worker do_static_roundtrip(buffer, msglen);
418*c8d645caSAndroid Build Coastguard Worker
419*c8d645caSAndroid Build Coastguard Worker status = do_pointer_decode(buffer, msglen, true);
420*c8d645caSAndroid Build Coastguard Worker
421*c8d645caSAndroid Build Coastguard Worker if (status)
422*c8d645caSAndroid Build Coastguard Worker do_pointer_roundtrip(buffer, msglen);
423*c8d645caSAndroid Build Coastguard Worker
424*c8d645caSAndroid Build Coastguard Worker /* Apply randomness to the encoded data */
425*c8d645caSAndroid Build Coastguard Worker while (rand_bool())
426*c8d645caSAndroid Build Coastguard Worker rand_mess(buffer, BUFSIZE);
427*c8d645caSAndroid Build Coastguard Worker
428*c8d645caSAndroid Build Coastguard Worker /* Apply randomness to encoded data length */
429*c8d645caSAndroid Build Coastguard Worker if (rand_bool())
430*c8d645caSAndroid Build Coastguard Worker msglen = rand_int(0, BUFSIZE);
431*c8d645caSAndroid Build Coastguard Worker
432*c8d645caSAndroid Build Coastguard Worker status = do_static_decode(buffer, msglen, false);
433*c8d645caSAndroid Build Coastguard Worker do_pointer_decode(buffer, msglen, status);
434*c8d645caSAndroid Build Coastguard Worker
435*c8d645caSAndroid Build Coastguard Worker if (status)
436*c8d645caSAndroid Build Coastguard Worker {
437*c8d645caSAndroid Build Coastguard Worker do_static_roundtrip(buffer, msglen);
438*c8d645caSAndroid Build Coastguard Worker do_pointer_roundtrip(buffer, msglen);
439*c8d645caSAndroid Build Coastguard Worker }
440*c8d645caSAndroid Build Coastguard Worker }
441*c8d645caSAndroid Build Coastguard Worker
442*c8d645caSAndroid Build Coastguard Worker free_with_check(buffer);
443*c8d645caSAndroid Build Coastguard Worker }
444*c8d645caSAndroid Build Coastguard Worker
main(int argc,char ** argv)445*c8d645caSAndroid Build Coastguard Worker int main(int argc, char **argv)
446*c8d645caSAndroid Build Coastguard Worker {
447*c8d645caSAndroid Build Coastguard Worker int i;
448*c8d645caSAndroid Build Coastguard Worker if (argc > 1)
449*c8d645caSAndroid Build Coastguard Worker {
450*c8d645caSAndroid Build Coastguard Worker random_seed = atol(argv[1]);
451*c8d645caSAndroid Build Coastguard Worker }
452*c8d645caSAndroid Build Coastguard Worker else
453*c8d645caSAndroid Build Coastguard Worker {
454*c8d645caSAndroid Build Coastguard Worker random_seed = time(NULL);
455*c8d645caSAndroid Build Coastguard Worker }
456*c8d645caSAndroid Build Coastguard Worker
457*c8d645caSAndroid Build Coastguard Worker fprintf(stderr, "Random seed: %llu\n", (long long unsigned)random_seed);
458*c8d645caSAndroid Build Coastguard Worker
459*c8d645caSAndroid Build Coastguard Worker for (i = 0; i < 10000; i++)
460*c8d645caSAndroid Build Coastguard Worker {
461*c8d645caSAndroid Build Coastguard Worker run_iteration();
462*c8d645caSAndroid Build Coastguard Worker }
463*c8d645caSAndroid Build Coastguard Worker
464*c8d645caSAndroid Build Coastguard Worker return 0;
465*c8d645caSAndroid Build Coastguard Worker }
466*c8d645caSAndroid Build Coastguard Worker
467