Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions fuzzing/cjson_print_roundtrip_fuzzer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* cjson_print_roundtrip_fuzzer.c
*
* Fuzz harness for cJSON print/serialize paths and parse->print->parse
* round-trip consistency. Exercises:
* - cJSON_ParseWithLength() with arbitrary length mismatch
* - cJSON_PrintUnformatted() serialization of parsed trees
* - cJSON_PrintBuffered() with small prebuf to force reallocation
* - Round-trip: parse -> print -> re-parse (checks serializer output is valid)
* - cJSON_Print() (formatted) on the same tree
* - cJSON_Duplicate() for deep trees
*
* Build: compiled by fuzzing/ossfuzz.sh alongside cjson_read_fuzzer.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "../cJSON.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); /* required by C89 */

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
cJSON *obj = NULL;
cJSON *reparsed = NULL;
cJSON *dup = NULL;
char *unformatted = NULL;
char *formatted = NULL;
char *buffered = NULL;

if (size == 0)
return 0;

/* 1. Parse with explicit length (may differ from null-termination) */
obj = cJSON_ParseWithLength((const char *)data, size);
if (obj == NULL)
return 0;

/* 2. Print unformatted */
unformatted = cJSON_PrintUnformatted(obj);
if (unformatted != NULL) {
/* 3. Round-trip: re-parse the printed output */
reparsed = cJSON_Parse(unformatted);
if (reparsed != NULL) {
cJSON_Delete(reparsed);
}
free(unformatted);
}

/* 4. Print formatted */
formatted = cJSON_Print(obj);
if (formatted != NULL) {
free(formatted);
}

/* 5. PrintBuffered with small prebuf to exercise realloc path */
buffered = cJSON_PrintBuffered(obj, 16, cJSON_False);
if (buffered != NULL) {
free(buffered);
}

/* 6. Also exercise cJSON_Duplicate for deep trees */
dup = cJSON_Duplicate(obj, cJSON_True);
if (dup != NULL) {
cJSON_Delete(dup);
}

cJSON_Delete(obj);
return 0;
}

#ifdef __cplusplus
}
#endif
4 changes: 4 additions & 0 deletions fuzzing/ossfuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ $CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \
-o $OUT/cjson_read_fuzzer \
$LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a

$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_print_roundtrip_fuzzer.c -I. \
-o $OUT/cjson_print_roundtrip_fuzzer \
$LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a

find $SRC/cjson/fuzzing/inputs -name "*" | \
xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip

Expand Down