414 Commits
Author SHA1 Message Date
Hugohong258 611c575a97 docs: add simple and nested update-assignment examples (#3664) 2026-10-12 00:24:32 +09:00
Michiel van Slobbe b904884b94 Improve performance of string output (#3643)
Printing a string wrote each character with a separate call, one
fwrite() per character, or one jv_string_append_buf() for tojson and
tostring, which made output of string-heavy data slow.

Scan ahead for the next byte that needs escaping and write the run of
bytes before it with a single call, without changing the output.
Printing strings is now significantly faster, most of all for long
strings with few characters to escape, and the same applies to tojson
and tostring. With --ascii-output, text that is almost all non-ASCII is
about the same speed, since nearly every byte is escaped anyway.
2026-10-10 21:50:10 +09:00
itchyny a5323a369c Fix assertion failure on too many parameters in a nested function (#3663)
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.
2026-10-10 21:29:56 +09:00
qodelicious 04042494cf Exit with the given status for negative halt_error codes (#3660)
halt_error with a negative exit code did not exit with that code. The
code collided with the internal status values for null or false output
and for no output, so halt_error(-1) exited with 0, or with 1 under
--exit-status.

Keep the low 8 bits of a negative code, as exit(3) does on POSIX
systems, so halt_error(-1) now exits with 255 and halt_error(-2) with
254, the same with or without --exit-status. Under --exit-status this
replaces the previous absolute value, so halt_error(-2) used to exit
with 2 and halt_error(-255) with 255, and they now exit with 254 and 1.
2026-10-10 21:26:02 +09:00
omkar bhor a8e6d5f871 Fix undefined behavior on out-of-range array index in has() and del() (#3560)
Converting a double outside the int range to int is undefined behavior,
and has() and del() did it on array indices like infinite or 1e10, which
UBSan reports as "inf is outside the range of representable values of
type 'int'". Only NaN was guarded against.

Clamp the index to the int range in has(), as getting and setting array
elements already do, and drop out-of-range indices in del() before they
are converted. Such indices can never refer to an element, so has()
returns false and del() leaves the array unchanged, the same as for
indices past the end of the array. Valid indices deleted together with
out-of-range ones, as in del(.[0, 1e10]), are still deleted.
2026-10-09 09:22:59 +09:00
neil dbbae0dee3 Add FreeBSD and NetBSD CI (#3600)
Add a BSD workflow with FreeBSD and NetBSD jobs that run the same build
and tests as the linux job, each inside a VM booted under QEMU on an
ubuntu-latest runner. The tests/shtest $NO_COLOR pty checks are now
skipped on NetBSD, as they already are on SunOS.
2026-10-08 23:38:20 +09:00
itchyny e001deb4cf Strip UTF-8 BOM at the start of each input file (#3657)
The UTF-8 BOM was stripped only at the start of the parser stream, but jq
feeds all input files into a single parser, so a BOM at the start of the
second and later files reached the parser as content and failed with a
confusing "Invalid numeric literal" error. Strip it in the file readers
instead, at the start of each input file including stdin, and in
jv_load_file.

This also strips the BOM for raw input, so -R and --rawfile no longer
yield a leading U+FEFF, and a BOM at the start of a -f program file or an
imported module is now accepted rather than reported as a syntax error.
In exchange, "\uFEFF1" | fromjson is now a parse error, since a U+FEFF
inside a string is content rather than an encoding marker, and the
dedicated "Malformed BOM" error is gone.
2026-10-08 23:01:36 +09:00
itchyny fd25c3e720 Parse the full ISO 8601 grammar in fromdateiso8601 (#3617)
`fromdateiso8601` was `strptime("%Y-%m-%dT%H:%M:%SZ") | mktime`, which
accepts only one of the many representations ISO 8601 permits. strptime
cannot be extended to cover the rest portably, since it has no specifier
for fractional seconds and glibc discards `%G` and `%V`.

Replace it with a parser in src/iso8601.c that handles basic and extended
representations, ordinal and week dates, fractional seconds, offsets and
date-only input. It uses integer arithmetic instead of `time_t`, so the
results no longer depend on the platform.

This is stricter than before. Impossible dates like `2015-02-30`, which
`mktime` used to normalize into March, and unpadded components like
`2015-3-5T6:00:00Z` are now errors. So is any trailing input, including
whitespace. Leading whitespace is rejected too; before, glibc skipped it
and macOS did not. A leap second now maps to the second before it rather
than the next minute. The error message has changed, and the result can
now be non-integer.
2026-10-08 08:24:10 +09:00
A4-Tacks a19efdd45d Parse ?// as ? and // outside destructuring patterns (#3593)
The lexer returned a single ALTERNATION token for `?//`, so any `?`
followed by `//` was consumed by it, and `.name?//"unknown"` failed
to parse even though they read as the optional operator followed by
the alternative operator.

Drop the lexer rule and spell the destructuring alternative operator
as `'?' "//"` instead. So `x ?// y` now parses as `x? // y`, while
`. as [$a] ?// [$b] | ...` keeps its meaning. Note that `?` and `//`
may now be separated by whitespaces inside a pattern.
2026-10-06 16:48:28 +09:00
Artem Lytkin 9a75bb0d43 Improve performance of join/1 on large arrays (#3639)
join/1 folded each element as `(acc + $x) + elem`, with the element
branch ending in `.//""`. Both leave a second live reference to the
accumulator: the nested + feeds the same `.` to both operands, and the
`//` leaves a forkpoint below it on the stack. `jvp_string_append`
therefore cannot grow the accumulator in place, and copies the whole
string once per element.

Pipe `acc + $x` into `. + elem` and drop the `//`, since adding null to
a string is already a no-op. join/1 is now linear: joining 8000
strings of 1000 chars goes from 6.5s to 0.06s, with output and error
messages unchanged.
2026-09-27 13:52:41 +09:00
itchyny df24981307 Fix reduce to preserve its input across init backtracking (#3633)
`reduce f as $x (init; update)` evaluated `f` against a stack slot
that forkpoints created while evaluating `init` restore. Both the
`DUPN` opening the reduction loop and the `LOADVN` retrieving the
result pop that slot destructively, nulling it out, so an `init`
that backtracks (e.g. `0, 0`) made `f` see `null` and fail with
"Cannot iterate over null".

Duplicate the input before the `FORK` instead of inside the loop,
and drop the leftover copy with `POP` once the loop is exhausted.
The slot left live at the `FORK` is then a block pushed after
`init` completed, which no earlier forkpoint can reach, so nulling
it is harmless. This is the same approach `gen_foreach` has used
since c70ae1a.

`DUPN` had no other user, so remove the opcode.
2026-09-19 15:21:29 +09:00
itchyny 12cdd950e9 Register imported libraries in dependency order (#3620)
block_mark_referenced walks the joined block backwards and skips the
body of any definition not yet marked referenced, so a library must
precede its importers.  f58787c41 registered a library before walking
its dependencies, to have somewhere to keep the `loading` flag, which
reversed that order and made block_drop_unreferenced free definitions
that are still referenced through bound_by.

Keep the libraries being loaded on a stack threaded through the
load_library frames instead, so registration can move back after the
dependency walk.
2026-09-18 22:27:54 +09:00
itchyny e371bfaa92 Implement range/3 in C for consistent error handling (#3267) 2026-09-18 22:20:58 +09:00
itchyny 6aeafff056 Fix gmtime and localtime on negative timestamps with fractional seconds (#3634)
The whole seconds were truncated toward zero while the fractional part
was measured from the floor, so any negative non-integral timestamp was
rendered one second late; gmtime was not monotonic across the epoch.
2026-09-18 18:45:36 +09:00
august fbee8f48ba Reject raw NUL bytes in the parser instead of silently truncating tokens (#3606) 2026-08-24 00:01:54 +09:00
ded-furby 2d410d6d86 docs: clarify join behavior on objects (#3555) 2026-07-19 21:27:45 +09:00
WinkleMad f1f39b42e3 Advance past the whole codepoint after a zero-width regex match (#3586) 2026-07-19 21:13:51 +09:00
pavel kuliaka dbcaa9d491 shtest: skip locale test if date lacks locale support (#3583) 2026-07-18 17:03:18 +09:00
Yu-Fu Fu 7122866869 Guard deep structural equality and comparison recursion (#3539)
jv_equal and jv_cmp overflows the C stack on deeply nested
input. Cap recursion at 10000 with -1 / INT_MIN sentinels;
operators that compose user expressions surface this as
"Equality check too deep" / "Comparison too deep".

Fixes CVE-2026-47770.
2026-05-22 20:07:16 +09:00
itchyny f58787c418 Detect circular module imports to prevent stack overflow
jq used to recurse without bound on mutual or self-referential
`import` declarations, exhausting the stack. Track each library's
load state with a `loading` flag set before its dependencies are
processed; a recursive reference to an in-progress library now
reports "circular import of X".

Fixes CVE-2026-44777.
2026-05-11 20:41:38 +09:00
itchyny 9d223f153c Reject embedded NUL bytes in module import paths
jq accepts embedded NUL bytes at the language level but resolves
module import paths through NUL-terminated C strings, so the path
validated by policy or audit code could differ from the on-disk
path jq actually opens. Pass jv through gen_import so the AST
preserves the original bytes, and reject embedded NULs in
validate_relpath.

Fixes CVE-2026-43895.
2026-05-09 17:08:43 +09:00
itchyny 532ccea608 Limit recursive object merge depth to prevent stack overflow
This fixes CVE-2026-43896.
2026-05-05 22:44:02 +09:00
itchyny 5a015deae3 Fix NUL truncation in program files loaded with -f
This fixes CVE-2026-41256.
2026-04-24 22:15:08 +09:00
itchyny d1a12569d9 Limit the containment check depth
This fixes CVE-2026-40612.
2026-04-24 22:02:24 +09:00
itchyny fb59f14910 Limit path depth to prevent stack overflow
Deeply nested path arrays can cause unbounded recursion in
`jv_setpath`, `jv_getpath`, and `jv_delpaths`, leading to
stack overflow. Add a depth limit of 10000 to match the
existing `tojson` depth limit. This fixes CVE-2026-33947.
2026-04-13 11:23:40 +09:00
itchyny 6374ae0bcd Fix NUL truncation in the JSON parser
This fixes CVE-2026-33948.
2026-04-13 08:46:11 +09:00
tlsbollei fdf8ef0f08 Add runtime type checks to f_string_indexes
This fixes CVE-2026-39956.
2026-04-08 21:43:46 +02:00
Vladimír Marek 9f778b4cb5 Add Solaris support (#3515)
I love jq :) So while updating the version we ship in Solaris I have
tried to modify stuff to make everything work out of the box. Just

```
autoreconf -fiv
./configure
gmake
gmake check
```

I also went ahead and created Solaris test action should you be
interested in having it too. The changes are not extensive and I have
tried to comment them nicely in each commit. Hopefully that's enough.

Thanks for jq!
2026-04-08 16:02:41 +02:00
Ze Sheng b6a9e260cd fix jq_fuzz_parse_stream: use iterative parser API for streaming mode (#3499) 2026-03-11 11:49:14 +09:00
itchyny ed3c7f214b Fix tonumber and toboolean to reject strings with embedded null bytes (#3496) 2026-03-05 08:28:43 +09:00
itchyny bfcf82fde1 Refactor @uri and @urid and fix multi-byte UTF-8 corruption (#3495)
This commit improves performance by refactoring `@uri` and `@urid`
to pre-alloacte buffers and build the `jv` string at the end.
Also, this fixes `@urid` to prevent multi-byte UTF-8 corruption,
and to preserve embedded null bytes.
2026-03-05 08:28:09 +09:00
itchyny 0df54c888a Fix infinite loop and undefined behavior in del(.[nan]) (#3490) 2026-03-02 21:58:28 +09:00
itchyny 601a37f452 Refactor tm2jv to handle fractional seconds removing duplicated code (#3489) 2026-03-01 06:18:14 +09:00
itchyny 22361cfb87 Improve error message truncation with closing delimiters (#3478)
Truncated strings now show closing delimiters: `..."` for strings,
`...]` for arrays, and `...}` for objects, making error messages
clearer.
2026-02-25 08:14:23 +09:00
Ze Sheng a2741ee0a8 Limit number of function parameters and definitions to prevent SEGV (#3460) 2026-02-25 07:49:40 +09:00
bigmoonbit 0eb3da11ed chore: fix typo in tests/jq.test (#3441)
fix typo in  tests/jq.test

Signed-off-by: bigmoonbit <[email protected]>
2025-11-27 10:44:45 +01:00
itchyny 5529788292 Fix slurping raw input not to corrupt multi-byte characters (fix #3389) (#3421) 2025-10-31 15:16:29 +09:00
Ish Nagy b29504b4e1 Increase the maximum printing depth from 256 to 10000 (fixes #3413) (#3414) 2025-10-14 14:12:57 +09:00
Sudhakar Verma 589a6947fa jq_fuzz_execute: limit oniguruma depth to 1024 (#3377)
Fixes #3375 - I'll also fix the oss-fuzz build for this in a PR

Signed-off-by: Sudhakar Verma <[email protected]>
2025-10-05 12:50:42 +09:00
A4-Tacks 169457328d Fix rtrimstr("") always output "" (#3415)
Example
---
**Before this fix**:

```sh
$ jq -n '"foo"|rtrimstr("")'
""
```

**After this fix**:

```sh
$ jq -n '"foo"|rtrimstr("")'
"foo"
```
2025-09-29 17:15:43 +02:00
itchyny c8017bf079 Fix localization test for time formatting functions (fix #3368) (#3409) 2025-09-15 07:48:02 +09:00
Alyssa Ross 3c5ceac8e7 jq.test: drop non-portable %F test (#3365)
%F is a non-portable GNU extension, not supported by all strptime
implementations (for example musl's).
2025-07-05 01:25:28 +09:00
Mattias Wadman 499c91bca9 Fixes CVE-2025-49014 which was introduced in 1.8.0 2025-06-19 00:11:01 +02:00
itchyny edbc1da809 Revert "fix: reduce/foreach state variable should not be reset each iteration" (#3349)
This reverts 96e8d893c1. The change
introduced a serious performance regression as reported in #3345.
2025-06-17 15:29:46 +09:00
itchyny a587ddc5a3 Fix syntax error assertion failure (fix #3348) (#3350) 2025-06-17 15:25:46 +09:00
itchyny 7cc202aa6e Fix portability of strptime especially for Windows (#3342) 2025-06-14 08:00:55 +09:00
itchyny d3cf5caf72 Add more test cases for JQ_COLORS support (ref #3288) 2025-05-31 16:29:02 +09:00
SArpnt aa977aa716 Dynamically allocate JQ_COLORS escapes for truecolor support (#3282) 2025-05-31 15:49:17 +09:00
itchyny c6e041699d Fix heap buffer overflow when formatting an empty string
The `jv_string_empty` did not properly null-terminate the string data,
which could lead to a heap buffer overflow. The test case of
GHSA-p7rr-28xf-3m5w (`0[""*0]`) was fixed by the commit dc849e9bb7,
but another case (`0[[]|implode]`) was still vulnerable. This commit
ensures string data is properly null-terminated, and fixes CVE-2025-48060.
2025-05-31 11:46:40 +09:00
Thalia Archibald 9ac6ddae22 Fix whitespace in number parsing (#3195)
* Handle input errors for --indent

Handle malformed and overflowing arguments. Also, forbid leading and
trailing spaces to match the behavior of tonumber from commit ce0e788
(improve tonumber/0 performance by parsing input as number literal,
2024-03-02).

* Do not skip leading whitespace in jvp_strtod

`jvp_strtod` skips leading whitespace, but its decnum counterpart
`decNumberFromString` (called within `jv_number_with_literal`) does not.
Those two are called interchangeably, so it leads to inconsistent
behavior depending on whether the decnum feature is enabled.
Additionally, `classify`, used in the token scanner, only considers
[ \t\n\r] to be whitespace, but `jvp_strtod` consumes the larger set
[ \t\n\v\f\r], so those extra characters are considered literals.

Changing this deviates from the behavior of `strdod` from <stdlib.h> and
is technically a breaking API change, since it is a public symbol.
2025-05-29 04:11:00 +09:00