Files
Jarred Sumner 92fc9f295b deps: update libarchive, brotli, lsquic, libjpeg-turbo, sqlite and others (#42523)
### What does this PR do?

Bumps every vendored dependency that has a newer upstream release, and
re-ports or drops the patches that no longer fit. mimalloc is left
alone. zstd, highway, c-ares, libspng, libwebp, zlib-ng and rust-argon2
are already on their latest release.

| dep | from → to | patches |
| --- | --- | --- |
| libarchive | 3.8.7 → 3.8.9 | 3 of 4 no longer applied (upstream
refactored `archive_read.c`, both gzip filters and the tar reader);
re-ported |
| brotli | 1.1.0 → 1.2.0 | none. Now pinned by sha. Four new source
files; `OS_*` / `BROTLI_HAVE_LOG2` defines are unused upstream and
removed |
| libdeflate | → 1.26 | none |
| lshpack | → 2.3.5 | `no-name-trim.patch` **deleted**, fixed upstream |
| lsqpack | → 2.7.0 | unchanged |
| lsquic | 4.6.2 → 4.9.4 | `node-quic-accessors.patch` re-ported; the
other nine apply unchanged |
| hdrhistogram | → 0.11.10 | new `no-avx2-dispatch.patch` |
| libjpeg-turbo | 3.1.4 → 3.2.0 | unchanged; dep file rewritten for the
unified `simd/jsimd.c` dispatcher |
| picohttpparser | 066d2b1 → f4d94b4 | `strict-chunk-size.patch`
rewritten as `chunked-decoder.patch` |
| sqlite | 3.53.2 → 3.53.4 | n/a |

Things a reviewer can't see from the version numbers:

**libarchive `nonblocking-read.patch`.** Same behaviour, carried across
upstream's `self/state/filter` → `f/gzip` renames and the
`default_inode` move into `struct tar`. One addition:
`archive_read_data_skip()` now returns on `ARCHIVE_RETRY` before it
flips the state to `HEADER`. The old patch's comment already assumed the
state stayed `DATA` so the skip would resume; the code did not do that.
Unreachable from `TarballStream` today (it always reads entries to EOF),
so no behaviour change for `bun install`.

**lshpack.** Upstream 2.3.5 removed the name trimming (what our patch
did) and also stopped failing the decode on a zero-length literal name.
The fetch h2 client and node:http2 already reject an empty name after
decoding (`HpackError::EmptyHeaderName`). Bun.serve's decoder relied on
lshpack for it, so `Http2Context.h` now checks `name_len == 0` and keeps
the COMPRESSION_ERROR connection error. `serve-http2-protocol.test.ts`
"zero-length field name is rejected" fails without that line.

**lsquic.** Upstream removed server push, added `MF_USER_CLOSE` /
`should_generate_connection_close()`, reordered `init_http`, and added
`on_hset_in` / `es_max_header_sets`. In the re-port, `MF_USE_PREF_ADDR`
moves from bit 1 (now `MF_USER_CLOSE`) to bit 9, and our `||
!es_silent_close` clause in the tick's close condition is dropped: every
path that sets `IFC_CLOSING` is now covered by `MF_USER_CLOSE`,
`IFC_GOAWAY_CLOSE`, or the existing `IFC_RECV_CLOSE && !(server &&
silent_close)` clause. The generated `lsquic_versions_to_string.c` is
byte-identical for the new `lsquic.h`.

**picohttpparser.** Two things broke silently:
- `struct phr_chunked_decoder` grew by two `uint64_t`; the `#[repr(C)]`
mirror in `src/picohttp/lib.rs` is updated.
- The decoder's private state enum gained three states, so the trailer
states are 6/7 instead of 4/5.
`InternalState::is_body_complete_on_close` compared `_state` to the
literals `4 | 5`, which would now mean "expecting CR/LF after chunk
data": a close during trailers would be rejected and a body truncated
right after chunk data would be accepted. The patch adds
`phr_decode_chunked_is_in_trailers()` next to upstream's
`phr_decode_chunked_is_in_data()` and Rust calls that instead of
mirroring the enum.

Upstream now rejects `0x5`-style chunk sizes itself, so the patch only
removes its SP/HTAB allowance (llhttp rejects those, and the existing
test expects it). It also removes upstream's new chunk-overhead limit
(fail once framing exceeds 100 KB and 75% of bytes read). That protects
a server from its clients; for fetch it turns a response streamed as
~21k one-byte chunks into `InvalidHTTPResponse`. User-visible change
that comes with the bump: bare-LF chunk line endings and `CR CR LF`
after chunk data are now rejected, as llhttp does.

**hdrhistogram.** 0.11.10 selects an AVX2 percentile scan with
`__builtin_cpu_supports()`, which links compiler-rt's cpu-model
constructor (runs before main; `CPUFeatures.cpp` avoids it for that
reason, and it is not on clang-cl's default link line). The patch gates
it on `HDR_NO_AVX2_DISPATCH`.

**sqlite.** `NodeSqlite.cpp` `static_assert`s its own copy of the
version against `sqlite3_local.h`, which the weekly auto-bump did not
touch, so that PR could never build. `update-sqlite-amalgamation.sh` now
rewrites those two constants and the workflow adds the file.

Not in this PR: lol-html (#41479 is open for it), and the forks whose
upgrades are rebases in their own repos (BoringSSL, WebKit, lol-html
onto upstream v3, libuv, tinycc).

### How did you verify your code works?

Debug+ASAN build on Linux x64; every patch applies with `git apply` (no
fuzz) and the patched trees are identical to the rebased branches they
were generated from.

- `test/js/web/fetch/fetch-chunked-size.test.ts` (new cases),
`chunked-trailing.test.js`. `chunked-trailing` fails 2/23 with the old
`4 | 5` literals. The new "one-byte chunks" test fails with
`InvalidHTTPResponse` when upstream's overhead limit is put back in
`vendor/picohttpparser`, and passes with the patch. The new truncation
and one-byte-chunk cases also pass on released Bun: they guard the enum
mirror and the patch hunk, not a shipped bug.
- libarchive: `archive.test.ts`,
`bun-install-streaming-extract.test.ts`,
`bun-install-tarball-integrity.test.ts`, `bun-pack.test.ts`. By hand:
`bun pm pack` still writes gzip OS=0xff / mtime 0; a 1.4 MB, 300-file
tarball with a pax long-name entry served in 1–700 byte chunks installs
byte-identical.
- lsquic/lsqpack/lshpack: all 235
`test/js/node/test/parallel/test-quic-*` (232 pass; two import
`node:stream/iter`, one asserts loopback RTT < 10 ms and fails
identically on a pre-upgrade build on the same loaded machine),
`test/js/node/quic/*`, `serve-http3.test.ts`,
`fetch-http3-{client,adversarial,cold-post}.test.ts`,
`serve-http2{,-protocol,-lifecycle}.test.ts`, `h2-conformance.test.ts`,
`node-http2.test.js`, `fetch-http2-{client,adversarial}.test.ts`.
- others: `fetch.brotli.test.ts`, `zlib.test.js`, `perf_hooks.test.ts`
(histogram output identical to the previous build and to Node),
`image.test.ts`, `image-adversarial.test.ts`, `sqlite.test.js`,
`node-sqlite.test.ts`.

Not verified locally: Windows and macOS/arm64 builds (libjpeg-turbo Neon
source list, libarchive Windows config, lsquic wincompat). Those need
CI.
2026-09-12 16:24:54 -07:00

105 lines
4.3 KiB
YAML

name: Update SQLite3
permissions:
contents: read
on:
schedule:
- cron: "0 6 * * 0" # Run weekly
workflow_dispatch:
jobs:
check-update:
if: github.repository == 'oven-sh/bun'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check SQLite version
id: check-version
run: |
set -euo pipefail
# Get current version from the header file using SQLITE_VERSION_NUMBER
CURRENT_VERSION_NUM=$(grep -o '#define SQLITE_VERSION_NUMBER [0-9]\+' src/jsc/bindings/sqlite/sqlite3_local.h | awk '{print $3}' | tr -d '\n\r')
if [ -z "$CURRENT_VERSION_NUM" ]; then
echo "Error: Could not find SQLITE_VERSION_NUMBER in sqlite3_local.h"
exit 1
fi
# Convert numeric version to semantic version for display
CURRENT_MAJOR=$((CURRENT_VERSION_NUM / 1000000))
CURRENT_MINOR=$((($CURRENT_VERSION_NUM / 1000) % 1000))
CURRENT_PATCH=$((CURRENT_VERSION_NUM % 1000))
CURRENT_VERSION="$CURRENT_MAJOR.$CURRENT_MINOR.$CURRENT_PATCH"
echo "current=$CURRENT_VERSION" >> $GITHUB_OUTPUT
echo "current_num=$CURRENT_VERSION_NUM" >> $GITHUB_OUTPUT
# Fetch SQLite download page
DOWNLOAD_PAGE=$(curl -sL https://sqlite.org/download.html)
if [ -z "$DOWNLOAD_PAGE" ]; then
echo "Error: Failed to fetch SQLite download page"
exit 1
fi
# Extract latest version and year from the amalgamation link
LATEST_INFO=$(echo "$DOWNLOAD_PAGE" | grep -o 'sqlite-amalgamation-[0-9]\{7\}.zip' | head -n1)
LATEST_YEAR=$(echo "$DOWNLOAD_PAGE" | grep -o '[0-9]\{4\}/sqlite-amalgamation-[0-9]\{7\}.zip' | head -n1 | cut -d'/' -f1 | tr -d '\n\r')
LATEST_VERSION_NUM=$(echo "$LATEST_INFO" | grep -o '[0-9]\{7\}' | tr -d '\n\r')
if [ -z "$LATEST_VERSION_NUM" ] || [ -z "$LATEST_YEAR" ]; then
echo "Error: Could not extract latest version info"
exit 1
fi
# Convert numeric version to semantic version for display
LATEST_MAJOR=$((10#$LATEST_VERSION_NUM / 1000000))
LATEST_MINOR=$((($LATEST_VERSION_NUM / 10000) % 100))
LATEST_PATCH=$((10#$LATEST_VERSION_NUM % 1000))
LATEST_VERSION="$LATEST_MAJOR.$LATEST_MINOR.$LATEST_PATCH"
echo "latest=$LATEST_VERSION" >> $GITHUB_OUTPUT
echo "latest_year=$LATEST_YEAR" >> $GITHUB_OUTPUT
echo "latest_num=$LATEST_VERSION_NUM" >> $GITHUB_OUTPUT
# Debug output
echo "Current version: $CURRENT_VERSION ($CURRENT_VERSION_NUM)"
echo "Latest version: $LATEST_VERSION ($LATEST_VERSION_NUM)"
- name: Update SQLite if needed
if: success() && steps.check-version.outputs.current_num < steps.check-version.outputs.latest_num
env:
LATEST_NUM: ${{ steps.check-version.outputs.latest_num }}
LATEST_YEAR: ${{ steps.check-version.outputs.latest_year }}
run: |
./scripts/update-sqlite-amalgamation.sh "$LATEST_NUM" "$LATEST_YEAR"
- name: Create Pull Request
if: success() && steps.check-version.outputs.current_num < steps.check-version.outputs.latest_num
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
add-paths: |
src/jsc/bindings/sqlite/sqlite3.c
src/jsc/bindings/sqlite/sqlite3_local.h
src/jsc/bindings/sqlite/NodeSqlite.cpp
commit-message: "deps: update sqlite to ${{ steps.check-version.outputs.latest }}"
title: "deps: update sqlite to ${{ steps.check-version.outputs.latest }}"
delete-branch: true
branch: deps/update-sqlite
body: |
## What does this PR do?
Updates SQLite to version ${{ steps.check-version.outputs.latest }}
Compare: https://sqlite.org/src/vdiff?from=${{ steps.check-version.outputs.current }}&to=${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-sqlite3.yml)