mirror of
https://github.com/jqlang/jq.git
synced 2026-10-11 21:49:50 +00:00
A call passing more than 4095 arguments at the start of a nested function body aborted jq after reporting the compile errors, with "Assertion failed: (nemb > 0 && sz > 0), function jv_mem_calloc" and exit status 134. Stop compiling a function before its bytecode is allocated when it has compile errors, since the bytecode is only generated and used when compilation succeeds. jq now prints the same compile errors followed by "jq: 2 compile errors" and exits with status 3, as it does for other compile errors, instead of crashing.
1000 lines
32 KiB
Bash
Executable File
1000 lines
32 KiB
Bash
Executable File
#!/bin/sh -x
|
|
|
|
. "${0%/*}/setup" "$@"
|
|
|
|
msys=false
|
|
mingw=false
|
|
sunos=false
|
|
netbsd=false
|
|
case "$(uname -s)" in
|
|
MSYS*) msys=true;;
|
|
MINGW*) mingw=true;;
|
|
SunOS*) sunos=true;;
|
|
NetBSD*) netbsd=true;;
|
|
esac
|
|
|
|
JQ_NO_B=$JQ
|
|
JQ="$JQ -b"
|
|
|
|
# On Solaris, GNU tools are available in /usr/gnu. This script should prefer
|
|
# them over the native tools, because the native versions may lack some
|
|
# command-line options the script relies on.
|
|
$sunos && PATH="/usr/gnu/bin:$PATH"
|
|
|
|
PATH=$JQBASEDIR:$PATH $JQBASEDIR/tests/jq-f-test.sh > /dev/null
|
|
|
|
SHELL=/bin/sh
|
|
export SHELL
|
|
|
|
unset JQ_COLORS
|
|
unset NO_COLOR
|
|
|
|
if [ -f "$JQBASEDIR/.libs/libinject_errors.so" ]; then
|
|
# Do some simple error injection tests to check that we're handling
|
|
# I/O errors correctly.
|
|
(
|
|
libinject=$JQBASEDIR/.libs/libinject_errors.so
|
|
cd $d
|
|
LD_PRELOAD=$libinject $JQ . /dev/null
|
|
touch fail_read
|
|
LD_PRELOAD=$libinject $JQ . fail_read && exit 2
|
|
touch fail_close
|
|
LD_PRELOAD=$libinject $JQ . fail_close && exit 2
|
|
true
|
|
)
|
|
fi
|
|
|
|
printf 'a\0b\nc\0d\ne' > $d/input
|
|
$VALGRIND $Q $JQ -Rse '. == "a\u0000b\nc\u0000d\ne"' $d/input
|
|
$VALGRIND $Q $JQ -Rne '[inputs] == ["a\u0000b", "c\u0000d", "e"]' $d/input
|
|
|
|
## Test constant folding
|
|
nref=$($VALGRIND $Q $JQ -n --debug-dump-disasm '"foo"' | wc -l)
|
|
for exp in '1+1' '1-1' '2*3' '9/3' '9%3' '9==3' '9!=3' \
|
|
'9<3' '9>3' '9<=3' '9>=3' '1+2*3-4/5%6' '"foo" + "bar"'; do
|
|
n=$($VALGRIND $Q $JQ -n --debug-dump-disasm "$exp" | wc -l)
|
|
if [ $n -ne $nref ]; then
|
|
echo "Constant expression folding didn't work: $exp"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
## Test UTF-8 BOM is stripped at the start of each input file
|
|
printf '\357\273\277[{"foo": 1}\n,{"foo": 2}\n]\n' > $d/bom1.json
|
|
printf '\357\273\277[{"foo": 3}\n,{"foo": 4}\n]\n' > $d/bom2.json
|
|
$VALGRIND $Q $JQ -e '.[0].foo == 1' $d/bom1.json
|
|
$VALGRIND $Q $JQ -se '. == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json $d/bom2.json
|
|
$VALGRIND $Q $JQ -ne '[inputs] == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json $d/bom2.json
|
|
$VALGRIND $Q $JQ -ne '[inputs] == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json - < $d/bom2.json
|
|
$VALGRIND $Q $JQ -Rne '[inputs] == ["[{\"foo\": 1}", ",{\"foo\": 2}", "]", "[{\"foo\": 3}", ",{\"foo\": 4}", "]"]' $d/bom1.json $d/bom2.json
|
|
$VALGRIND $Q $JQ -ne --slurpfile x $d/bom1.json '$x == [[{"foo":1},{"foo":2}]]'
|
|
$VALGRIND $Q $JQ -ne --rawfile x $d/bom1.json '$x == "[{\"foo\": 1}\n,{\"foo\": 2}\n]\n"'
|
|
|
|
## Test JSON sequence support
|
|
cat > $d/expected <<EOF
|
|
jq: ignoring parse error: Truncated value at line 2, column 5
|
|
jq: ignoring parse error: Truncated value at line 2, column 25
|
|
jq: ignoring parse error: Truncated value at line 2, column 41
|
|
EOF
|
|
printf '1\0362 3\n[0,1\036[4,5]true"ab"{"c":4\036{}{"d":5,"e":6"\036false\n'|$VALGRIND $Q $JQ -ces --seq '. == [2,3,[4,5],true,"ab",{},false]' > /dev/null 2> $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
cat > $d/expected <<EOF
|
|
jq: ignoring parse error: Truncated value at line 2, column 5
|
|
jq: ignoring parse error: Truncated value at line 2, column 25
|
|
jq: ignoring parse error: Truncated value at line 3, column 1
|
|
EOF
|
|
printf '1\0362 3\n[0,1\036[4,5]true"ab"{"c":4\036{}{"d":5,"e":6"false\n\036null'|$VALGRIND $Q $JQ -ces --seq '. == [2,3,[4,5],true,"ab",{},null]' > /dev/null 2> $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
# Note that here jq sees no inputs at all but it still succeeds because
|
|
# --seq ignores parse errors
|
|
cat > $d/expected <<EOF
|
|
jq: ignoring parse error: Unfinished abandoned text at EOF at line 1, column 4
|
|
EOF
|
|
printf '"foo' | $JQ -c --seq . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# with -e option should give 4 here as there's no valid output after
|
|
# ignoring parse errors with --seq.
|
|
printf '"foo' | $JQ -ce --seq . > $d/out 2>&1 || ret=$?
|
|
[ $ret -eq 4 ]
|
|
cmp $d/out $d/expected
|
|
|
|
# Numeric values truncated by EOF are ignored
|
|
cat > $d/expected <<EOF
|
|
jq: ignoring parse error: Unfinished abandoned text at EOF at line 1, column 1
|
|
EOF
|
|
printf '1' | $JQ -c --seq . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
cat > $d/expected <<EOF
|
|
jq: error (at <stdin>:1): Unfinished abandoned text at EOF at line 2, column 0
|
|
EOF
|
|
if printf '1\n' | $JQ -cen --seq '[inputs] == []' >/dev/null 2> $d/out; then
|
|
printf 'Error expected but jq exited successfully\n' 1>&2
|
|
exit 2
|
|
fi
|
|
cmp $d/out $d/expected
|
|
|
|
# Test control characters for #2909
|
|
cat > $d/expected <<EOF
|
|
jq: parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 1, column 3
|
|
EOF
|
|
for i in 1 2 30 31; do
|
|
if printf "\"$(printf '\\%03o' $i)\"" | $JQ '.' > $d/out 2>&1; then
|
|
printf 'Error expected but jq exited successfully\n' 1>&2
|
|
exit 2
|
|
fi
|
|
cmp $d/out $d/expected
|
|
done
|
|
printf '" ~\\u007f"\n' > $d/expected
|
|
printf "\"$(printf '\\%03o' 32 126 127)\"" | $JQ '.' > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# Regression test for #3110: a raw NUL byte outside of a string must be a clean
|
|
# parse error, not silently truncate the surrounding token. Previously
|
|
# `printf '12\0003'` printed 12 and dropped the trailing 3.
|
|
cat > $d/expected <<EOF
|
|
jq: parse error: Invalid character at line 1, column 3
|
|
EOF
|
|
if printf '12\0003' | $JQ '.' > $d/out 2>&1; then
|
|
printf 'Error expected but jq exited successfully\n' 1>&2
|
|
exit 2
|
|
fi
|
|
cmp $d/out $d/expected
|
|
# A NUL at the very start of the input is rejected too.
|
|
cat > $d/expected <<EOF
|
|
jq: parse error: Invalid character at line 1, column 1
|
|
EOF
|
|
if printf '\000' | $JQ '.' > $d/out 2>&1; then
|
|
printf 'Error expected but jq exited successfully\n' 1>&2
|
|
exit 2
|
|
fi
|
|
cmp $d/out $d/expected
|
|
|
|
## Test --exit-status
|
|
data='{"i": 1}\n{"i": 2}\n{"i": 3}\n'
|
|
printf "$data" | $JQ --exit-status 'select(.i==1)' > /dev/null 2>&1
|
|
printf "$data" | $JQ --exit-status 'select(.i==2)' > /dev/null 2>&1
|
|
printf "$data" | $JQ --exit-status 'select(.i==3)' > /dev/null 2>&1
|
|
ret=0
|
|
printf "$data" | $JQ --exit-status 'select(.i==4)' > /dev/null 2>&1 || ret=$?
|
|
[ $ret -eq 4 ]
|
|
ret=0
|
|
printf "$data" | $JQ --exit-status 'select(.i==2) | false' > /dev/null 2>&1 || ret=$?
|
|
[ $ret -eq 1 ]
|
|
printf "$data" | $JQ --exit-status 'select(.i==2) | true' > /dev/null 2>&1
|
|
|
|
|
|
# Regression test for #951
|
|
printf '"a\n' > $d/input
|
|
if $VALGRIND $Q $JQ -e . $d/input; then
|
|
printf 'Issue #951 is back?\n' 1>&2
|
|
exit 2
|
|
fi
|
|
|
|
# Regression test for #2146
|
|
if echo "foobar" | $JQ .; then
|
|
printf 'Issue #2146 is back?\n' 1>&2
|
|
exit 1
|
|
elif [ $? -ne 5 ]; then
|
|
echo "Invalid input had wrong error code" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Regression test for #2367; make sure to call jq twice
|
|
if ! echo '{"a": 1E9999999999}' | $JQ . | $JQ -e .a; then
|
|
printf 'Issue #2367 is back?\n' 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Regression test for #1534
|
|
echo "[1,2,3,4]" > $d/expected
|
|
printf "[1,2][3,4]" | $JQ -cs add > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
printf "[1,2][3,4]\n" | $JQ -cs add > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# Regression test for #3273
|
|
echo "[[[0],1],[[0]],[[0],2],[[0]]]" > $d/expected
|
|
printf "[1][2]" | $JQ -c -s --stream . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
printf "[1][2]\n" | $JQ -c -s --stream . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# Regression test for --raw-output0
|
|
printf "a\0b\0" > $d/expected
|
|
printf '["a", "b"]' | $VALGRIND $Q $JQ --raw-output0 '.[]' > $d/out
|
|
cmp $d/out $d/expected
|
|
printf "a\0" > $d/expected
|
|
if printf '["a", "c\\u0000d", "b"]' | $VALGRIND $Q $JQ --raw-output0 '.[]' > $d/out; then
|
|
echo "Should exit error on string containing NUL with --raw-output0" 1>&2
|
|
exit 1
|
|
elif [ $? -ne 5 ]; then
|
|
echo "Invalid error code" 1>&2
|
|
exit 1
|
|
else
|
|
cmp $d/out $d/expected
|
|
fi
|
|
|
|
# Regression tests for #3194
|
|
echo 42 > $d/expected
|
|
$JQ -nn 42 > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
$JQ -nL. 42 > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
$JQ -nL . 42 > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
$JQ -h > $d/expected 2>&1
|
|
$JQ -hV > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
$JQ -h -V > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
$JQ -V > $d/expected 2>&1
|
|
$JQ -Vh > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
$JQ -V -h > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# CRLF line break support #1219
|
|
if ! x=$($JQ -n "$(printf '1\r\n+\r\n2')") || [ "$x" != '3' ]; then
|
|
echo 'CRLF line break support failed?' 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
## Test streaming parser
|
|
|
|
## If we add an option to stream to the `import ... as $symbol;` directive
|
|
## then we can move these tests into tests/all.test.
|
|
$VALGRIND $Q $JQ -c '. as $d|path(..) as $p|$d|getpath($p)|select((type|. != "array" and . != "object") or length==0)|[$p,.]' < "$JQTESTDIR/torture/input0.json" > $d/out0
|
|
$VALGRIND $Q $JQ --stream -c '.|select(length==2)' < "$JQTESTDIR/torture/input0.json" > $d/out1
|
|
diff $d/out0 $d/out1
|
|
|
|
printf '["Unfinished JSON term at EOF at line 1, column 1",[0]]\n' > $d/expected
|
|
printf '[' | $VALGRIND $Q $JQ --stream-errors -c . > $d/out 2>&1
|
|
diff $d/out $d/expected
|
|
|
|
|
|
## XXX This test can be moved to tests/all.test _now_
|
|
clean=false
|
|
if which seq > /dev/null 2>&1; then
|
|
# XXX We should try every prefix of input0.json, but that makes this
|
|
# test very, very slow when run with valgrind, and the whole point
|
|
# is to run it with valgrind.
|
|
#
|
|
#len=$(wc -c < "$JQTESTDIR/torture/input0.json")
|
|
if [ -z "$VALGRIND" ]; then
|
|
start=1
|
|
end=$(wc -c < "$JQTESTDIR/torture/input0.json")
|
|
else
|
|
start=120
|
|
end=151
|
|
fi
|
|
for i in $(seq $start $end); do
|
|
dd "if=tests/torture/input0.json" bs=$i count=1 2>/dev/null |
|
|
$VALGRIND $JQ -c . > $d/out0 2>$d/err || true
|
|
if [ -n "$VALGRIND" ]; then
|
|
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d/err > /dev/null
|
|
else
|
|
tail -n1 -- "$d/err" | grep -Ei 'assert|abort|core' && false
|
|
fi
|
|
|
|
dd "if=tests/torture/input0.json" bs=$i count=1 2>/dev/null |
|
|
$VALGRIND $JQ -cn --stream 'fromstream(inputs)' > $d/out1 2>$d/err || true
|
|
if [ -n "$VALGRIND" ]; then
|
|
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d/err > /dev/null
|
|
else
|
|
tail -n1 -- "$d/err" | grep -Ei 'assert|abort|core' && false
|
|
fi
|
|
|
|
diff $d/out0 $d/out1
|
|
done
|
|
else
|
|
echo "Not doing torture tests"
|
|
fi
|
|
|
|
## Regression test for issue #2378 assert when stream parse broken object pair
|
|
echo '{"a":1,"b",' | $JQ --stream > /dev/null 2> $d/err || true
|
|
grep 'Objects must consist of key:value pairs' $d/err > /dev/null
|
|
|
|
## Regression tests for issue #2463 assert when stream parse non-scalar object key
|
|
echo '{{"a":"b"}}' | $JQ --stream > /dev/null 2> $d/err || true
|
|
grep "Expected string key after '{', not '{'" $d/err > /dev/null
|
|
echo '{"x":"y",{"a":"b"}}' | $JQ --stream > /dev/null 2> $d/err || true
|
|
grep "Expected string key after ',' in object, not '{'" $d/err > /dev/null
|
|
echo '{["a","b"]}' | $JQ --stream > /dev/null 2> $d/err || true
|
|
grep "Expected string key after '{', not '\\['" $d/err > /dev/null
|
|
echo '{"x":"y",["a","b"]}' | $JQ --stream > /dev/null 2> $d/err || true
|
|
grep "Expected string key after ',' in object, not '\\['" $d/err > /dev/null
|
|
|
|
# debug, stderr
|
|
$VALGRIND $Q $JQ -n '"test", {} | debug, stderr' >/dev/null
|
|
$JQ -n -c -j '"hello\nworld", null, [false, 0], {"foo":["bar"]}, "\n" | stderr' >$d/out 2>$d/err
|
|
cat > $d/expected <<'EOF'
|
|
hello
|
|
worldnull[false,0]{"foo":["bar"]}
|
|
EOF
|
|
cmp $d/out $d/expected
|
|
cmp $d/err $d/expected
|
|
|
|
# --arg, --argjson, $ARGS.named
|
|
$VALGRIND $JQ -n -c --arg foo 1 --argjson bar 2 '{$foo, $bar} | ., . == $ARGS.named' > $d/out
|
|
printf '{"foo":"1","bar":2}\ntrue\n' > $d/expected
|
|
cmp $d/out $d/expected
|
|
|
|
# --slurpfile, --rawfile
|
|
$VALGRIND $JQ -n --slurpfile foo $JQBASEDIR/tests/modules/data.json \
|
|
--rawfile bar $JQBASEDIR/tests/modules/data.json '{$foo, $bar}' > $d/out
|
|
cat > $d/expected <<'EOF'
|
|
{
|
|
"foo": [
|
|
{
|
|
"this": "is a test",
|
|
"that": "is too"
|
|
}
|
|
],
|
|
"bar": "{\n \"this\": \"is a test\",\n \"that\": \"is too\"\n}\n"
|
|
}
|
|
EOF
|
|
cmp $d/out $d/expected
|
|
|
|
# --args, --jsonargs, $ARGS.positional
|
|
$VALGRIND $JQ -n -c --args '$ARGS.positional' foo bar baz > $d/out
|
|
printf '["foo","bar","baz"]\n' > $d/expected
|
|
cmp $d/out $d/expected
|
|
$VALGRIND $JQ -n -c --jsonargs '$ARGS.positional' null true '[]' '{}' > $d/out
|
|
printf '[null,true,[],{}]\n' > $d/expected
|
|
cmp $d/out $d/expected
|
|
$VALGRIND $JQ -n -c '$ARGS.positional' --args foo 1 --jsonargs 2 '{}' --args 3 4 > $d/out
|
|
printf '["foo","1",2,{},"3","4"]\n' > $d/expected
|
|
cmp $d/out $d/expected
|
|
$VALGRIND $JQ -n -c '$ARGS.positional' --args --jsonargs > $d/out
|
|
printf '[]\n' > $d/expected
|
|
cmp $d/out $d/expected
|
|
|
|
## Regression test for issue #2572 assert when using --jsonargs and invalid JSON
|
|
$VALGRIND $JQ -n --jsonargs null invalid && EC=$? || EC=$?
|
|
if [ "$EC" -ne 2 ]; then
|
|
echo "--jsonargs exited with wrong exit code, expected 2 got $EC" 1>&2
|
|
exit 1
|
|
fi
|
|
# this tests the args_done code path "--"
|
|
$VALGRIND $JQ -n --jsonargs null -- invalid && EC=$? || EC=$?
|
|
if [ "$EC" -ne 2 ]; then
|
|
echo "--jsonargs exited with wrong exit code, expected 2 got $EC" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
## Fuzz parser
|
|
|
|
## XXX With a $(urandom) builtin we could move this test into tests/all.test
|
|
clean=false
|
|
if dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null; then
|
|
# Have a /dev/urandom, good
|
|
$VALGRIND $Q $JQ --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q $JQ --seq --stream . $d/rand >/dev/null 2>&1
|
|
dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null
|
|
$VALGRIND $Q $JQ --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q $JQ --seq --stream . $d/rand >/dev/null 2>&1
|
|
dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null
|
|
$VALGRIND $Q $JQ --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q $JQ --seq --stream . $d/rand >/dev/null 2>&1
|
|
fi
|
|
clean=true
|
|
|
|
## Test library/module system
|
|
|
|
# Check handling of ~/.jq; these can't move into jq_test.c yet because
|
|
# they depend on $HOME
|
|
if [ "$(HOME="$mods/home1" $VALGRIND $Q $JQ -nr fg)" != foobar ]; then
|
|
echo "Bug #479 appears to be back" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if $msys || $mingw; then
|
|
HOME_BAK=$HOME
|
|
unset HOME
|
|
if [ "$(USERPROFILE="$mods/home1" $VALGRIND $Q $JQ -nr foo)" != baz ]; then
|
|
echo "Bug #3104 regressed (sourcing %USERPROFILE%/.jq on Windows)" 1>&2
|
|
exit 1
|
|
fi
|
|
export HOME=$HOME_BAK
|
|
unset HOME_BAK
|
|
fi
|
|
|
|
if [ $(HOME="$mods/home1" $VALGRIND $Q $JQ --debug-dump-disasm -n fg | grep '^[a-z]' | wc -l) -ne 3 ]; then
|
|
echo "Binding too many defs into program" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! HOME="$mods/home2" $VALGRIND $Q $JQ -n 'include "g"; empty'; then
|
|
echo "Mishandling directory ~/.jq" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
(
|
|
cd "$JQBASEDIR" # so that relative library paths are guaranteed correct
|
|
if ! $VALGRIND $Q $JQ -L ./tests/modules -ne 'import "test_bind_order" as check; check::check==true'; then
|
|
echo "Issue #817 regression?" 1>&2
|
|
exit 1
|
|
fi
|
|
)
|
|
|
|
(
|
|
cd "$JQBASEDIR"
|
|
if ! $VALGRIND $Q $JQ -L tests/modules -ne 'import "test_bind_order" as check; check::check==true'; then
|
|
echo "Issue #817 regression?" 1>&2
|
|
exit 1
|
|
fi
|
|
)
|
|
|
|
# CVE-2026-44777: Circular imports should be detected
|
|
if $VALGRIND $JQ -L "$mods" -ne 'import "cycle_a" as a; null' 2> $d/out; then
|
|
echo "Mutual import should be rejected" 1>&2
|
|
exit 1
|
|
fi
|
|
if ! grep -q "circular import" $d/out; then
|
|
echo "Expected circular import error" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if $VALGRIND $JQ -L "$mods" -ne 'import "cycle_self" as s; null' 2> $d/out; then
|
|
echo "Self import should be rejected" 1>&2
|
|
exit 1
|
|
fi
|
|
if ! grep -q "circular import" $d/out; then
|
|
echo "Expected circular import error" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
## Halt
|
|
|
|
if ! $VALGRIND $Q $JQ -n halt; then
|
|
echo "jq halt didn't work as expected" 1>&2
|
|
exit 1
|
|
fi
|
|
if $VALGRIND $Q $VG_EXIT0 $JQ -n 'halt_error(1)'; then
|
|
echo "jq halt_error(1) didn't work as expected" 1>&2
|
|
exit 1
|
|
elif [ $? -ne 1 ]; then
|
|
echo "jq halt_error(1) had wrong error code" 1>&2
|
|
exit 1
|
|
fi
|
|
if $VALGRIND $Q $VG_EXIT0 $JQ -n 'halt_error(11)'; then
|
|
echo "jq halt_error(11) didn't work as expected" 1>&2
|
|
exit 1
|
|
elif [ $? -ne 11 ]; then
|
|
echo "jq halt_error(11) had wrong error code" 1>&2
|
|
exit 1
|
|
fi
|
|
for opt in '' -e; do
|
|
if $VALGRIND $Q $VG_EXIT0 $JQ $opt -n 'halt_error(-1)'; then
|
|
echo "jq $opt halt_error(-1) didn't work as expected" 1>&2
|
|
exit 1
|
|
elif [ $? -ne 255 ]; then
|
|
echo "jq $opt halt_error(-1) had wrong error code" 1>&2
|
|
exit 1
|
|
fi
|
|
done
|
|
if [ -n "$($VALGRIND $Q $JQ -n 'halt_error(1)' 2>&1)" ]; then
|
|
echo "jq halt_error(1) had unexpected output" 1>&2
|
|
exit 1
|
|
fi
|
|
if [ -n "$($VALGRIND $Q $JQ -n '"xyz\n" | halt_error(1)' 2>/dev/null)" ]; then
|
|
echo "jq halt_error(1) had unexpected output on stdout" 1>&2
|
|
exit 1
|
|
fi
|
|
if [ "$($VALGRIND $Q $JQ -n '"xy" | halt_error(1)' 2>&1 || echo "z")" != "xyz" ]; then
|
|
echo "jq halt_error(1) had unexpected output" 1>&2
|
|
exit 1
|
|
fi
|
|
if [ "$($VALGRIND $Q $JQ -n '"x\u0000y\u0000z" | halt_error(1)' 2>&1 | tr '\0' '.')" != "x.y.z" ]; then
|
|
echo "jq halt_error(1) had unexpected output" 1>&2
|
|
exit 1
|
|
fi
|
|
if [ "$($VALGRIND $Q $JQ -n '{"a":"xyz"} | halt_error(1)' 2>&1)" != '{"a":"xyz"}' ]; then
|
|
echo "jq halt_error(1) had unexpected output" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Check $JQ_COLORS
|
|
|
|
## Default colors, null input
|
|
$JQ -Ccn . > $d/color
|
|
printf '\033[0;90mnull\033[0m\n' > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set non-default color, null input
|
|
JQ_COLORS='4;31' $JQ -Ccn . > $d/color
|
|
printf '\033[4;31mnull\033[0m\n' > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set implicit empty color, null input
|
|
$JQ -Ccn . > $d/color
|
|
printf '\033[0;90mnull\033[0m\n' > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set explicit empty color, null input
|
|
JQ_COLORS=':' $JQ -Ccn . > $d/color
|
|
printf '\033[mnull\033[0m\n' > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Extra colors, null input
|
|
JQ_COLORS='::::::::' $JQ -Ccn . > $d/color
|
|
printf '\033[mnull\033[0m\n' > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Default colors, complex input
|
|
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[1;39m[\033[0m'
|
|
printf '\033[1;39m{\033[0m'
|
|
printf '\033[1;34m"a"\033[0m'
|
|
printf '\033[1;39m:\033[0m'
|
|
printf '\033[0;39mtrue\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[1;34m"b"\033[0m'
|
|
printf '\033[1;39m:\033[0m'
|
|
printf '\033[0;39mfalse\033[0m'
|
|
printf '\033[1;39m}\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;32m"abc"\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;39m123\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;90mnull\033[0m'
|
|
printf '\033[1;39m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set non-default colors, complex input
|
|
JQ_COLORS='0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
|
|
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[1;35m[\033[0m'
|
|
printf '\033[1;36m{\033[0m'
|
|
printf '\033[1;37m"a"\033[0m'
|
|
printf '\033[1;36m:\033[0m'
|
|
printf '\033[0;32mtrue\033[0m'
|
|
printf '\033[1;36m,\033[0m'
|
|
printf '\033[1;37m"b"\033[0m'
|
|
printf '\033[1;36m:\033[0m'
|
|
printf '\033[0;31mfalse\033[0m'
|
|
printf '\033[1;36m}\033[0m'
|
|
printf '\033[1;35m,\033[0m'
|
|
printf '\033[0;34m"abc"\033[0m'
|
|
printf '\033[1;35m,\033[0m'
|
|
printf '\033[0;33m123\033[0m'
|
|
printf '\033[1;35m,\033[0m'
|
|
printf '\033[0;30mnull\033[0m'
|
|
printf '\033[1;35m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set non-default colors only for literals, complex input
|
|
JQ_COLORS='0;37:0;31:0;35:0;34:0;36' \
|
|
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[1;39m[\033[0m'
|
|
printf '\033[1;39m{\033[0m'
|
|
printf '\033[1;34m"a"\033[0m'
|
|
printf '\033[1;39m:\033[0m'
|
|
printf '\033[0;35mtrue\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[1;34m"b"\033[0m'
|
|
printf '\033[1;39m:\033[0m'
|
|
printf '\033[0;31mfalse\033[0m'
|
|
printf '\033[1;39m}\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;36m"abc"\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;34m123\033[0m'
|
|
printf '\033[1;39m,\033[0m'
|
|
printf '\033[0;37mnull\033[0m'
|
|
printf '\033[1;39m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Default colors, complex input, indented
|
|
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[1;39m[\033[0m\n'
|
|
printf ' \033[1;39m{\033[0m\n'
|
|
printf ' \033[1;34m"a"\033[0m'
|
|
printf '\033[1;39m:\033[0m '
|
|
printf '\033[0;39mtrue\033[0m'
|
|
printf '\033[1;39m,\033[0m\n'
|
|
printf ' \033[1;34m"b"\033[0m'
|
|
printf '\033[1;39m:\033[0m '
|
|
printf '\033[0;39mfalse\033[0m\n'
|
|
printf ' \033[1;39m}\033[0m'
|
|
printf '\033[1;39m,\033[0m\n'
|
|
printf ' \033[0;32m"abc"\033[0m'
|
|
printf '\033[1;39m,\033[0m\n'
|
|
printf ' \033[0;39m123\033[0m'
|
|
printf '\033[1;39m,\033[0m\n'
|
|
printf ' \033[0;90mnull\033[0m\n'
|
|
printf '\033[1;39m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set non-default colors, complex input, indented
|
|
JQ_COLORS='0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
|
|
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[1;35m[\033[0m\n'
|
|
printf ' \033[1;36m{\033[0m\n'
|
|
printf ' \033[1;37m"a"\033[0m'
|
|
printf '\033[1;36m:\033[0m '
|
|
printf '\033[0;32mtrue\033[0m'
|
|
printf '\033[1;36m,\033[0m\n'
|
|
printf ' \033[1;37m"b"\033[0m'
|
|
printf '\033[1;36m:\033[0m '
|
|
printf '\033[0;31mfalse\033[0m\n'
|
|
printf ' \033[1;36m}\033[0m'
|
|
printf '\033[1;35m,\033[0m\n'
|
|
printf ' \033[0;34m"abc"\033[0m'
|
|
printf '\033[1;35m,\033[0m\n'
|
|
printf ' \033[0;33m123\033[0m'
|
|
printf '\033[1;35m,\033[0m\n'
|
|
printf ' \033[0;30mnull\033[0m\n'
|
|
printf '\033[1;35m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
## Set truecolor, complex input, indented
|
|
JQ_COLORS=$(printf '38;2;%s:' \
|
|
'255;173;173' '255;214;165' '253;255;182' '202;255;191' \
|
|
'155;246;255' '160;196;255' '189;178;255' '255;198;255') \
|
|
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d/color
|
|
{
|
|
printf '\033[38;2;160;196;255m[\033[0m\n'
|
|
printf ' \033[38;2;189;178;255m{\033[0m\n'
|
|
printf ' \033[38;2;255;198;255m"a"\033[0m'
|
|
printf '\033[38;2;189;178;255m:\033[0m '
|
|
printf '\033[38;2;253;255;182mtrue\033[0m'
|
|
printf '\033[38;2;189;178;255m,\033[0m\n'
|
|
printf ' \033[38;2;255;198;255m"b"\033[0m'
|
|
printf '\033[38;2;189;178;255m:\033[0m '
|
|
printf '\033[38;2;255;214;165mfalse\033[0m\n'
|
|
printf ' \033[38;2;189;178;255m}\033[0m'
|
|
printf '\033[38;2;160;196;255m,\033[0m\n'
|
|
printf ' \033[38;2;155;246;255m"abc"\033[0m'
|
|
printf '\033[38;2;160;196;255m,\033[0m\n'
|
|
printf ' \033[38;2;202;255;191m123\033[0m'
|
|
printf '\033[38;2;160;196;255m,\033[0m\n'
|
|
printf ' \033[38;2;255;173;173mnull\033[0m\n'
|
|
printf '\033[38;2;160;196;255m]\033[0m\n'
|
|
} > $d/expect
|
|
cmp $d/color $d/expect
|
|
|
|
# Check invalid JQ_COLORS
|
|
echo 'Failed to set $JQ_COLORS' > $d/expect_warning
|
|
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/expect
|
|
for colors in '/' '[30' '30m' '30:31m:32' '30:*:31' 'invalid'; do
|
|
export JQ_COLORS=$colors
|
|
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
|
|
cmp $d/color $d/expect
|
|
cmp $d/warning $d/expect_warning
|
|
done
|
|
unset JQ_COLORS
|
|
|
|
# Check $NO_COLOR
|
|
test_no_color=true
|
|
$msys && test_no_color=false
|
|
$mingw && test_no_color=false
|
|
$sunos && test_no_color=false
|
|
# NetBSD's script(1) intermittently loses the whole session output (the
|
|
# output file comes back empty for fast commands about half the time), so
|
|
# the pty checks cannot run reliably there.
|
|
$netbsd && test_no_color=false
|
|
if $test_no_color && command -v script >/dev/null 2>&1; then
|
|
if script -qc echo /dev/null >/dev/null 2>&1; then
|
|
faketty() { script -qec "$*" /dev/null; }
|
|
else # macOS
|
|
faketty() { script -q /dev/null "$@" /dev/null |
|
|
sed 's/^\x5E\x44\x08\x08//'; }
|
|
fi
|
|
|
|
faketty $JQ_NO_B -n . > $d/color
|
|
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
|
|
od -tc $d/expect
|
|
od -tc $d/color
|
|
cmp $d/color $d/expect
|
|
faketty env NO_COLOR= $JQ_NO_B -n . > $d/color
|
|
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
|
|
od -tc $d/expect
|
|
od -tc $d/color
|
|
cmp $d/color $d/expect
|
|
faketty env NO_COLOR=1 $JQ_NO_B -n . > $d/color
|
|
printf 'null\r\n' > $d/expect
|
|
od -tc $d/expect
|
|
od -tc $d/color
|
|
cmp $d/color $d/expect
|
|
faketty env NO_COLOR=1 $JQ_NO_B -Cn . > $d/color
|
|
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
|
|
od -tc $d/expect
|
|
od -tc $d/color
|
|
cmp $d/color $d/expect
|
|
fi
|
|
|
|
# #2785
|
|
if $VALGRIND $Q $JQ -n -f "$JQTESTDIR/no-main-program.jq" > $d/out 2>&1; then
|
|
echo "jq -f $JQTESTDIR/no-main-program.jq succeeded"
|
|
exit 1
|
|
else
|
|
EC=$?
|
|
if [ $EC -eq 1 ]; then
|
|
echo "jq -f $JQTESTDIR/no-main-program.jq failed with memory errors"
|
|
exit 1
|
|
fi
|
|
if [ $EC -ne 3 ]; then
|
|
echo "jq -f $JQTESTDIR/no-main-program.jq failed with wrong exit code ($EC)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
cat > $d/expected <<EOF
|
|
jq: error: Top-level program not given (try ".")
|
|
jq: 1 compile error
|
|
EOF
|
|
if ! diff $d/expected $d/out; then
|
|
echo "jq -f $JQTESTDIR/no-main-program.jq failed but its error message is not the expected one"
|
|
exit 1
|
|
fi
|
|
|
|
if ! $VALGRIND $Q $JQ -n -f "$JQTESTDIR/yes-main-program.jq" > $d/out 2>&1; then
|
|
echo "jq -f $JQTESTDIR/yes-main-program.jq failed"
|
|
exit 1
|
|
fi
|
|
|
|
if ! $msys && ! $mingw && locales=$(locale -a); then
|
|
{ l=$(grep -Ev '^(C|LANG|POSIX|en)' | grep -Ei '\.utf-?8$' | head -n1) ;} \
|
|
<<EOF
|
|
$locales
|
|
EOF
|
|
if [ -z "$l" ]; then
|
|
echo "WARNING: Not testing localization"
|
|
elif [ "$(LC_ALL=C date +%a%b)" = "$(LC_ALL=$l date +%a%b)" ]; then
|
|
echo "WARNING: Date does not produce locale-dependent output for $l, skipping localization test"
|
|
else
|
|
dt1=$(LC_ALL=$l date +'%a %d %b %Y at %H:%M:%S')
|
|
dt2=$(LC_ALL=$l $JQ -nr 'now | strflocaltime("%a %d %b %Y at %H:%M:%S")')
|
|
dt3=$(LC_ALL=$l date +'%a %d %b %Y at %H:%M:%S')
|
|
if [ "$dt1" != "$dt2" ] && [ "$dt2" != "$dt3" ]; then
|
|
echo "jq does not honor LC_ALL environment variable ($dt1, $dt2, $dt3)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Test syntax error messages of multiline filter (we can't test in jq.test)
|
|
if $VALGRIND $Q $JQ -n '[
|
|
try if .
|
|
then 1
|
|
else 2
|
|
catch ]' > $d/out 2>&1; then
|
|
echo 'syntax error not detected'
|
|
exit 1
|
|
fi
|
|
cat > $d/expected <<EOF
|
|
jq: error: syntax error, unexpected catch, expecting end or '|' or ',' at <top-level>, line 5, column 3:
|
|
catch ]
|
|
^^^^^
|
|
jq: error: Possibly unterminated 'if' statement at <top-level>, line 2, column 7:
|
|
try if .
|
|
^^^^
|
|
jq: error: Possibly unterminated 'try' statement at <top-level>, line 2, column 3:
|
|
try if .
|
|
^^^^^^^^
|
|
jq: 3 compile errors
|
|
EOF
|
|
diff $d/out $d/expected
|
|
|
|
# Test syntax error messages when error happens at the end.
|
|
if $VALGRIND $Q $JQ -n 'if
|
|
' > $d/out 2>&1; then
|
|
echo 'syntax error not detected'
|
|
exit 1
|
|
fi
|
|
cat > $d/expected <<EOF
|
|
jq: error: syntax error, unexpected end of file at <top-level>, line 1, column 3:
|
|
if
|
|
^
|
|
jq: 1 compile error
|
|
EOF
|
|
diff $d/out $d/expected
|
|
|
|
# Comments!
|
|
if ! x=$($JQ -n '123 # comment') || [ "$x" != 123 ]; then
|
|
echo 'comment did not work'
|
|
exit 1
|
|
fi
|
|
|
|
cr=$(printf \\r)
|
|
if ! x=$($JQ -n "1 # foo$cr + 2") || [ "$x" != 1 ]; then
|
|
echo 'regression: carriage return terminates comment'
|
|
exit 1
|
|
fi
|
|
|
|
if ! x=$($JQ -cn '[
|
|
1,
|
|
# foo \
|
|
2,
|
|
# bar \\
|
|
3,
|
|
4, # baz \\\
|
|
5, \
|
|
6,
|
|
7
|
|
# comment \
|
|
comment \
|
|
comment
|
|
]') || [ "$x" != '[1,3,4,7]' ]; then
|
|
echo 'multiline comment was not handled correctly'
|
|
exit 1
|
|
fi
|
|
|
|
if ! x=$($JQ -cn "$(printf '[\r\n1,# comment\r\n2,# comment\\\r\ncomment\r\n3\r\n]')") \
|
|
|| [ "$x" != '[1,2,3]' ]; then
|
|
echo 'multiline comment with CRLF line breaks was not handled correctly'
|
|
exit 1
|
|
fi
|
|
|
|
# Allow passing the inline jq script before -- #2919
|
|
if ! r=$($JQ --args -rn -- '$ARGS.positional[0]' bar) || [ "$r" != bar ]; then
|
|
echo "passing the inline script after -- didn't work"
|
|
exit 1
|
|
fi
|
|
if ! r=$($JQ --args -rn 1 -- '$ARGS.positional[0]' bar) || [ "$r" != 1 ]; then
|
|
echo "passing the inline script before -- didn't work"
|
|
exit 1
|
|
fi
|
|
|
|
# CVE-2023-50246: No heap overflow for '-10E-1000000001'
|
|
$VALGRIND $Q $JQ . <<\NUM
|
|
-10E-1000000001
|
|
NUM
|
|
|
|
# test for --indent and --compact-output -- #1465
|
|
printf '[1,2]\n' > $d/expected
|
|
$JQ --compact-output -n "[1,2]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n1,\n2\n]\n' > $d/expected
|
|
$JQ --indent 0 -n "[1,2]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n 1,\n 2\n]\n' > $d/expected
|
|
$JQ --indent 1 -n "[1,2]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n 1,\n 2\n]\n' > $d/expected
|
|
$JQ --indent 5 -n "[1,2]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n{\n"a": 1\n}\n]\n' > $d/expected
|
|
$JQ --indent 0 -n "[{a:1}]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n {\n "a": 1\n }\n]\n' > $d/expected
|
|
$JQ --indent 1 -n "[{a:1}]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
printf '[\n {\n "a": 1\n }\n]\n' > $d/expected
|
|
$JQ --indent 6 -n "[{a:1}]" > $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
if ! $msys && ! $mingw; then
|
|
# Test handling of timezones -- #2429, #2475
|
|
if ! r=$(TZ=Asia/Tokyo $JQ -rn '1731627341 | strflocaltime("%F %T %z %Z")') \
|
|
|| [ "$r" != "2024-11-15 08:35:41 +0900 JST" ]; then
|
|
echo "Incorrectly formatted local time"
|
|
exit 1
|
|
fi
|
|
|
|
if ! r=$(TZ=Europe/Paris $JQ -rn '1731627341 | strflocaltime("%F %T %z %Z")') \
|
|
|| [ "$r" != "2024-11-15 00:35:41 +0100 CET" ]; then
|
|
echo "Incorrectly formatted local time"
|
|
exit 1
|
|
fi
|
|
|
|
# Test when DST is in effect: #1912
|
|
if ! r=$(TZ=Europe/Paris $JQ -rn '1750500000 | strflocaltime("%F %T %z %Z")') \
|
|
|| [ "$r" != "2025-06-21 12:00:00 +0200 CEST" ]; then
|
|
echo "Incorrectly formatted local time"
|
|
exit 1
|
|
fi
|
|
|
|
if ! r=$(TZ=Europe/Paris $JQ -rn '1731627341 | strftime("%F %T %z %Z")') \
|
|
|| ( [ "$r" != "2024-11-14 23:35:41 +0000 UTC" ] \
|
|
&& [ "$r" != "2024-11-14 23:35:41 +0000 GMT" ] ); then
|
|
echo "Incorrectly formatted universal time"
|
|
exit 1
|
|
fi
|
|
|
|
if ! r=$(TZ=Etc/GMT+7 $JQ -nc '1731627341 | .,. | [strftime("%FT%T"),strflocaltime("%FT%T%z")]'
|
|
) \
|
|
|| [ "$r" != '["2024-11-14T23:35:41","2024-11-14T16:35:41-0700"]
|
|
["2024-11-14T23:35:41","2024-11-14T16:35:41-0700"]' ]; then
|
|
echo "strftime or strftimelocal are not pure functions"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Test ARG_NEWCLOSURE overflow protection (issue #3458)
|
|
# Test 1: Too many function parameters (4097 params triggers the limit)
|
|
echo "Testing function parameter limit..."
|
|
cat > $d/expected <<EOF
|
|
jq: error: too many function parameters or local function definitions (max 4095)
|
|
jq: 1 compile error
|
|
EOF
|
|
$JQ -rn '"def f(\([range(4097) | "a\(.)"] | join(";"))): .; f(\([range(4097)] | join(";")))"' > $d/prog.jq
|
|
$JQ -nf $d/prog.jq 2> $d/out && {
|
|
echo "Expected compile error for too many parameters"
|
|
exit 1
|
|
}
|
|
diff $d/out $d/expected
|
|
|
|
# Test 2: Too many local functions (4097 functions triggers the limit)
|
|
echo "Testing local function limit..."
|
|
cat > $d/expected <<EOF
|
|
jq: error: too many function parameters or local function definitions (max 4095)
|
|
jq: 1 compile error
|
|
EOF
|
|
$JQ -rn '"\([range(4097) | "def f\(.): \(.)"] | join("; ")); \([range(4097) | "f\(.)"] | join(" + "))"' > $d/prog.jq
|
|
$JQ -nf $d/prog.jq 2> $d/out && {
|
|
echo "Expected compile error for too many local functions"
|
|
exit 1
|
|
}
|
|
diff $d/out $d/expected
|
|
|
|
# Test 3: Too many function parameters in a nested function (issue #3661)
|
|
echo "Testing function parameter limit in a nested function..."
|
|
cat > $d/expected <<EOF
|
|
jq: error: function has too many parameters (max 4095)
|
|
jq: error: too many function parameters or local function definitions (max 4095)
|
|
jq: 2 compile errors
|
|
EOF
|
|
$JQ -rn '"def g(\([range(4097) | "a\(.)"] | join(";"))): .; def f: g(\([range(4097)] | join(";"))); f"' > $d/prog.jq
|
|
$JQ -nf $d/prog.jq 2> $d/out && {
|
|
echo "Expected compile error for too many parameters in a nested function"
|
|
exit 1
|
|
}
|
|
diff $d/out $d/expected
|
|
|
|
# CVE-2026-33948: No NUL truncation in the JSON parser
|
|
if printf '{}\x00{}' | $JQ >/dev/null 2> /dev/null; then
|
|
printf 'Error expected but jq exited successfully\n' 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# CVE-2026-41256: No NUL truncation in program files loaded with -f
|
|
printf '.\x00invalid' > "$d/nul_prog.jq"
|
|
if echo '42' | $JQ -f "$d/nul_prog.jq" >/dev/null 2>/dev/null; then
|
|
printf 'Error expected for program file with NUL bytes\n' 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# CVE-2026-43895: No NUL bytes in module/data import paths
|
|
printf 'import "a\\u0000b" as $x; .' > "$d/nul_import.jq"
|
|
if $JQ -nf "$d/nul_import.jq" >/dev/null 2>/dev/null; then
|
|
printf 'Error expected for import path with NUL bytes\n' 1>&2
|
|
exit 1
|
|
fi
|
|
printf 'include "a\\u0000b"; .' > "$d/nul_include.jq"
|
|
if $JQ -nf "$d/nul_include.jq" >/dev/null 2>/dev/null; then
|
|
printf 'Error expected for include path with NUL bytes\n' 1>&2
|
|
exit 1
|
|
fi
|
|
printf '"a\\u0000b" | modulemeta' > "$d/nul_modulemeta.jq"
|
|
if $JQ -nf "$d/nul_modulemeta.jq" >/dev/null 2>/dev/null; then
|
|
printf 'Error expected for modulemeta with NUL bytes\n' 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
exit 0
|