diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/fuzztest/SConscript | 4 | ||||
-rw-r--r-- | tests/fuzztest/fuzzstub.c | 2 | ||||
-rw-r--r-- | tests/fuzztest/generate_message.c | 101 | ||||
-rw-r--r-- | tests/regression/issue_172/SConscript | 16 | ||||
-rw-r--r-- | tests/regression/issue_172/msg_size.c | 9 | ||||
-rw-r--r-- | tests/regression/issue_172/submessage/submessage.options | 1 | ||||
-rw-r--r-- | tests/regression/issue_172/submessage/submessage.proto | 4 | ||||
-rw-r--r-- | tests/regression/issue_172/test.proto | 6 |
8 files changed, 142 insertions, 1 deletions
diff --git a/tests/fuzztest/SConscript b/tests/fuzztest/SConscript index 973148c2..d2fb689c 100644 --- a/tests/fuzztest/SConscript +++ b/tests/fuzztest/SConscript @@ -36,4 +36,8 @@ fuzzstub = malloc_env.Program(["fuzzstub.c", "$COMMON/pb_common_with_malloc.o", "$COMMON/malloc_wrappers.o"]) +generate_message = malloc_env.Program(["generate_message.c", + "alltypes_static.pb.c", + "$COMMON/pb_encode.o", + "$COMMON/pb_common.o"]) diff --git a/tests/fuzztest/fuzzstub.c b/tests/fuzztest/fuzzstub.c index ce14b9ba..ec9e2afe 100644 --- a/tests/fuzztest/fuzzstub.c +++ b/tests/fuzztest/fuzzstub.c @@ -165,7 +165,7 @@ static void run_iteration() size_t msglen; bool status; - msglen = fread(buffer, BUFSIZE, 1, stdin); + msglen = fread(buffer, 1, BUFSIZE, stdin); status = do_static_decode(buffer, msglen, false); diff --git a/tests/fuzztest/generate_message.c b/tests/fuzztest/generate_message.c new file mode 100644 index 00000000..6e492990 --- /dev/null +++ b/tests/fuzztest/generate_message.c @@ -0,0 +1,101 @@ +/* Generates a random, valid protobuf message. Useful to seed + * external fuzzers such as afl-fuzz. + */ + +#include <pb_encode.h> +#include <pb_common.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> +#include "alltypes_static.pb.h" + +static uint64_t random_seed; + +/* Uses xorshift64 here instead of rand() for both speed and + * reproducibility across platforms. */ +static uint32_t rand_word() +{ + random_seed ^= random_seed >> 12; + random_seed ^= random_seed << 25; + random_seed ^= random_seed >> 27; + return random_seed * 2685821657736338717ULL; +} + +/* Fills a buffer with random data. */ +static void rand_fill(uint8_t *buf, size_t count) +{ + while (count--) + { + *buf++ = rand_word() & 0xff; + } +} + +/* Check that size/count fields do not exceed their max size. + * Otherwise we would have to loop pretty long in generate_message(). + * Note that there may still be a few encoding errors from submessages. + */ +static void limit_sizes(alltypes_static_AllTypes *msg) +{ + pb_field_iter_t iter; + pb_field_iter_begin(&iter, alltypes_static_AllTypes_fields, msg); + while (pb_field_iter_next(&iter)) + { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_BYTES) + { + ((pb_bytes_array_t*)iter.pData)->size %= iter.pos->data_size - PB_BYTES_ARRAY_T_ALLOCSIZE(0); + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED) + { + *((pb_size_t*)iter.pSize) %= iter.pos->array_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_ONEOF) + { + /* Set the oneof to this message type with 50% chance. */ + if (rand_word() & 1) + { + *((pb_size_t*)iter.pSize) = iter.pos->tag; + } + } + } +} + +static void generate_message() +{ + alltypes_static_AllTypes msg; + uint8_t buf[8192]; + pb_ostream_t stream = {0}; + + do { + if (stream.errmsg) + fprintf(stderr, "Encoder error: %s\n", stream.errmsg); + + stream = pb_ostream_from_buffer(buf, sizeof(buf)); + rand_fill((void*)&msg, sizeof(msg)); + limit_sizes(&msg); + } while (!pb_encode(&stream, alltypes_static_AllTypes_fields, &msg)); + + fwrite(buf, 1, stream.bytes_written, stdout); +} + +int main(int argc, char **argv) +{ + if (argc > 1) + { + random_seed = atol(argv[1]); + } + else + { + random_seed = time(NULL); + } + + fprintf(stderr, "Random seed: %llu\n", (long long unsigned)random_seed); + + generate_message(); + + return 0; +} + diff --git a/tests/regression/issue_172/SConscript b/tests/regression/issue_172/SConscript new file mode 100644 index 00000000..49c919e8 --- /dev/null +++ b/tests/regression/issue_172/SConscript @@ -0,0 +1,16 @@ +# Verify that _size define is generated for messages that have +# includes from another directory. + +Import('env') + +incpath = env.Clone() +incpath.Append(PROTOCPATH="#regression/issue_172/submessage") +incpath.Append(CPPPATH="$BUILD/regression/issue_172/submessage") +incpath.NanopbProto('test') +incpath.NanopbProto(['submessage/submessage', 'submessage/submessage.options']) + +p = incpath.Program(["msg_size.c", + "test.pb.c", + "submessage/submessage.pb.c"]) + + diff --git a/tests/regression/issue_172/msg_size.c b/tests/regression/issue_172/msg_size.c new file mode 100644 index 00000000..be45acb4 --- /dev/null +++ b/tests/regression/issue_172/msg_size.c @@ -0,0 +1,9 @@ +#include "test.pb.h" + +PB_STATIC_ASSERT(testmessage_size >= 1+1+1+1+16, TESTMESSAGE_SIZE_IS_WRONG) + +int main() +{ + return 0; +} + diff --git a/tests/regression/issue_172/submessage/submessage.options b/tests/regression/issue_172/submessage/submessage.options new file mode 100644 index 00000000..12fb1984 --- /dev/null +++ b/tests/regression/issue_172/submessage/submessage.options @@ -0,0 +1 @@ +submessage.data max_size: 16 diff --git a/tests/regression/issue_172/submessage/submessage.proto b/tests/regression/issue_172/submessage/submessage.proto new file mode 100644 index 00000000..ce6804af --- /dev/null +++ b/tests/regression/issue_172/submessage/submessage.proto @@ -0,0 +1,4 @@ +syntax = "proto2"; +message submessage { + required bytes data = 1; +} diff --git a/tests/regression/issue_172/test.proto b/tests/regression/issue_172/test.proto new file mode 100644 index 00000000..fbd97be5 --- /dev/null +++ b/tests/regression/issue_172/test.proto @@ -0,0 +1,6 @@ +syntax = "proto2"; +import "submessage.proto"; + +message testmessage { + optional submessage sub = 1; +} |