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
104 changes: 104 additions & 0 deletions fuzzing/cjson_array_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2025 Google LLC
// Fuzz target for cJSON array operations
// Targets: cJSON_CreateStringArray, cJSON_Duplicate, cJSON_Compare

#include <cjson/cJSON.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

// Helper to safely create string array from fuzz input
cJSON* create_string_array_from_input(const char* data, size_t size) {
// Parse input as newline-separated strings
const char* strings[32];
int count = 0;
char* temp = (char*)malloc(size + 1);
if (!temp) return NULL;

memcpy(temp, data, size);
temp[size] = '\0';

char* token = strtok(temp, "\n");
while (token && count < 32) {
strings[count++] = token;
token = strtok(NULL, "\n");
}

cJSON* arr = NULL;
if (count > 0) {
arr = cJSON_CreateStringArray(strings, count);
}

free(temp);
return arr;
}

// Fuzz target for cJSON array and comparison operations
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 2) return 0;

// Split input into two parts for comparison testing
size_t split = size / 2;

// Create first JSON object
char* input1 = (char*)malloc(split + 1);
if (!input1) return 0;
memcpy(input1, data, split);
input1[split] = '\0';

cJSON* obj1 = cJSON_Parse(input1);
free(input1);

// Create second JSON object
char* input2 = (char*)malloc(size - split + 1);
if (!input2) {
if (obj1) cJSON_Delete(obj1);
return 0;
}
memcpy(input2, data + split, size - split);
input2[size - split] = '\0';

cJSON* obj2 = cJSON_Parse(input2);
free(input2);

// Test cJSON_Compare - 0% coverage target
if (obj1 && obj2) {
cJSON_Compare(obj1, obj2, cJSON_False);
cJSON_Compare(obj1, obj2, cJSON_True); // case-sensitive
}

// Test cJSON_Duplicate - 0% coverage target
if (obj1) {
cJSON* dup1 = cJSON_Duplicate(obj1, cJSON_False); // shallow
if (dup1) cJSON_Delete(dup1);

cJSON* dup2 = cJSON_Duplicate(obj1, cJSON_True); // deep
if (dup2) cJSON_Delete(dup2);
}

// Test cJSON_CreateStringArray - 0% coverage target
cJSON* str_array = create_string_array_from_input((const char*)data, size);
if (str_array) {
// Test detaching and deleting items
cJSON* detached = cJSON_DetachItemFromArray(str_array, 0);
if (detached) cJSON_Delete(detached);

cJSON_DeleteItemFromArray(str_array, 0);
cJSON_Delete(str_array);
}

// Test object detachment functions
if (obj1) {
cJSON* detached = cJSON_DetachItemFromObject(obj1, "key");
if (detached) cJSON_Delete(detached);

cJSON_DeleteItemFromObject(obj1, "key");
cJSON_DeleteItemFromObjectCaseSensitive(obj1, "Key");
}

// Cleanup
if (obj1) cJSON_Delete(obj1);
if (obj2) cJSON_Delete(obj2);

return 0;
}
59 changes: 59 additions & 0 deletions fuzzing/cjson_manipulation_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2025 Google LLC
// Fuzz target for cJSON object manipulation functions
// Targets: cJSON_Parse, cJSON_ReplaceItemInObject, cJSON_AddItemToObject

#include <cjson/cJSON.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

// Fuzz target for cJSON object manipulation
// This targets functions that currently have 0% coverage according to Fuzz Introspector
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Ensure null-terminated string for JSON parsing
char* input = (char*)malloc(size + 1);
if (!input) return 0;

memcpy(input, data, size);
input[size] = '\0';

// Parse the input as JSON
cJSON* root = cJSON_Parse(input);
if (!root) {
free(input);
return 0;
}

// Test cJSON_ReplaceItemInObject - 0% coverage target
cJSON* replacement = cJSON_CreateString("fuzz_value");
if (replacement) {
cJSON_ReplaceItemInObject(root, "key", replacement);
// Also test case-sensitive version
cJSON_ReplaceItemInObjectCaseSensitive(root, "Key", replacement);
}

// Test cJSON_AddItemToObject - another 0% coverage target
cJSON* new_item = cJSON_CreateNumber(42);
if (new_item) {
cJSON_AddItemToObject(root, "fuzz_key", new_item);
}

// Test cJSON_AddItemToObjectCS (constant string key)
cJSON* cs_item = cJSON_CreateBool(1);
if (cs_item) {
cJSON_AddItemToObjectCS(root, "const_key", cs_item);
}

// Test array manipulation
cJSON* array = cJSON_GetObjectItem(root, "array");
if (array && cJSON_IsArray(array)) {
cJSON* arr_item = cJSON_CreateNumber(123);
cJSON_ReplaceItemInArray(array, 0, arr_item);
}

// Cleanup
cJSON_Delete(root);
free(input);

return 0;
}
77 changes: 77 additions & 0 deletions fuzzing/cjson_serialization_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2025 Google LLC
// Fuzz target for cJSON serialization functions
// Targets: cJSON_PrintPreallocated, cJSON_PrintBuffered

#include <cjson/cJSON.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

// Fuzz target for cJSON serialization with preallocated buffers
// Targets 0% coverage functions identified by Fuzz Introspector
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Ensure null-terminated string
char* input = (char*)malloc(size + 1);
if (!input) return 0;

memcpy(input, data, size);
input[size] = '\0';

// Parse JSON first
cJSON* root = cJSON_Parse(input);
if (!root) {
free(input);
return 0;
}

// Test cJSON_PrintPreallocated - 0% coverage target
// This function prints to a user-provided buffer
size_t buffer_size = 65536; // 64KB initial buffer
char* buffer = (char*)malloc(buffer_size);
if (buffer) {
cJSON_bool prealloc_result = cJSON_PrintPreallocated(
root, buffer, (int)buffer_size, cJSON_False
);
// Try with formatted output as well
if (!prealloc_result) {
cJSON_PrintPreallocated(root, buffer, (int)buffer_size, cJSON_True);
}
free(buffer);
}

// Test various cJSON structures for better coverage
cJSON* test_obj = cJSON_CreateObject();
if (test_obj) {
// Add various data types
cJSON_AddNullToObject(test_obj, "null_val");
cJSON_AddTrueToObject(test_obj, "true_val");
cJSON_AddFalseToObject(test_obj, "false_val");
cJSON_AddBoolToObject(test_obj, "bool_val", cJSON_True);
cJSON_AddNumberToObject(test_obj, "num_val", 3.14159);
cJSON_AddStringToObject(test_obj, "str_val", "test");
cJSON_AddRawToObject(test_obj, "raw_val", "{\"nested\":true}");

// Create and add array
cJSON* arr = cJSON_CreateIntArray((const int[]){1, 2, 3}, 3);
cJSON_AddItemToObject(test_obj, "int_array", arr);

cJSON* double_arr = cJSON_CreateDoubleArray(
(const double[]){1.1, 2.2, 3.3}, 3
);
cJSON_AddItemToObject(test_obj, "double_array", double_arr);

cJSON* float_arr = cJSON_CreateFloatArray(
(const float[]){1.1f, 2.2f, 3.3f}, 3
);
cJSON_AddItemToObject(test_obj, "float_array", float_arr);

// Cleanup
cJSON_Delete(test_obj);
}

// Cleanup
cJSON_Delete(root);
free(input);

return 0;
}