1 /* Fuzz testing for the nanopb core.
2 * This can be used with external fuzzers, e.g. radamsa.
3 * It performs most of the same checks as fuzztest, but does not feature data generation.
13 #include <malloc_wrappers.h>
14 #include "alltypes_static.pb.h"
15 #include "alltypes_pointer.pb.h"
19 static bool do_static_decode(uint8_t *buffer, size_t msglen, bool assert_success)
24 alltypes_static_AllTypes *msg = malloc_with_check(sizeof(alltypes_static_AllTypes));
25 stream = pb_istream_from_buffer(buffer, msglen);
26 status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg);
28 if (!status && assert_success)
30 /* Anything that was successfully encoded, should be decodeable.
31 * One exception: strings without null terminator are encoded up
32 * to end of buffer, but refused on decode because the terminator
34 if (strcmp(stream.errmsg, "string overflow") != 0)
42 static bool do_pointer_decode(uint8_t *buffer, size_t msglen, bool assert_success)
46 alltypes_pointer_AllTypes *msg;
48 msg = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
49 memset(msg, 0, sizeof(alltypes_pointer_AllTypes));
50 stream = pb_istream_from_buffer(buffer, msglen);
52 assert(get_alloc_count() == 0);
53 status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg);
58 pb_release(alltypes_pointer_AllTypes_fields, msg);
59 assert(get_alloc_count() == 0);
66 /* Do a decode -> encode -> decode -> encode roundtrip */
67 static void do_static_roundtrip(uint8_t *buffer, size_t msglen)
70 uint8_t *buf2 = malloc_with_check(BUFSIZE);
71 uint8_t *buf3 = malloc_with_check(BUFSIZE);
72 size_t msglen2, msglen3;
73 alltypes_static_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_static_AllTypes));
74 alltypes_static_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_static_AllTypes));
75 memset(msg1, 0, sizeof(alltypes_static_AllTypes));
76 memset(msg2, 0, sizeof(alltypes_static_AllTypes));
79 pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
80 status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg1);
85 pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
86 status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg1);
88 msglen2 = stream.bytes_written;
92 pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
93 status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg2);
98 pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
99 status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg2);
101 msglen3 = stream.bytes_written;
104 assert(msglen2 == msglen3);
105 assert(memcmp(buf2, buf3, msglen2) == 0);
107 free_with_check(msg1);
108 free_with_check(msg2);
109 free_with_check(buf2);
110 free_with_check(buf3);
113 /* Do decode -> encode -> decode -> encode roundtrip */
114 static void do_pointer_roundtrip(uint8_t *buffer, size_t msglen)
117 uint8_t *buf2 = malloc_with_check(BUFSIZE);
118 uint8_t *buf3 = malloc_with_check(BUFSIZE);
119 size_t msglen2, msglen3;
120 alltypes_pointer_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
121 alltypes_pointer_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
122 memset(msg1, 0, sizeof(alltypes_pointer_AllTypes));
123 memset(msg2, 0, sizeof(alltypes_pointer_AllTypes));
126 pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
127 status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg1);
132 pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
133 status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg1);
135 msglen2 = stream.bytes_written;
139 pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
140 status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg2);
145 pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
146 status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg2);
148 msglen3 = stream.bytes_written;
151 assert(msglen2 == msglen3);
152 assert(memcmp(buf2, buf3, msglen2) == 0);
154 pb_release(alltypes_pointer_AllTypes_fields, msg1);
155 pb_release(alltypes_pointer_AllTypes_fields, msg2);
156 free_with_check(msg1);
157 free_with_check(msg2);
158 free_with_check(buf2);
159 free_with_check(buf3);
162 static void run_iteration()
164 uint8_t *buffer = malloc_with_check(BUFSIZE);
168 msglen = fread(buffer, 1, BUFSIZE, stdin);
170 status = do_static_decode(buffer, msglen, false);
173 do_static_roundtrip(buffer, msglen);
175 status = do_pointer_decode(buffer, msglen, false);
178 do_pointer_roundtrip(buffer, msglen);
180 free_with_check(buffer);
183 int main(int argc, char **argv)