Coverage Report

Created: 2026-02-26 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/tests/jq_fuzz_fixed.cpp
Line
Count
Source
1
#include <fuzzer/FuzzedDataProvider.h>
2
#include <string>
3
4
#include "jq.h"
5
#include "jv.h"
6
7
8
const char *jq_progs[] = {
9
    ". / \", \"",
10
    ".[]",
11
    "$ENV.PAGER",
12
    ".[0]",
13
    ". < 0.12345678901234567890123456788",
14
    ".[] == 1",
15
    ".[] | (1 / .)?",
16
    "10 / . * 3",
17
    "[1,2,empty,3]",
18
    "1, empty, 2",
19
    "[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]",
20
    ".[-2:]",
21
    ".[-2]",
22
    ".[2]",
23
    "[ .[] | . * 2]",
24
    ".[2:4]",
25
    "(. + 2) * 5",
26
    ".[:3]",
27
    ".[4,2]",
28
    "42 and \"a string\"",
29
    "4 - .a",
30
    ". < 5",
31
    ".. | .a?",
32
    "[.[] | .a?]",
33
    ".a + 1",
34
    "{a: 1} + {b: 2} + {c: 3} + {a: 42}",
35
    ".a + .b",
36
    ".a = .b",
37
    ".a |= .b",
38
    "add",
39
    "all",
40
    ".a + null",
41
    "any",
42
    ".[] as [$a, $b] | {a: $a, b: $b}",
43
    ". as [$a, $b, {c: $c}] | $a + $b + $c",
44
    ".[] as {$a, $b, c: {$d}} ?// {$a, $b, c: [{$e}]} | {$a, $b, $d, $e}",
45
    ".[] as {$a, $b, c: {$d, $e}} ?// {$a, $b, c: [{$d, $e}]} | {$a, $b, "
46
    "$d, $e}",
47
    ".[] as [$a] ?// [$b] | if $a != null then error(\"err: \\($a)\") else "
48
    "{$a,$b} end",
49
    ". as $big | [$big, $big + 1] | map(. > "
50
    "10000000000000000000000000000000)",
51
    ". as $dot|fromstream($dot|tostream)|.==$dot",
52
    ". as $i|[(.*2|. as $i| $i), $i]",
53
    "ascii_upcase",
54
    ".bar as $x | .foo | . + $x",
55
    "@base64",
56
    "@base64d",
57
    ". == {\"b\": {\"d\": (4 + 1e-20), \"c\": 3}, \"a\":1}",
58
    "bsearch(0)",
59
    "bsearch(4) as $ix | if $ix < 0 then .[-(1+$ix)] = 4 else . end",
60
    "capture(\"(?<a>[a-z]+)-(?<n>[0-9]+)\")",
61
    "capture(\"(?<a>[a-z]+)-(?<n>[0-9]+)\")",
62
    "combinations",
63
    "combinations(2)",
64
    "contains(\"bar\")",
65
    "contains([\"baz\", \"bar\"])",
66
    "contains([\"bazzzzz\", \"bar\"])",
67
    "contains({foo: 12, bar: [{barp: 15}]})",
68
    "def addvalue(f): f as $x | map(. + $x); addvalue(.[0])",
69
    "def addvalue(f): . + [f]; map(addvalue(.[0]))",
70
    "def while(cond; update): def _while: if cond then ., (update | "
71
    "_while) else empty end; _while; [while(.<100; .*2)]",
72
    "del(.[1, 2])",
73
    "del(.foo)",
74
    "delpaths([[\"a\",\"b\"]])",
75
    "empty // 42",
76
    "[.[]|endswith(\"foo\")]",
77
    "env.PAGER",
78
    "explode",
79
    ". == false",
80
    "(false, null, 1) // 42",
81
    "(false, null, 1) | . // 42",
82
    "flatten",
83
    "flatten(1)",
84
    "floor",
85
    ".[\"foo\"]",
86
    ".[\"foo\"]?",
87
    ".foo",
88
    ".foo?",
89
    ".foo[]",
90
    "[.foo?]",
91
    ".foo += 1",
92
    ".foo // 42",
93
    ".foo, .bar",
94
    "foreach .[] as $item (0; . + $item)",
95
    "foreach .[] as $item (0; . + $item; [$item, . * 2])",
96
    "foreach .[] as $item (0; . + 1; {index: ., $item})",
97
    "fromdate",
98
    "from_entries",
99
    "fromstream(1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]]))",
100
    "getpath([\"a\",\"b\"])",
101
    "[getpath([\"a\",\"b\"], [\"a\",\"c\"])]",
102
    "group_by(.foo)",
103
    "[.[] | gsub(\", \"; \":\")]",
104
    "gsub(\"$\"; \"a\"; \"g\")",
105
    "gsub(\"^\"; \"a\")",
106
    "[gsub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", "
107
    "\"c\")]",
108
    "gsub(\"^.*?a\"; \"b\")",
109
    "gsub(\"^.*a\"; \"b\")",
110
    "gsub(\"a\";\"b\")",
111
    "gsub(\"\"; \"a\"; \"g\")",
112
    "gsub(\"\"; \"a\"; \"g\")",
113
    "gsub(\"[^a-z]*(?<x>[a-z]*)\"; \"Z\\(.x)\")",
114
    "gsub(\"\\b(?<x>.)\"; \"\\(.x|ascii_downcase)\")",
115
    "gsub(\"(?<d>\\d)\"; \":\\(.d);\")",
116
    "gsub(\"^\"; \"\"; \"g\")",
117
    "[gsub(\"p\"; \"a\", \"b\")]",
118
    "gsub(\"(?=u)\"; \"u\")",
119
    "gsub(\"(.*)\"; \"\"; \"x\")",
120
    "gsub(\"(?<x>.)[^a]*\"; \"+\\(.x)-\")",
121
    "gsub(\"(?<x>.)(?<y>[0-9])\"; \"\\(.x|ascii_downcase)\\(.y)\")",
122
    "@html",
123
    "if . == 0 then   \"zero\" elif . == 1 then   \"one\" else   \"many\" "
124
    "end",
125
    "implode",
126
    "index(\", \")",
127
    "index(1)",
128
    "index([1,2])",
129
    "indices(\", \")",
130
    "indices(1)",
131
    "indices([1,2])",
132
    ".[] | (infinite * .) < 0",
133
    "infinite, nan | type",
134
    ".[] | in({\"foo\": 42})",
135
    "inside({\"foo\": 12, \"bar\":[1,2,{\"barp\":12, \"blip\":13}]})",
136
    "inside({\"foo\": 12, \"bar\":[1,2,{\"barp\":12, \"blip\":13}]})",
137
    "inside(\"foobar\")",
138
    "inside([\"foobar\", \"foobaz\", \"blarp\"])",
139
    "inside([\"foobar\", \"foobaz\", \"blarp\"])",
140
    "isempty(.[])",
141
    "isempty(.[])",
142
    "isempty(empty)",
143
    "join(\" \")",
144
    "join(\", \")",
145
    "keys",
146
    "keys",
147
    ".[] | length",
148
    "[limit(3;.[])]",
149
    "[.[]|ltrimstr(\"foo\")]",
150
    "map(., .)",
151
    "map(.+1)",
152
    "map([., . == 1]) | tojson",
153
    "map(abs)",
154
    "map(has(2))",
155
    "map(has(\"foo\"))",
156
    "map(in([0,1]))",
157
    "map(select(. >= 2))",
158
    "map(type)",
159
    "map_values(.+1)",
160
    "map_values(. // empty)",
161
    "match(\"(abc)+\"; \"g\")",
162
    "[match(\"a\"; \"gi\")]",
163
    "[match(\".+?\\b\")]",
164
    "[match([\"(bar)\"])]",
165
    "match(\"foo\")",
166
    "[match([\"foo (?<bar123>bar)? foo\", \"ig\"])]",
167
    "match(\"foo (?<bar123>bar)? foo\"; \"ig\")",
168
    "match([\"foo\", \"ig\"])",
169
    "[match(\"\"; \"g\")]",
170
    "[ match(\".\"; \"g\")] | length",
171
    "[match(\"( )*\"; \"gn\")]",
172
    "max_by(.foo)",
173
    "min",
174
    ".[] | .name",
175
    ".[]|numbers",
176
    "[path(..)]",
177
    "path(.a[0].b)",
178
    "[paths]",
179
    "[paths(type == \"number\")]",
180
    "pick(.[2], .[0], .[0])",
181
    "pick(.a, .b.c, .x)",
182
    "[range(0; 10; -1)]",
183
    "[range(0; 10; 3)]",
184
    "[range(0; -5; -1)]",
185
    "[range(2; 4)]",
186
    "range(2; 4)",
187
    "[range(4)]",
188
    "[range(.)]|[first, last, nth(5)]",
189
    "recurse",
190
    "recurse(. * .; . < 20)",
191
    "recurse(.foo[])",
192
    "reduce .[] as [$i,$j] (0; . + $i * $j)",
193
    "reduce .[] as $item (0; . + $item)",
194
    "reduce .[] as {$x,$y} (null; .x += $x | .y += [$y])",
195
    "[repeat(.*2, error)?]",
196
    "reverse",
197
    "rindex(\", \")",
198
    "rindex(1)",
199
    "rindex([1,2])",
200
    "[.[]|rtrimstr(\"foo\")]",
201
    "[.[] | scan(\", \")]",
202
    "[.[] | scan(\"b+\"; \"i\")]",
203
    "scan(\"c\")",
204
    ".[] | select(.id == \"second\")",
205
    "(..|select(type==\"boolean\")) |= if . then 1 else 0 end",
206
    "setpath([0,\"a\"]; 1)",
207
    "setpath([\"a\",\"b\"]; 1)",
208
    "setpath([\"a\",\"b\"]; 1)",
209
    "@sh \"echo \\(.)\"",
210
    "sort",
211
    "sort_by(.foo)",
212
    "sort_by(.foo, .bar)",
213
    "split(\", *\"; null)",
214
    "splits(\", *\")",
215
    "sqrt",
216
    "[.[]|startswith(\"foo\")]",
217
    "strptime(\"%Y-%m-%dT%H:%M:%SZ\")",
218
    "strptime(\"%Y-%m-%dT%H:%M:%SZ\")|mktime",
219
    "[sub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\")]",
220
    "[sub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", "
221
    "\"c\")]",
222
    "[sub(\"a\"; \"b\", \"c\")]",
223
    "sub(\"[^a-z]*(?<x>[a-z]+)\"; \"Z\\(.x)\"; \"g\")",
224
    "[.[]|[[sub(\", *\";\":\")], [gsub(\", *\";\":\")], [scan(\", *\")]]]",
225
    "[.[]|[[sub(\", +\";\":\")], [gsub(\", +\";\":\")], [scan(\", +\")]]]",
226
    "sub(\"^(?<head>.)\"; \"Head=\\(.head) Tail=\")",
227
    "[test(\"ā\")]",
228
    ".[] | test(\"a b c # spaces are ignored\"; \"ix\")",
229
    "test(\"foo\")",
230
    "to_entries",
231
    "[., tojson]",
232
    "[.[]|tojson]",
233
    "[.[]|tojson|fromjson]",
234
    ".[] | tonumber",
235
    "[.[] | tonumber?]",
236
    ".[] | tostring",
237
    "[.[]|tostring]",
238
    "transpose",
239
    "[true, false | not]",
240
    "(true, false) or false",
241
    "(true, true) and (true, false)",
242
    "truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]])",
243
    "[.[]|try .a]",
244
    "unique",
245
    "unique_by(.foo)",
246
    "unique_by(length)",
247
    ".user, .projects[]",
248
    "[.user, .projects[]]",
249
    "{(.user): .titles}",
250
    "{user, title: .titles[]}",
251
    "utf8bytelength",
252
    "walk(if type == \"array\" then sort else . end)",
253
    "walk( if type == \"object\" then with_entries( .key |= sub( \"^_+\"; "
254
    "\"\") ) else . end )",
255
    "[while(.<100; .*2)]",
256
    "with_entries(.key |= \"KEY_\" + .)",
257
    ". - [\"xml\", \"yaml\"]",
258
};
259
260
// Fuzzer inspired by /src/jq_test.c
261
// The goal is to have the fuzzer execute the functions:
262
// jq_compile -> jv_parse -> jq_next.
263
12.9k
extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
264
12.9k
  FuzzedDataProvider fdp(data, size);
