1*c8d645caSAndroid Build Coastguard Worker /* Fuzz testing for the nanopb core.
2*c8d645caSAndroid Build Coastguard Worker * This can be used with external fuzzers, e.g. radamsa.
3*c8d645caSAndroid Build Coastguard Worker * It performs most of the same checks as fuzztest, but does not feature data generation.
4*c8d645caSAndroid Build Coastguard Worker */
5*c8d645caSAndroid Build Coastguard Worker
6*c8d645caSAndroid Build Coastguard Worker #include <pb_decode.h>
7*c8d645caSAndroid Build Coastguard Worker #include <pb_encode.h>
8*c8d645caSAndroid Build Coastguard Worker #include <stdio.h>
9*c8d645caSAndroid Build Coastguard Worker #include <stdlib.h>
10*c8d645caSAndroid Build Coastguard Worker #include <string.h>
11*c8d645caSAndroid Build Coastguard Worker #include <assert.h>
12*c8d645caSAndroid Build Coastguard Worker #include <time.h>
13*c8d645caSAndroid Build Coastguard Worker #include <malloc_wrappers.h>
14*c8d645caSAndroid Build Coastguard Worker #include "alltypes_static.pb.h"
15*c8d645caSAndroid Build Coastguard Worker #include "alltypes_pointer.pb.h"
16*c8d645caSAndroid Build Coastguard Worker
17*c8d645caSAndroid Build Coastguard Worker #define BUFSIZE 4096
18*c8d645caSAndroid Build Coastguard Worker
do_static_decode(uint8_t * buffer,size_t msglen,bool assert_success)19*c8d645caSAndroid Build Coastguard Worker static bool do_static_decode(uint8_t *buffer, size_t msglen, bool assert_success)
20*c8d645caSAndroid Build Coastguard Worker {
21*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream;
22*c8d645caSAndroid Build Coastguard Worker bool status;
23*c8d645caSAndroid Build Coastguard Worker
24*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg = malloc_with_check(sizeof(alltypes_static_AllTypes));
25*c8d645caSAndroid Build Coastguard Worker stream = pb_istream_from_buffer(buffer, msglen);
26*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg);
27*c8d645caSAndroid Build Coastguard Worker
28*c8d645caSAndroid Build Coastguard Worker if (!status && assert_success)
29*c8d645caSAndroid Build Coastguard Worker {
30*c8d645caSAndroid Build Coastguard Worker /* Anything that was successfully encoded, should be decodeable.
31*c8d645caSAndroid Build Coastguard Worker * One exception: strings without null terminator are encoded up
32*c8d645caSAndroid Build Coastguard Worker * to end of buffer, but refused on decode because the terminator
33*c8d645caSAndroid Build Coastguard Worker * would not fit. */
34*c8d645caSAndroid Build Coastguard Worker if (strcmp(stream.errmsg, "string overflow") != 0)
35*c8d645caSAndroid Build Coastguard Worker assert(status);
36*c8d645caSAndroid Build Coastguard Worker }
37*c8d645caSAndroid Build Coastguard Worker
38*c8d645caSAndroid Build Coastguard Worker free_with_check(msg);
39*c8d645caSAndroid Build Coastguard Worker return status;
40*c8d645caSAndroid Build Coastguard Worker }
41*c8d645caSAndroid Build Coastguard Worker
do_pointer_decode(uint8_t * buffer,size_t msglen,bool assert_success)42*c8d645caSAndroid Build Coastguard Worker static bool do_pointer_decode(uint8_t *buffer, size_t msglen, bool assert_success)
43*c8d645caSAndroid Build Coastguard Worker {
44*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream;
45*c8d645caSAndroid Build Coastguard Worker bool status;
46*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg;
47*c8d645caSAndroid Build Coastguard Worker
48*c8d645caSAndroid Build Coastguard Worker msg = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
49*c8d645caSAndroid Build Coastguard Worker memset(msg, 0, sizeof(alltypes_pointer_AllTypes));
50*c8d645caSAndroid Build Coastguard Worker stream = pb_istream_from_buffer(buffer, msglen);
51*c8d645caSAndroid Build Coastguard Worker
52*c8d645caSAndroid Build Coastguard Worker assert(get_alloc_count() == 0);
53*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg);
54*c8d645caSAndroid Build Coastguard Worker
55*c8d645caSAndroid Build Coastguard Worker if (assert_success)
56*c8d645caSAndroid Build Coastguard Worker assert(status);
57*c8d645caSAndroid Build Coastguard Worker
58*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg);
59*c8d645caSAndroid Build Coastguard Worker assert(get_alloc_count() == 0);
60*c8d645caSAndroid Build Coastguard Worker
61*c8d645caSAndroid Build Coastguard Worker free_with_check(msg);
62*c8d645caSAndroid Build Coastguard Worker
63*c8d645caSAndroid Build Coastguard Worker return status;
64*c8d645caSAndroid Build Coastguard Worker }
65*c8d645caSAndroid Build Coastguard Worker
66*c8d645caSAndroid Build Coastguard Worker /* Do a decode -> encode -> decode -> encode roundtrip */
do_static_roundtrip(uint8_t * buffer,size_t msglen)67*c8d645caSAndroid Build Coastguard Worker static void do_static_roundtrip(uint8_t *buffer, size_t msglen)
68*c8d645caSAndroid Build Coastguard Worker {
69*c8d645caSAndroid Build Coastguard Worker bool status;
70*c8d645caSAndroid Build Coastguard Worker uint8_t *buf2 = malloc_with_check(BUFSIZE);
71*c8d645caSAndroid Build Coastguard Worker uint8_t *buf3 = malloc_with_check(BUFSIZE);
72*c8d645caSAndroid Build Coastguard Worker size_t msglen2, msglen3;
73*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_static_AllTypes));
74*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_static_AllTypes));
75*c8d645caSAndroid Build Coastguard Worker memset(msg1, 0, sizeof(alltypes_static_AllTypes));
76*c8d645caSAndroid Build Coastguard Worker memset(msg2, 0, sizeof(alltypes_static_AllTypes));
77*c8d645caSAndroid Build Coastguard Worker
78*c8d645caSAndroid Build Coastguard Worker {
79*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
80*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg1);
81*c8d645caSAndroid Build Coastguard Worker assert(status);
82*c8d645caSAndroid Build Coastguard Worker }
83*c8d645caSAndroid Build Coastguard Worker
84*c8d645caSAndroid Build Coastguard Worker {
85*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
86*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg1);
87*c8d645caSAndroid Build Coastguard Worker assert(status);
88*c8d645caSAndroid Build Coastguard Worker msglen2 = stream.bytes_written;
89*c8d645caSAndroid Build Coastguard Worker }
90*c8d645caSAndroid Build Coastguard Worker
91*c8d645caSAndroid Build Coastguard Worker {
92*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
93*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg2);
94*c8d645caSAndroid Build Coastguard Worker assert(status);
95*c8d645caSAndroid Build Coastguard Worker }
96*c8d645caSAndroid Build Coastguard Worker
97*c8d645caSAndroid Build Coastguard Worker {
98*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
99*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg2);
100*c8d645caSAndroid Build Coastguard Worker assert(status);
101*c8d645caSAndroid Build Coastguard Worker msglen3 = stream.bytes_written;
102*c8d645caSAndroid Build Coastguard Worker }
103*c8d645caSAndroid Build Coastguard Worker
104*c8d645caSAndroid Build Coastguard Worker assert(msglen2 == msglen3);
105*c8d645caSAndroid Build Coastguard Worker assert(memcmp(buf2, buf3, msglen2) == 0);
106*c8d645caSAndroid Build Coastguard Worker
107*c8d645caSAndroid Build Coastguard Worker free_with_check(msg1);
108*c8d645caSAndroid Build Coastguard Worker free_with_check(msg2);
109*c8d645caSAndroid Build Coastguard Worker free_with_check(buf2);
110*c8d645caSAndroid Build Coastguard Worker free_with_check(buf3);
111*c8d645caSAndroid Build Coastguard Worker }
112*c8d645caSAndroid Build Coastguard Worker
113*c8d645caSAndroid Build Coastguard Worker /* Do decode -> encode -> decode -> encode roundtrip */
do_pointer_roundtrip(uint8_t * buffer,size_t msglen)114*c8d645caSAndroid Build Coastguard Worker static void do_pointer_roundtrip(uint8_t *buffer, size_t msglen)
115*c8d645caSAndroid Build Coastguard Worker {
116*c8d645caSAndroid Build Coastguard Worker bool status;
117*c8d645caSAndroid Build Coastguard Worker uint8_t *buf2 = malloc_with_check(BUFSIZE);
118*c8d645caSAndroid Build Coastguard Worker uint8_t *buf3 = malloc_with_check(BUFSIZE);
119*c8d645caSAndroid Build Coastguard Worker size_t msglen2, msglen3;
120*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
121*c8d645caSAndroid Build Coastguard Worker alltypes_pointer_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
122*c8d645caSAndroid Build Coastguard Worker memset(msg1, 0, sizeof(alltypes_pointer_AllTypes));
123*c8d645caSAndroid Build Coastguard Worker memset(msg2, 0, sizeof(alltypes_pointer_AllTypes));
124*c8d645caSAndroid Build Coastguard Worker
125*c8d645caSAndroid Build Coastguard Worker {
126*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
127*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg1);
128*c8d645caSAndroid Build Coastguard Worker assert(status);
129*c8d645caSAndroid Build Coastguard Worker }
130*c8d645caSAndroid Build Coastguard Worker
131*c8d645caSAndroid Build Coastguard Worker {
132*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
133*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg1);
134*c8d645caSAndroid Build Coastguard Worker assert(status);
135*c8d645caSAndroid Build Coastguard Worker msglen2 = stream.bytes_written;
136*c8d645caSAndroid Build Coastguard Worker }
137*c8d645caSAndroid Build Coastguard Worker
138*c8d645caSAndroid Build Coastguard Worker {
139*c8d645caSAndroid Build Coastguard Worker pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
140*c8d645caSAndroid Build Coastguard Worker status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg2);
141*c8d645caSAndroid Build Coastguard Worker assert(status);
142*c8d645caSAndroid Build Coastguard Worker }
143*c8d645caSAndroid Build Coastguard Worker
144*c8d645caSAndroid Build Coastguard Worker {
145*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
146*c8d645caSAndroid Build Coastguard Worker status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg2);
147*c8d645caSAndroid Build Coastguard Worker assert(status);
148*c8d645caSAndroid Build Coastguard Worker msglen3 = stream.bytes_written;
149*c8d645caSAndroid Build Coastguard Worker }
150*c8d645caSAndroid Build Coastguard Worker
151*c8d645caSAndroid Build Coastguard Worker assert(msglen2 == msglen3);
152*c8d645caSAndroid Build Coastguard Worker assert(memcmp(buf2, buf3, msglen2) == 0);
153*c8d645caSAndroid Build Coastguard Worker
154*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg1);
155*c8d645caSAndroid Build Coastguard Worker pb_release(alltypes_pointer_AllTypes_fields, msg2);
156*c8d645caSAndroid Build Coastguard Worker free_with_check(msg1);
157*c8d645caSAndroid Build Coastguard Worker free_with_check(msg2);
158*c8d645caSAndroid Build Coastguard Worker free_with_check(buf2);
159*c8d645caSAndroid Build Coastguard Worker free_with_check(buf3);
160*c8d645caSAndroid Build Coastguard Worker }
161*c8d645caSAndroid Build Coastguard Worker
run_iteration()162*c8d645caSAndroid Build Coastguard Worker static void run_iteration()
163*c8d645caSAndroid Build Coastguard Worker {
164*c8d645caSAndroid Build Coastguard Worker uint8_t *buffer = malloc_with_check(BUFSIZE);
165*c8d645caSAndroid Build Coastguard Worker size_t msglen;
166*c8d645caSAndroid Build Coastguard Worker bool status;
167*c8d645caSAndroid Build Coastguard Worker
168*c8d645caSAndroid Build Coastguard Worker msglen = fread(buffer, 1, BUFSIZE, stdin);
169*c8d645caSAndroid Build Coastguard Worker
170*c8d645caSAndroid Build Coastguard Worker status = do_static_decode(buffer, msglen, false);
171*c8d645caSAndroid Build Coastguard Worker
172*c8d645caSAndroid Build Coastguard Worker if (status)
173*c8d645caSAndroid Build Coastguard Worker do_static_roundtrip(buffer, msglen);
174*c8d645caSAndroid Build Coastguard Worker
175*c8d645caSAndroid Build Coastguard Worker status = do_pointer_decode(buffer, msglen, false);
176*c8d645caSAndroid Build Coastguard Worker
177*c8d645caSAndroid Build Coastguard Worker if (status)
178*c8d645caSAndroid Build Coastguard Worker do_pointer_roundtrip(buffer, msglen);
179*c8d645caSAndroid Build Coastguard Worker
180*c8d645caSAndroid Build Coastguard Worker free_with_check(buffer);
181*c8d645caSAndroid Build Coastguard Worker }
182*c8d645caSAndroid Build Coastguard Worker
main(int argc,char ** argv)183*c8d645caSAndroid Build Coastguard Worker int main(int argc, char **argv)
184*c8d645caSAndroid Build Coastguard Worker {
185*c8d645caSAndroid Build Coastguard Worker run_iteration();
186*c8d645caSAndroid Build Coastguard Worker
187*c8d645caSAndroid Build Coastguard Worker return 0;
188*c8d645caSAndroid Build Coastguard Worker }
189*c8d645caSAndroid Build Coastguard Worker
190