Coverage Report

Created: 2026-09-03 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jansson/test/ossfuzz/json_pack_unpack_fuzzer.cc
Line
Count
Source
1
/*
2
 * json_pack_unpack_fuzzer.cc
3
 *
4
 * Fuzz harness for jansson json_unpack() and json_deep_copy() paths.
5
 * json_unpack() processes a format string + JSON value and extracts
6
 * typed fields — it involves non-trivial string/type dispatch that
7
 * is not exercised by the load/dump fuzzer.
8
 *
9
 * OSS-Fuzz build: compiled via test/ossfuzz/ossfuzz.sh.
10
 */
11
#include <stdint.h>
12
#include <stddef.h>
13
#include <string.h>
14
#include <stdlib.h>
15
16
#include "jansson.h"
17
18
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
19
5.91k
{
20
5.91k
    if (size < 2)
21
1
        return 0;
22
23
    /* Use first byte to select format variant, rest as JSON input */
24
5.91k
    uint8_t variant = data[0] % 8;
25
5.91k
    const char *json_str = (const char *)(data + 1);
26
5.91k
    size_t json_len = size - 1;
27
28
5.91k
    json_error_t error;
29
5.91k
    json_t *root = json_loadb(json_str, json_len,
30
5.91k
                               JSON_DECODE_ANY | JSON_ALLOW_NUL, &error);
31
5.91k
    if (root == NULL)
32
1.28k
        return 0;
33
34
    /* Exercise json_deep_copy on whatever we parsed */
35
4.63k
    json_t *copy = json_deep_copy(root);
36
4.63k
    if (copy != NULL)
37
4.63k
        json_decref(copy);
38
39
    /* Exercise json_dumps with various flags */
40
4.63k
    const int flag_sets[] = {
41
4.63k
        0,
42
4.63k
        JSON_COMPACT,
43
4.63k
        JSON_ENSURE_ASCII,
44
4.63k
        JSON_SORT_KEYS,
45
4.63k
        JSON_COMPACT | JSON_ENSURE_ASCII,
46
4.63k
    };
47
4.63k
    int flags = flag_sets[variant % 5];
48
4.63k
    char *dumped = json_dumps(root, flags);
49
4.63k
    if (dumped != NULL) {
50
        /* Re-load the dumped output for round-trip check */
51
4.52k
        json_t *reparsed = json_loads(dumped, 0, NULL);
52
4.52k
        if (reparsed != NULL)
53
4.51k
            json_decref(reparsed);
54
4.52k
        free(dumped);
55
4.52k
    }
56
57
    /* Exercise json_unpack with simple format strings if root is an object */
58
4.63k
    if (json_is_object(root)) {
59
442
        json_t *val = NULL;
60
442
        const char *key = NULL;
61
        /* Unpack first key-value pair */
62
442
        void *iter = json_object_iter(root);
63
442
        if (iter != NULL) {
64
440
            key = json_object_iter_key(iter);
65
440
            val  = json_object_iter_value(iter);
66
440
            (void)key;
67
440
            (void)val;
68
440
        }
69
70
        /* json_unpack with "o" format — extract object */
71
442
        json_t *out_obj = NULL;
72
442
        json_unpack(root, "o", &out_obj);
73
74
        /* json_unpack with "{s?o}" — optional key lookup */
75
442
        json_t *field = NULL;
76
442
        json_unpack(root, "{s?o}", "data", &field);
77
442
    }
78
79
    /* Exercise json_unpack on array */
80
4.63k
    if (json_is_array(root) && json_array_size(root) > 0) {
81
4.08k
        json_t *first = NULL;
82
4.08k
        json_unpack(root, "[o!]", &first);
83
4.08k
    }
84
85
4.63k
    json_decref(root);
86
4.63k
    return 0;
87
5.91k
}