diff --git a/corpus/example.bin b/corpus/example.bin new file mode 100644 index 0000000..97c945a --- /dev/null +++ b/corpus/example.bin @@ -0,0 +1 @@ +"Â € " \ No newline at end of file diff --git a/src/fuzz.cpp b/src/fuzz.cpp index 097e8f8..8149164 100644 --- a/src/fuzz.cpp +++ b/src/fuzz.cpp @@ -42,6 +42,25 @@ std::pair runBatch(std::string copy) { return {state.result, s}; } +std::pair runPrefix(std::string copy, + int prefix) { + SerializeState state; + auto c = serializeCallbacks(); + std::unique_ptr parser{ + WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; + auto s = WeaselJsonParser_parse(parser.get(), copy.data(), prefix); + if (s != WeaselJson_AGAIN) { + return {state.result, s}; + } + s = WeaselJsonParser_parse(parser.get(), copy.data() + prefix, + copy.size() - prefix); + if (s != WeaselJson_AGAIN) { + return {state.result, s}; + } + s = WeaselJsonParser_parse(parser.get(), nullptr, 0); + return {state.result, s}; +} + void testStreaming(std::string const &json) { auto batch = runBatch(json); if (batch.second == WeaselJson_AGAIN) { @@ -57,15 +76,36 @@ void testStreaming(std::string const &json) { bool batchOk = batch.second == WeaselJson_OK; if (streamingOk == batchOk && !batchOk) { // It's ok if the processed data doesn't match if parsing failed - continue; + } else { + printf("streaming: %s, %s\n", + streaming.second == WeaselJson_OK ? "accept" : "reject", + streaming.first.c_str()); + printf("batch: %s, %s\n", + batch.second == WeaselJson_OK ? "accept" : "reject", + batch.first.c_str()); + abort(); + } + } + if (int(json.size()) > stride) { + auto prefix = runPrefix(json, stride); + if (prefix != batch) { + if (prefix.second == WeaselJson_AGAIN) { + abort(); + } + bool prefixOk = prefix.second == WeaselJson_OK; + bool batchOk = batch.second == WeaselJson_OK; + if (prefixOk == batchOk && !batchOk) { + // It's ok if the processed data doesn't match if parsing failed + } else { + printf("prefix: %s, %s\n", + prefix.second == WeaselJson_OK ? "accept" : "reject", + prefix.first.c_str()); + printf("batch: %s, %s\n", + batch.second == WeaselJson_OK ? "accept" : "reject", + batch.first.c_str()); + abort(); + } } - printf("streaming: %s, %s\n", - streaming.second == WeaselJson_OK ? "accept" : "reject", - streaming.first.c_str()); - printf("batch: %s, %s\n", - batch.second == WeaselJson_OK ? "accept" : "reject", - batch.first.c_str()); - abort(); } } }