jq dumps JSON to the Windows console as UTF-16 with WriteConsoleW(),
but priv_fwrite() still writes the raw UTF-8 bytes with WriteFile(),
which the console decodes with its output code page. So `jq .k` prints
non-ASCII correctly while `jq -r .k` prints mojibake, and the same goes
for -j, --raw-output0, --seq, halt_error and the `stderr` builtin.
The tty flag is computed once, from stdout, and passed to writes aimed
at stderr too, so ask the handle instead: with stdout on a console and
stderr redirected, WriteConsoleW() failed on the file handle and the
output was dropped.
One byte-level change: with stdout on a console and stderr redirected,
halt_error and the `stderr` builtin now go through the CRT, so bare LF
becomes CRLF and an existing CRLF becomes CR CRLF. Use -b for
byte-exact output on that stream.
The ownership comment in `jv.h` currently says every `jv_*` function
except `jv_copy` consumes its input. Several accessors and
object-iteration functions borrow their arguments instead, which makes
that guidance misleading for callers and language bindings.
Document the borrowing exceptions beside their declarations, including
numeric helpers and `jv_show`. Clarify that returned `jv` values are
owned, while the pointers returned by `jv_string_value` and
`jv_number_get_literal` belong to their input values. This changes
comments only.
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.
Only the latest release stays visible in the binary, checksum and
signature, and source tarball lists; older versions move into
collapsible `<details>` sections. Condense the repetitive per-version
checksum and signature sentences into a single list.
State explicitly in the README and download page that the
platform-specific prebuilt files are standalone executables, not
archives. Include the rename and executable-permission step for macOS
and Linux in the README.
Addresses #2956. Source archives are not described as executables.
Validation: the official `docs/build_website.py` completed and the
generated download page contains the new guidance. Used a Python venv
with the site's required rendering packages; restored the Windows
checkout's manual symlink in a temporary build copy only. jq itself was
not built or tested for this documentation-only change.
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
The bundle generated by actions/attest is currently only retrievable
via the GitHub attestations API, which requires authentication.
Uploading it as jq-attestation.json lets downstream consumers
(distro packagers, unauthenticated CI) verify provenance offline.
The bound added in CVE-2026-32316 (e47e56d22) still allowed
`sizeof(jvp_string) + (currlen + len) * 2 + 1` to wrap `size_t` on
32-bit platforms. Tighten the threshold so the final allocation
fits in 32-bit `size_t`.
Also break out of `jv_string_implode` and `f_string_implode` once
`jv_string_append_codepoint` returns an invalid `jv`; otherwise the
next iteration triggers the assertion in `jvp_string_ptr` (or
invokes undefined behavior under `-DNDEBUG`).
Fixes CVE-2026-54679.
Co-authored-by: Dirk Müller <dirk@dmllr.de>
When `jv_string_append_buf` overflows the string length limit,
it returns an invalid `jv`; `jv_load_file` then re-entered it
on the invalid value and overran the heap. Break out of the loop
once the value is invalid.
Fixes CVE-2026-49839.
The table was declared with 255 entries but indexed by an unsigned
char, so the decoder would read one byte past the array for input
bytes equal to 0xFF. Through jq's normal input paths the over-read
is unreachable because invalid UTF-8 bytes are normalized to U+FFFD
before reaching @base64d, but the table is still wrong at the C
level and reachable by libjq callers that construct strings via
the C API without UTF-8 validation.
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.
A signed-int overflow in decNumber's D2U macro lets huge literals
write attacker-controlled bytes past a stack buffer. Cap the length
before calling decNumberFromString, and pre-slice long strings in
jv_dump_string_trunc so the resulting error message doesn't itself
allocate a multi-GiB buffer.
Fixes CVE-2026-43894.
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.
The hash function used a fixed seed, allowing attackers to craft colliding keys
and cause O(n^2) object parsing performance. Initialize the seed from a random
source at process startup to prevent the attack. This fixes CVE-2026-40164.
Co-authored-by: Asaf Meizner <asafmeizner@gmail.com>
In `jvp_string_append`, the allocation size `(currlen + len) * 2` could
overflow `uint32_t` when `currlen + len` exceeds `INT_MAX`, causing a small
allocation followed by a large `memcpy`.
In `jvp_string_copy_replace_bad`, the output buffer size calculation
`length * 3 + 1` could overflow `uint32_t`, again resulting in a small
allocation followed by a large write.
Add overflow checks to both functions to return an error for strings
that would exceed `INT_MAX` in length. Fixes CVE-2026-32316.
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!
If --disable-maintainer-mode is enabled, then the rules for generating
parser.[ch] and lexer.[ch] did nothing. This worked fine if the source
and build directories are the same as the pre-generated parser.c and
lexer.c files would suffice. However, if the build directory is not the
same as the source directory, then the rest of the Make rules expect
parser.[ch] and lexer.[ch] to have been created in the build directory
if their source files (parser.y and lexer.l) are newer than the target
files, which can happen in case the source is fetched using Git.
Avoid the problem by copying the files to the build directory if needed.
Co-authored-by: Peter Kjellerstedt <pkj@axis.com>