2023-12-06 22:46:45 +00:00
|
|
|
#include <fuzzer/FuzzedDataProvider.h>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "jq.h"
|
|
|
|
#include "jv.h"
|
|
|
|
|
|
|
|
|
|
|
|
const char *jq_progs[] = {
|
|
|
|
". / \", \"",
|
|
|
|
".[]",
|
|
|
|
"$ENV.PAGER",
|
|
|
|
".[0]",
|
|
|
|
". < 0.12345678901234567890123456788",
|
|
|
|
".[] == 1",
|
|
|
|
".[] | (1 / .)?",
|
|
|
|
"10 / . * 3",
|
|
|
|
"[1,2,empty,3]",
|
|
|
|
"1, empty, 2",
|
|
|
|
"[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]",
|
|
|
|
".[-2:]",
|
|
|
|
".[-2]",
|
|
|
|
".[2]",
|
|
|
|
"[ .[] | . * 2]",
|
|
|
|
".[2:4]",
|
|
|
|
"(. + 2) * 5",
|
|
|
|
".[:3]",
|
|
|
|
".[4,2]",
|
|
|
|
"42 and \"a string\"",
|
|
|
|
"4 - .a",
|
|
|
|
". < 5",
|
|
|
|
".. | .a?",
|
|
|
|
"[.[] | .a?]",
|
|
|
|
".a + 1",
|
|
|
|
"{a: 1} + {b: 2} + {c: 3} + {a: 42}",
|
|
|
|
".a + .b",
|
|
|
|
".a = .b",
|
|
|
|
".a |= .b",
|
|
|
|
"add",
|
|
|
|
"all",
|
|
|
|
".a + null",
|
|
|
|
"any",
|
|
|
|
".[] as [$a, $b] | {a: $a, b: $b}",
|
|
|
|
". as [$a, $b, {c: $c}] | $a + $b + $c",
|
|
|
|
".[] as {$a, $b, c: {$d}} ?// {$a, $b, c: [{$e}]} | {$a, $b, $d, $e}",
|
|
|
|
".[] as {$a, $b, c: {$d, $e}} ?// {$a, $b, c: [{$d, $e}]} | {$a, $b, "
|
|
|
|
"$d, $e}",
|
2023-12-10 15:22:03 +01:00
|
|
|
".[] as [$a] ?// [$b] | if $a != null then error(\"err: \\($a)\") else "
|
2023-12-06 22:46:45 +00:00
|
|
|
"{$a,$b} end",
|
|
|
|
". as $big | [$big, $big + 1] | map(. > "
|
|
|
|
"10000000000000000000000000000000)",
|
|
|
|
". as $dot|fromstream($dot|tostream)|.==$dot",
|
|
|
|
". as $i|[(.*2|. as $i| $i), $i]",
|
|
|
|
"ascii_upcase",
|
|
|
|
".bar as $x | .foo | . + $x",
|
|
|
|
"@base64",
|
|
|
|
"@base64d",
|
|
|
|
". == {\"b\": {\"d\": (4 + 1e-20), \"c\": 3}, \"a\":1}",
|
|
|
|
"bsearch(0)",
|
|
|
|
"bsearch(4) as $ix | if $ix < 0 then .[-(1+$ix)] = 4 else . end",
|
|
|
|
"capture(\"(?<a>[a-z]+)-(?<n>[0-9]+)\")",
|
|
|
|
"capture(\"(?<a>[a-z]+)-(?<n>[0-9]+)\")",
|
|
|
|
"combinations",
|
|
|
|
"combinations(2)",
|
|
|
|
"contains(\"bar\")",
|
|
|
|
"contains([\"baz\", \"bar\"])",
|
|
|
|
"contains([\"bazzzzz\", \"bar\"])",
|
|
|
|
"contains({foo: 12, bar: [{barp: 15}]})",
|
|
|
|
"def addvalue(f): f as $x | map(. + $x); addvalue(.[0])",
|
|
|
|
"def addvalue(f): . + [f]; map(addvalue(.[0]))",
|
|
|
|
"def while(cond; update): def _while: if cond then ., (update | "
|
|
|
|
"_while) else empty end; _while; [while(.<100; .*2)]",
|
|
|
|
"del(.[1, 2])",
|
|
|
|
"del(.foo)",
|
|
|
|
"delpaths([[\"a\",\"b\"]])",
|
|
|
|
"empty // 42",
|
|
|
|
"[.[]|endswith(\"foo\")]",
|
|
|
|
"env.PAGER",
|
|
|
|
"explode",
|
|
|
|
". == false",
|
|
|
|
"(false, null, 1) // 42",
|
|
|
|
"(false, null, 1) | . // 42",
|
|
|
|
"flatten",
|
|
|
|
"flatten(1)",
|
|
|
|
"floor",
|
|
|
|
".[\"foo\"]",
|
|
|
|
".[\"foo\"]?",
|
|
|
|
".foo",
|
|
|
|
".foo?",
|
|
|
|
".foo[]",
|
|
|
|
"[.foo?]",
|
|
|
|
".foo += 1",
|
|
|
|
".foo // 42",
|
|
|
|
".foo, .bar",
|
|
|
|
"foreach .[] as $item (0; . + $item)",
|
|
|
|
"foreach .[] as $item (0; . + $item; [$item, . * 2])",
|
|
|
|
"foreach .[] as $item (0; . + 1; {index: ., $item})",
|
|
|
|
"fromdate",
|
|
|
|
"from_entries",
|
|
|
|
"fromstream(1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]]))",
|
|
|
|
"getpath([\"a\",\"b\"])",
|
|
|
|
"[getpath([\"a\",\"b\"], [\"a\",\"c\"])]",
|
|
|
|
"group_by(.foo)",
|
|
|
|
"[.[] | gsub(\", \"; \":\")]",
|
|
|
|
"gsub(\"$\"; \"a\"; \"g\")",
|
|
|
|
"gsub(\"^\"; \"a\")",
|
2023-12-10 15:22:03 +01:00
|
|
|
"[gsub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", "
|
2023-12-06 22:46:45 +00:00
|
|
|
"\"c\")]",
|
|
|
|
"gsub(\"^.*?a\"; \"b\")",
|
|
|
|
"gsub(\"^.*a\"; \"b\")",
|
|
|
|
"gsub(\"a\";\"b\")",
|
|
|
|
"gsub(\"\"; \"a\"; \"g\")",
|
|
|
|
"gsub(\"\"; \"a\"; \"g\")",
|
2023-12-10 15:22:03 +01:00
|
|
|
"gsub(\"[^a-z]*(?<x>[a-z]*)\"; \"Z\\(.x)\")",
|
|
|
|
"gsub(\"\\b(?<x>.)\"; \"\\(.x|ascii_downcase)\")",
|
|
|
|
"gsub(\"(?<d>\\d)\"; \":\\(.d);\")",
|
2023-12-06 22:46:45 +00:00
|
|
|
"gsub(\"^\"; \"\"; \"g\")",
|
|
|
|
"[gsub(\"p\"; \"a\", \"b\")]",
|
|
|
|
"gsub(\"(?=u)\"; \"u\")",
|
|
|
|
"gsub(\"(.*)\"; \"\"; \"x\")",
|
2023-12-10 15:22:03 +01:00
|
|
|
"gsub(\"(?<x>.)[^a]*\"; \"+\\(.x)-\")",
|
|
|
|
"gsub(\"(?<x>.)(?<y>[0-9])\"; \"\\(.x|ascii_downcase)\\(.y)\")",
|
2023-12-06 22:46:45 +00:00
|
|
|
"@html",
|
|
|
|
"if . == 0 then \"zero\" elif . == 1 then \"one\" else \"many\" "
|
|
|
|
"end",
|
|
|
|
"implode",
|
|
|
|
"index(\", \")",
|
|
|
|
"index(1)",
|
|
|
|
"index([1,2])",
|
|
|
|
"indices(\", \")",
|
|
|
|
"indices(1)",
|
|
|
|
"indices([1,2])",
|
|
|
|
".[] | (infinite * .) < 0",
|
|
|
|
"infinite, nan | type",
|
|
|
|
".[] | in({\"foo\": 42})",
|
|
|
|
"inside({\"foo\": 12, \"bar\":[1,2,{\"barp\":12, \"blip\":13}]})",
|
|
|
|
"inside({\"foo\": 12, \"bar\":[1,2,{\"barp\":12, \"blip\":13}]})",
|
|
|
|
"inside(\"foobar\")",
|
|
|
|
"inside([\"foobar\", \"foobaz\", \"blarp\"])",
|
|
|
|
"inside([\"foobar\", \"foobaz\", \"blarp\"])",
|
|
|
|
"isempty(.[])",
|
|
|
|
"isempty(.[])",
|
|
|
|
"isempty(empty)",
|
|
|
|
"join(\" \")",
|
|
|
|
"join(\", \")",
|
|
|
|
"keys",
|
|
|
|
"keys",
|
|
|
|
".[] | length",
|
|
|
|
"[limit(3;.[])]",
|
|
|
|
"[.[]|ltrimstr(\"foo\")]",
|
|
|
|
"map(., .)",
|
|
|
|
"map(.+1)",
|
|
|
|
"map([., . == 1]) | tojson",
|
|
|
|
"map(abs)",
|
|
|
|
"map(has(2))",
|
|
|
|
"map(has(\"foo\"))",
|
|
|
|
"map(in([0,1]))",
|
|
|
|
"map(select(. >= 2))",
|
|
|
|
"map(type)",
|
|
|
|
"map_values(.+1)",
|
|
|
|
"map_values(. // empty)",
|
|
|
|
"match(\"(abc)+\"; \"g\")",
|
|
|
|
"[match(\"a\"; \"gi\")]",
|
|
|
|
"[match(\".+?\\b\")]",
|
|
|
|
"[match([\"(bar)\"])]",
|
|
|
|
"match(\"foo\")",
|
|
|
|
"[match([\"foo (?<bar123>bar)? foo\", \"ig\"])]",
|
|
|
|
"match(\"foo (?<bar123>bar)? foo\"; \"ig\")",
|
|
|
|
"match([\"foo\", \"ig\"])",
|
|
|
|
"[match(\"\"; \"g\")]",
|
|
|
|
"[ match(\".\"; \"g\")] | length",
|
|
|
|
"[match(\"( )*\"; \"gn\")]",
|
|
|
|
"max_by(.foo)",
|
|
|
|
"min",
|
|
|
|
".[] | .name",
|
|
|
|
".[]|numbers",
|
|
|
|
"[path(..)]",
|
|
|
|
"path(.a[0].b)",
|
|
|
|
"[paths]",
|
|
|
|
"[paths(type == \"number\")]",
|
|
|
|
"pick(.[2], .[0], .[0])",
|
|
|
|
"pick(.a, .b.c, .x)",
|
|
|
|
"[range(0; 10; -1)]",
|
|
|
|
"[range(0; 10; 3)]",
|
|
|
|
"[range(0; -5; -1)]",
|
|
|
|
"[range(2; 4)]",
|
|
|
|
"range(2; 4)",
|
|
|
|
"[range(4)]",
|
|
|
|
"[range(.)]|[first, last, nth(5)]",
|
|
|
|
"recurse",
|
|
|
|
"recurse(. * .; . < 20)",
|
|
|
|
"recurse(.foo[])",
|
|
|
|
"reduce .[] as [$i,$j] (0; . + $i * $j)",
|
|
|
|
"reduce .[] as $item (0; . + $item)",
|
|
|
|
"reduce .[] as {$x,$y} (null; .x += $x | .y += [$y])",
|
|
|
|
"[repeat(.*2, error)?]",
|
|
|
|
"reverse",
|
|
|
|
"rindex(\", \")",
|
|
|
|
"rindex(1)",
|
|
|
|
"rindex([1,2])",
|
|
|
|
"[.[]|rtrimstr(\"foo\")]",
|
|
|
|
"[.[] | scan(\", \")]",
|
|
|
|
"[.[] | scan(\"b+\"; \"i\")]",
|
|
|
|
"scan(\"c\")",
|
|
|
|
".[] | select(.id == \"second\")",
|
|
|
|
"(..|select(type==\"boolean\")) |= if . then 1 else 0 end",
|
|
|
|
"setpath([0,\"a\"]; 1)",
|
|
|
|
"setpath([\"a\",\"b\"]; 1)",
|
|
|
|
"setpath([\"a\",\"b\"]; 1)",
|
2023-12-10 15:22:03 +01:00
|
|
|
"@sh \"echo \\(.)\"",
|
2023-12-06 22:46:45 +00:00
|
|
|
"sort",
|
|
|
|
"sort_by(.foo)",
|
|
|
|
"sort_by(.foo, .bar)",
|
|
|
|
"split(\", *\"; null)",
|
|
|
|
"splits(\", *\")",
|
|
|
|
"sqrt",
|
|
|
|
"[.[]|startswith(\"foo\")]",
|
|
|
|
"strptime(\"%Y-%m-%dT%H:%M:%SZ\")",
|
|
|
|
"strptime(\"%Y-%m-%dT%H:%M:%SZ\")|mktime",
|
2023-12-10 15:22:03 +01:00
|
|
|
"[sub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\")]",
|
|
|
|
"[sub(\"(?<a>.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", "
|
2023-12-06 22:46:45 +00:00
|
|
|
"\"c\")]",
|
|
|
|
"[sub(\"a\"; \"b\", \"c\")]",
|
2023-12-10 15:22:03 +01:00
|
|
|
"sub(\"[^a-z]*(?<x>[a-z]+)\"; \"Z\\(.x)\"; \"g\")",
|
2023-12-06 22:46:45 +00:00
|
|
|
"[.[]|[[sub(\", *\";\":\")], [gsub(\", *\";\":\")], [scan(\", *\")]]]",
|
|
|
|
"[.[]|[[sub(\", +\";\":\")], [gsub(\", +\";\":\")], [scan(\", +\")]]]",
|
2023-12-10 15:22:03 +01:00
|
|
|
"sub(\"^(?<head>.)\"; \"Head=\\(.head) Tail=\")",
|
2023-12-06 22:46:45 +00:00
|
|
|
"[test(\"ā\")]",
|
|
|
|
".[] | test(\"a b c # spaces are ignored\"; \"ix\")",
|
|
|
|
"test(\"foo\")",
|
|
|
|
"to_entries",
|
|
|
|
"[., tojson]",
|
|
|
|
"[.[]|tojson]",
|
|
|
|
"[.[]|tojson|fromjson]",
|
|
|
|
".[] | tonumber",
|
|
|
|
"[.[] | tonumber?]",
|
|
|
|
".[] | tostring",
|
|
|
|
"[.[]|tostring]",
|
|
|
|
"transpose",
|
|
|
|
"[true, false | not]",
|
|
|
|
"(true, false) or false",
|
|
|
|
"(true, true) and (true, false)",
|
|
|
|
"truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]])",
|
|
|
|
"[.[]|try .a]",
|
|
|
|
"unique",
|
|
|
|
"unique_by(.foo)",
|
|
|
|
"unique_by(length)",
|
|
|
|
".user, .projects[]",
|
|
|
|
"[.user, .projects[]]",
|
|
|
|
"{(.user): .titles}",
|
|
|
|
"{user, title: .titles[]}",
|
|
|
|
"utf8bytelength",
|
|
|
|
"walk(if type == \"array\" then sort else . end)",
|
|
|
|
"walk( if type == \"object\" then with_entries( .key |= sub( \"^_+\"; "
|
|
|
|
"\"\") ) else . end )",
|
|
|
|
"[while(.<100; .*2)]",
|
|
|
|
"with_entries(.key |= \"KEY_\" + .)",
|
|
|
|
". - [\"xml\", \"yaml\"]",
|
|
|
|
};
|
|
|
|
|
|
|
|
// Fuzzer inspired by /src/jq_test.c
|
|
|
|
// The goal is to have the fuzzer execute the functions:
|
|
|
|
// jq_compile -> jv_parse -> jq_next.
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
|
|
|
|
FuzzedDataProvider fdp(data, size);
|
|
|
|
std::string parse_payload1 = fdp.ConsumeRandomLengthString();
|
|
|
|
std::string parse_payload2 = fdp.ConsumeRandomLengthString();
|
|
|
|
|
|
|
|
int idx = fdp.ConsumeIntegralInRange<int>(
|
|
|
|
0, (sizeof(jq_progs) / sizeof(char *)) - 1);
|
|
|
|
|
|
|
|
jq_state *jq = NULL;
|
|
|
|
jq = jq_init();
|
|
|
|
if (jq != NULL) {
|
|
|
|
jq_set_attr(jq, jv_string("JQ_ORIGIN"), jv_string("/tmp/"));
|
|
|
|
|
|
|
|
if (jq_compile(jq, jq_progs[idx])) {
|
|
|
|
// Process to jv_parse and then jv_next
|
|
|
|
jv input = jv_parse(parse_payload1.c_str());
|
|
|
|
if (jv_is_valid(input)) {
|
|
|
|
jq_start(jq, input, 0);
|
|
|
|
jv next = jv_parse(parse_payload2.c_str());
|
|
|
|
if (jv_is_valid(next)) {
|
|
|
|
jv actual = jq_next(jq);
|
|
|
|
jv_free(actual);
|
|
|
|
}
|
|
|
|
jv_free(next);
|
|
|
|
} else {
|
|
|
|
// Only free if input is invalid as otherwise jq_teardown
|
|
|
|
// frees it.
|
|
|
|
jv_free(input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jq_teardown(&jq);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|