Fuzztest: reduce memory usage (for AVR)
diff --git a/tests/common/malloc_wrappers.c b/tests/common/malloc_wrappers.c
index 93b9840..ad8cbdc 100644
--- a/tests/common/malloc_wrappers.c
+++ b/tests/common/malloc_wrappers.c
@@ -20,6 +20,10 @@
#define MAX_REALLOC_SIZE 1024*1024
#endif
+#ifndef DEBUG_MALLOC
+#define DEBUG_MALLOC 0
+#endif
+
/* Allocate memory and place check values before and after. */
void* malloc_with_check(size_t size)
{
@@ -30,11 +34,12 @@
((size_t*)buf)[1] = CHECK1;
((size_t*)(buf + size))[2] = CHECK2;
alloc_count++;
+ if (DEBUG_MALLOC) fprintf(stderr, "Alloc 0x%04x/%u\n", (unsigned)(uintptr_t)(buf + PREFIX_SIZE), (unsigned)size);
return buf + PREFIX_SIZE;
}
else
{
- fprintf(stderr, "malloc(%u) failed\n", (unsigned)size);
+ if (DEBUG_MALLOC) fprintf(stderr, "malloc(%u) failed\n", (unsigned)size);
return NULL;
}
}
@@ -50,6 +55,7 @@
assert(((size_t*)(buf + size))[2] == CHECK2);
assert(alloc_count > 0);
alloc_count--;
+ if (DEBUG_MALLOC) fprintf(stderr, "Release 0x%04x/%u\n", (unsigned)(uintptr_t)mem, (unsigned)size);
free(buf);
}
}
@@ -79,6 +85,8 @@
((size_t*)buf)[0] = size;
((size_t*)buf)[1] = CHECK1;
((size_t*)(buf + size))[2] = CHECK2;
+
+ if (DEBUG_MALLOC) fprintf(stderr, "Realloc 0x%04x/%u to 0x%04x/%u\n", (unsigned)(uintptr_t)ptr, (unsigned)oldsize, (unsigned)(uintptr_t)(buf + PREFIX_SIZE), (unsigned)size);
return buf + PREFIX_SIZE;
}
else if (ptr && !size)
diff --git a/tests/fuzztest/SConscript b/tests/fuzztest/SConscript
index b2ae886..9a747cb 100644
--- a/tests/fuzztest/SConscript
+++ b/tests/fuzztest/SConscript
@@ -1,5 +1,6 @@
# Run a fuzz test to verify robustness against corrupted/malicious data.
+import sys
import time
import zipfile
import subprocess
@@ -81,9 +82,10 @@
if env.has_key("TEST_RUNNER"):
args = [env["TEST_RUNNER"]] + args
- for filename in corpus.namelist():
- if filename.endswith('/'):
- continue
+ files = [n for n in corpus.namelist() if not n.endswith('/')]
+ for filename in files:
+ sys.stdout.write("Fuzzing: %5d/%5d: %-40.40s\r" % (count, len(files), filename))
+ sys.stdout.flush()
count += 1
process = subprocess.Popen(args, stdin=subprocess.PIPE,
diff --git a/tests/fuzztest/fuzztest.c b/tests/fuzztest/fuzztest.c
index e919a76..ab7824c 100644
--- a/tests/fuzztest/fuzztest.c
+++ b/tests/fuzztest/fuzztest.c
@@ -33,11 +33,26 @@
static size_t g_bufsize = 4096;
#endif
+static uint32_t xor32_checksum(const void *data, size_t len)
+{
+ const uint8_t *buf = (const uint8_t*)data;
+ uint32_t checksum = 1234;
+ while (len--)
+ {
+ checksum ^= checksum << 13;
+ checksum ^= checksum >> 17;
+ checksum ^= checksum << 5;
+ checksum += *buf++;
+ }
+ return checksum;
+}
+
static bool do_decode(const uint8_t *buffer, size_t msglen, size_t structsize, const pb_msgdesc_t *msgtype, unsigned flags, bool assert_success)
{
bool status;
pb_istream_t stream;
size_t initial_alloc_count = get_alloc_count();
+ uint8_t *buf2 = malloc_with_check(g_bufsize); /* This is just to match the amount of memory allocations in do_roundtrips(). */
void *msg = malloc_with_check(structsize);
alltypes_static_TestExtension extmsg = alltypes_static_TestExtension_init_zero;
pb_extension_t ext = pb_extension_init_zero;
@@ -72,6 +87,7 @@
pb_release(msgtype, msg);
free_with_check(msg);
+ free_with_check(buf2);
assert(get_alloc_count() == initial_alloc_count);
return status;
@@ -160,9 +176,9 @@
static void do_roundtrip(const uint8_t *buffer, size_t msglen, size_t structsize, const pb_msgdesc_t *msgtype)
{
bool status;
- uint8_t *buf2 = malloc_with_check(g_bufsize);
- uint8_t *buf3 = malloc_with_check(g_bufsize);
+ uint32_t checksum2, checksum3;
size_t msglen2, msglen3;
+ uint8_t *buf2 = malloc_with_check(g_bufsize);
void *msg = malloc_with_check(structsize);
/* For proto2 types, we also test extension fields */
@@ -202,11 +218,12 @@
if (!status) fprintf(stderr, "pb_encode: %s\n", PB_GET_ERROR(&stream));
assert(status);
msglen2 = stream.bytes_written;
+ checksum2 = xor32_checksum(buf2, msglen2);
}
pb_release(msgtype, msg);
- /* Then decode and encode again. Result should remain the same. */
+ /* Then decode from canonical format and re-encode. Result should remain the same. */
{
pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
memset(msg, 0, structsize);
@@ -219,20 +236,20 @@
}
{
- pb_ostream_t stream = pb_ostream_from_buffer(buf3, g_bufsize);
+ pb_ostream_t stream = pb_ostream_from_buffer(buf2, g_bufsize);
status = pb_encode(&stream, msgtype, msg);
if (!status) fprintf(stderr, "pb_encode: %s\n", PB_GET_ERROR(&stream));
assert(status);
msglen3 = stream.bytes_written;
+ checksum3 = xor32_checksum(buf2, msglen3);
}
assert(msglen2 == msglen3);
- assert(memcmp(buf2, buf3, msglen2) == 0);
+ assert(checksum2 == checksum3);
pb_release(msgtype, msg);
free_with_check(msg);
free_with_check(buf2);
- free_with_check(buf3);
}
void do_roundtrips(const uint8_t *data, size_t size, bool expect_valid)