/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 | } |