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.
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.
`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.
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.
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.
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.
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.
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.
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.
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!
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.
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.
* 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.
Previously, the precedence of `as` binding was higher than the binary
operators. This results in unexpected behaviors, `1 + 2 as $x | -$x`
was `-1` instead of `-3`. The commit 92daac90f6 (PR #3053) changed
the behavior to emit syntax error on this case. Now, this commit allows
binary operators with `as` binding. This fixes#2446, and fixes#3284.
This commit fixes signed integer overflow and SEGV issues on growing
arrays and objects. The size of arrays and objects is now limited to
`536870912` (`0x20000000`). This fixes CVE-2024-23337 and fixes#3262.
This commit improves the parser and compiler error messages, making
it more easier to understand where in the filter the problem is.
Like modern compilers, jq will show the line in the filter where the
error occurred, will display squiggly line under the invalid token.
This commit improves the parser to fix some unintuitive results of the unary
operator `-` (e.g. `[-1 as $x | 1,$x]` is now `[1,-1]`, previously `[-1,-1]`).
Also, this commit now allows to use binary operator expressions, `reduce`,
`foreach`, `if`, and `try` expressions for object values.
This commit refactors `splits/2` implementation using `foreach` syntax
and reduces intermediate arrays. This refactoring removes an unnecessary
private (and undocumented) filter `_nwise` and closes#3148.