#include #include #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}", ".[] as [$a] ?// [$b] | if $a != null then error(\"err: \\($a)\") else " "{$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-z]+)-(?[0-9]+)\")", "capture(\"(?[a-z]+)-(?[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\")", "[gsub(\"(?.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", " "\"c\")]", "gsub(\"^.*?a\"; \"b\")", "gsub(\"^.*a\"; \"b\")", "gsub(\"a\";\"b\")", "gsub(\"\"; \"a\"; \"g\")", "gsub(\"\"; \"a\"; \"g\")", "gsub(\"[^a-z]*(?[a-z]*)\"; \"Z\\(.x)\")", "gsub(\"\\b(?.)\"; \"\\(.x|ascii_downcase)\")", "gsub(\"(?\\d)\"; \":\\(.d);\")", "gsub(\"^\"; \"\"; \"g\")", "[gsub(\"p\"; \"a\", \"b\")]", "gsub(\"(?=u)\"; \"u\")", "gsub(\"(.*)\"; \"\"; \"x\")", "gsub(\"(?.)[^a]*\"; \"+\\(.x)-\")", "gsub(\"(?.)(?[0-9])\"; \"\\(.x|ascii_downcase)\\(.y)\")", "@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 (?bar)? foo\", \"ig\"])]", "match(\"foo (?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)", "@sh \"echo \\(.)\"", "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", "[sub(\"(?.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\")]", "[sub(\"(?.)\"; \"\\(.a|ascii_upcase)\", \"\\(.a|ascii_downcase)\", " "\"c\")]", "[sub(\"a\"; \"b\", \"c\")]", "sub(\"[^a-z]*(?[a-z]+)\"; \"Z\\(.x)\"; \"g\")", "[.[]|[[sub(\", *\";\":\")], [gsub(\", *\";\":\")], [scan(\", *\")]]]", "[.[]|[[sub(\", +\";\":\")], [gsub(\", +\";\":\")], [scan(\", +\")]]]", "sub(\"^(?.)\"; \"Head=\\(.head) Tail=\")", "[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( 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; }