265
12.9k
  std::string parse_payload1 = fdp.ConsumeRandomLengthString();
266
12.9k
  std::string parse_payload2 = fdp.ConsumeRandomLengthString();
267
268
12.9k
  int idx = fdp.ConsumeIntegralInRange<int>(
269
12.9k
      0, (sizeof(jq_progs) / sizeof(char *)) - 1);
270
271
12.9k
  jq_state *jq = NULL;
272
12.9k
  jq = jq_init();
273
12.9k
  if (jq != NULL) {
274
12.9k
    jq_set_attr(jq, jv_string("JQ_ORIGIN"), jv_string("/tmp/"));
275
276
12.9k
    if (jq_compile(jq, jq_progs[idx])) {
277
      // Process to jv_parse and then jv_next
278
12.0k
      jv input = jv_parse(parse_payload1.c_str());
279
12.0k
      if (jv_is_valid(input)) {
280
10.8k
        jq_start(jq, input, 0);
281
10.8k
        jv next = jv_parse(parse_payload2.c_str());
282
10.8k
        if (jv_is_valid(next)) {
283
10.4k
          jv actual = jq_next(jq);
284
10.4k
          jv_free(actual);
285
10.4k
        }
286
10.8k
        jv_free(next);
287
10.8k
      } else {
288
        // Only free if input is invalid as otherwise jq_teardown
289
        // frees it.
290
1.19k
        jv_free(input);
291
1.19k
      }
292
12.0k
    }
293
12.9k
  }
294
12.9k
  jq_teardown(&jq);
295
296
12.9k
  return 0;
297
12.9k
}