fuzz: check "short read" and io_reader.is_closed
Updates #96
diff --git a/fuzz/c/fuzzlib/fuzzlib.c b/fuzz/c/fuzzlib/fuzzlib.c
index 1f34046..e890b3a 100644
--- a/fuzz/c/fuzzlib/fuzzlib.c
+++ b/fuzz/c/fuzzlib/fuzzlib.c
@@ -27,6 +27,30 @@
*ptr = 0;
}
+static uint32_t //
+popcount32(uint32_t x) {
+ static const uint8_t table[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, //
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, //
+ };
+ return table[0xFF & (x >> 0)] + table[0xFF & (x >> 8)] +
+ table[0xFF & (x >> 16)] + table[0xFF & (x >> 24)];
+}
+
// jenkins_hash_u32 implements
// https://en.wikipedia.org/wiki/Jenkins_hash_function
static uint32_t //
@@ -68,15 +92,21 @@
uint32_t hash1 = jenkins_hash_u32(data + s2, size - s2);
uint64_t hash = (((uint64_t)hash0) << 32) | ((uint64_t)hash1);
+ // The ! means that closed will be true for (size == 0).
+ const bool closed = !(1 & popcount32(hash0));
+
wuffs_base__io_buffer src =
- wuffs_base__ptr_u8__reader((uint8_t*)data, size, true);
+ wuffs_base__ptr_u8__reader((uint8_t*)data, size, closed);
const char* msg = fuzz(&src, hash);
if (msg) {
if (strnlen(msg, 2047) >= 2047) {
msg = "fuzzlib: internal error: error message is too long";
}
- if (strstr(msg, "internal error:")) {
+ if (closed && strstr(msg, "base: short read")) {
+ fprintf(stderr, "short read on a closed io_reader\n");
+ intentional_segfault();
+ } else if (strstr(msg, "internal error:")) {
fprintf(stderr, "internal errors shouldn't occur: \"%s\"\n", msg);
intentional_segfault();
}
diff --git a/fuzz/c/std/cbor_fuzzer.c b/fuzz/c/std/cbor_fuzzer.c
index 2fcd01b..6d5f4a4 100644
--- a/fuzz/c/std/cbor_fuzzer.c
+++ b/fuzz/c/std/cbor_fuzzer.c
@@ -317,6 +317,9 @@
no_progress_count = 0;
} else if (no_progress_count < 999) {
no_progress_count++;
+ } else if (!full_src->meta.closed &&
+ (status.repr == wuffs_base__suspension__short_read)) {
+ return wuffs_base__status__message(&status);
} else {
return "fuzz: internal error: no progress";
}
@@ -345,8 +348,6 @@
break;
} else if (status.repr == wuffs_base__suspension__short_read) {
- // Some Wuffs packages can yield "$short read" for a closed io_reader,
- // but Wuffs' cbor package does not.
if (src.meta.closed) {
return "fuzz: internal error: short read on a closed io_reader";
}
diff --git a/fuzz/c/std/json_fuzzer.cc b/fuzz/c/std/json_fuzzer.cc
index 5cb0e22..231e8f8 100644
--- a/fuzz/c/std/json_fuzzer.cc
+++ b/fuzz/c/std/json_fuzzer.cc
@@ -338,6 +338,9 @@
no_progress_count = 0;
} else if (no_progress_count < 999) {
no_progress_count++;
+ } else if (!full_src->meta.closed &&
+ (status.repr == wuffs_base__suspension__short_read)) {
+ return wuffs_base__status__message(&status);
} else {
return "fuzz: internal error: no progress";
}
@@ -366,8 +369,6 @@
break;
} else if (status.repr == wuffs_base__suspension__short_read) {
- // Some Wuffs packages can yield "$short read" for a closed io_reader,
- // but Wuffs' json package does not.
if (src.meta.closed) {
return "fuzz: internal error: short read on a closed io_reader";
}