blob: fb159fd1c20b5d2f538be0a3e5abf1c52749a339 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file fuzz_json_parser.c
* @brief OSS-Fuzz target for json-c parsing (HTTP/2 Pure JSON Architecture)
*
* This fuzzer tests the HTTP/2 JSON processing path in Axis2/C:
* - HTTP/2 mode uses json_tokener_parse() directly from json-c
* - Returns json_object* (no AXIOM/XML conversion)
* - Used by axis2_h2_transport_utils.c for HTTP/2 JSON services
*
* For HTTP/1.1 JSON processing (JSON->AXIOM conversion),
* see fuzz_json_reader.c which tests axis2_json_reader.
*
* Architecture:
* - HTTP/2: JSON -> json_tokener_parse() -> json_object* (this fuzzer)
* - HTTP/1.1: JSON -> axis2_json_reader -> axiom_node_t* (fuzz_json_reader)
*
* Attack vectors tested:
* - CVE-2020-12762 (integer overflow in json-c)
* - Stack exhaustion from deeply nested structures
* - Malformed JSON handling
* - Memory exhaustion from large payloads
*/
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <json-c/json.h>
/**
* Main fuzzer entry point - called millions of times with random data
*/
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct json_tokener *tok = NULL;
struct json_object *root = NULL;
if (size == 0 || size > 10 * 1024 * 1024) {
return 0; /* Skip empty or oversized inputs */
}
/* Create JSON tokener with depth limit to prevent stack exhaustion */
tok = json_tokener_new_ex(32); /* Max depth of 32 */
if (!tok) {
return 0;
}
/* Attempt to parse - should handle any input without crashing */
root = json_tokener_parse_ex(tok, (const char *)data, (int)size);
/* If parsing succeeded, exercise the structure */
if (root) {
/* Exercise various json-c operations */
enum json_type type = json_object_get_type(root);
(void)type;
if (json_object_is_type(root, json_type_object)) {
struct json_object_iterator it = json_object_iter_begin(root);
struct json_object_iterator end = json_object_iter_end(root);
int count = 0;
while (!json_object_iter_equal(&it, &end) && count < 100) {
const char *key = json_object_iter_peek_name(&it);
struct json_object *val = json_object_iter_peek_value(&it);
(void)key;
(void)val;
json_object_iter_next(&it);
count++;
}
} else if (json_object_is_type(root, json_type_array)) {
size_t len = json_object_array_length(root);
for (size_t i = 0; i < len && i < 100; i++) {
struct json_object *item = json_object_array_get_idx(root, i);
(void)item;
}
}
/* Test serialization */
const char *str = json_object_to_json_string(root);
(void)str;
json_object_put(root); /* Free JSON object */
}
json_tokener_free(tok);
return 0;
}