Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
443 commits
Select commit Hold shift + click to select a range
b94b3a2
ci: unflake the reload-leak check — triage sanitizer output instead o…
mreiden Aug 12, 2026
f66ed29
conf: quiet the gzip_vary-off warnings when a compression_vary module…
mreiden Aug 12, 2026
44fd234
ci: gate the ASAN smoke step on leaks, fix the two unstable check nam…
eilandert Aug 13, 2026
a8c6f19
tools: give nginx teardown a 30s reap budget (second flake class) (#114)
eilandert Aug 13, 2026
de4ced9
tools: close the last two tight teardown reaps in the coverage suite …
eilandert Aug 13, 2026
802624f
fix(filter): latch first-call init; keep data-less bufs out of buffer…
hvelioniskis Aug 13, 2026
901aaa7
fix: guard zero-delta input-buffer pointer update; unique test temp f…
eilandert Aug 13, 2026
6a17abd
ci: wait for the dpkg lock instead of dying on it (third flake class)…
mreiden Aug 14, 2026
211844a
build: test Windows toolchains (#120)
eilandert Aug 18, 2026
a80d8d6
ci: two apt network profiles, one conf file per job
mreiden Aug 21, 2026
a9f5b39
fix(static): opt in to byte ranges like gzip_static (reverses f7e2ef3…
mreiden Aug 21, 2026
0780bbf
test: force the two timing-dependent filter paths every run (#125)
mreiden Aug 21, 2026
844446b
build: bump the Windows nginx pin to 1.31.4 (#124)
mreiden Aug 21, 2026
d525de7
ci: service the #121 merge nits -- comment dedupe, phantom case dropp…
mreiden Aug 21, 2026
3db29cd
ci: vendor the ast-grep ruleset and pre-commit gates (#127)
eilandert Aug 21, 2026
c0ddc63
ci: adopt the skeleton layout, runner identity and PR orchestrator (s…
eilandert Aug 22, 2026
214c750
ci: adopt the skeleton workflow set, test layers and linter retarget …
eilandert Aug 22, 2026
1c260b5
ci: depth pass, docs, adoption stamp (steps 30-42) (#131)
eilandert Aug 22, 2026
8e68693
ci(lint): coverage table, and close the two gaps it found (#132)
eilandert Aug 22, 2026
001364b
fix(valgrind): drop the copied suppression file that muted the Cond c…
eilandert Aug 22, 2026
6265158
ci-deep: add a jobs input so a dispatch can run a subset (#134)
eilandert Aug 22, 2026
17a90e0
test(lint): cover the two lint.yml gates that are not lint-*.sh scrip…
eilandert Aug 22, 2026
708925e
docs: point the reproduce commands at ci/ after the skeleton move (#136)
eilandert Aug 22, 2026
ca98c82
ci(deep): point the monthly scanners job at src/ and let it fail (#137)
eilandert Aug 22, 2026
3d8fc2c
test: reproduce sub_filter/CCtx-reset regression with uncoalesced bac…
eilandert Aug 22, 2026
bdadb06
ci: gate heavy build lanes behind validation (#139)
eilandert Aug 22, 2026
288908f
security(dcz): fail closed on duplicate negotiation headers (#140)
eilandert Aug 22, 2026
24c6a96
docs(ci): correct the lane comment to the measured 12-slot pool (#141)
eilandert Aug 23, 2026
8096994
fix: apply the 2026-08-23 audit findings (#142)
eilandert Aug 23, 2026
049dacc
ci/tools/soak.sh: enumerate all response variants, hard-fail on unkno…
eilandert Aug 23, 2026
5e4cf31
fuzz(dcz): extract digest-decode helper, add second harness (#144)
eilandert Aug 23, 2026
ce5e1c3
refactor: extract q-fraction digit-walk out of eval_qvalue (#145)
eilandert Aug 23, 2026
869e832
refactor(static): extract the .zst frame probe into a pure, testable …
eilandert Aug 23, 2026
18a7613
ci: regenerate pre-commit config, refresh vendored ast-grep rules (#147)
eilandert Aug 23, 2026
910bdbf
perf: pass zlcf to ngx_http_zstd_filter_get_buf() instead of re-fetch…
eilandert Aug 23, 2026
f2001d6
perf: reuse a worker-lifetime ZSTD_CCtx across responses (#148)
eilandert Aug 23, 2026
e8dc483
docs: note that zstd_min_length cannot apply to chunked responses (#150)
eilandert Aug 23, 2026
3434bf4
ci: add request-path A/B benchmark harness (ab_bench.py) (#151)
eilandert Aug 24, 2026
131b1a7
ci(tools): add config_bench.py, a config-load A/B harness (#152)
eilandert Aug 24, 2026
97fa10d
perf: drop the unread request pointer from the filter context (#153)
eilandert Aug 24, 2026
b6b50d7
perf: config-time caching — preformat variable, free dict buffer (#154)
eilandert Aug 24, 2026
b1557a3
fix(ab_bench): escape the literal percent in --comp-level help (#156)
eilandert Aug 24, 2026
466dfb8
perf: per-profile CCtx slot ring, sized at 4 by measurement (#155)
eilandert Aug 24, 2026
184ebcd
perf(filter): output/streaming allocation and buffer-sizing cleanups …
eilandert Aug 24, 2026
718958b
security: validate skippable .zst frames beyond the four-byte magic (…
eilandert Aug 24, 2026
8fce91d
security: enforce RFC 9842 secure-context before selecting dcz (#158)
eilandert Aug 24, 2026
9ba4f81
security(dcz): key shared caches on the Sec-Fetch-Site cross-origin d…
eilandert Aug 24, 2026
97ef7b3
security(ci): trust-anchor every download that is unpacked or execute…
eilandert Aug 24, 2026
bc364ed
security: run the .zst frame probe on Windows too (#162)
eilandert Aug 24, 2026
947a8b4
security(vary): emit Vary: Accept-Encoding by construction, not by di…
eilandert Aug 24, 2026
afcf5e6
fix: stop nginx -t dying with SIGFPE on zstd_long + zstd_max_cctx_mem…
eilandert Aug 24, 2026
f64eaca
security(dict): reject non-regular dictionary paths, add strict trust…
eilandert Aug 24, 2026
e4c15c6
feat: warn when an enabled zstd profile commits large per-request mem…
eilandert Aug 24, 2026
dc0cac1
security(buffers): bound the aggregate zstd_buffers number*size at co…
eilandert Aug 24, 2026
70593d6
batch G6 — seven verified NITs (#168)
eilandert Aug 24, 2026
4db03aa
ci: add dcz CDict-vs-refPrefix equivalence probes (refutes the config…
eilandert Aug 24, 2026
6f672a5
perf: cache zstd_dict_file CDicts in a cycle-wide profile registry (#…
eilandert Aug 24, 2026
3256288
perf(dict): build static-API trained CDicts by reference, not by copy…
eilandert Aug 24, 2026
6882c44
refactor: Remove duplicated Available-Dictionary framing gate in dcz_…
eilandert Aug 24, 2026
a357575
perf(cctx): return the CCtx loan through its lending slot, not a ring…
eilandert Aug 24, 2026
d7660e5
perf(cctx): refactor slot profile comparison into portable unit (#174)
eilandert Aug 25, 2026
9852547
perf(dcz): single-pass header collection for Available-Dictionary and…
eilandert Aug 25, 2026
4f8cef6
perf: fuse chain-copy and tail-track in one pass (#176)
eilandert Aug 25, 2026
2979ca0
perf: pack CCtx memory profile into one 64-bit key (#177)
eilandert Aug 25, 2026
c66cdeb
perf: add HEAD fast path in static handler (#179)
eilandert Aug 25, 2026
ab77ca2
feat: add markdownlint config and fix substantive findings (#180)
eilandert Aug 25, 2026
569001a
refactor: extract token validation from ngx_http_zstd_set_bypass_vary…
eilandert Aug 25, 2026
944e6ae
perf: skip filter/static hook registration when the module is off eve…
eilandert Aug 25, 2026
04ada99
config_bench: raise location-workload scale points to clear the 50ms …
eilandert Aug 25, 2026
fbaca91
perf: make $zstd_ratio/$zstd_bytes_in/$zstd_bytes_out dynamically cac…
eilandert Aug 25, 2026
ec468ae
warn: couple direct header/cookie zstd_bypass predicates to their cac…
eilandert Aug 25, 2026
dda136b
Add early subrequest guard to ngx_http_zstd_header_filter() (#186)
eilandert Aug 25, 2026
ab66a42
Raise dcz-dicts scale points to clear 50ms harness floor. (#187)
eilandert Aug 25, 2026
62dc98b
fix: clamp the dcz window to the CCtx memory budget and key the ring …
eilandert Aug 25, 2026
75f4166
Inline the dcz 40-byte prefix into the first compressor buffer (#189)
eilandert Aug 25, 2026
c9f97ed
test: vendor the testkit harness and make the libzstd failure arms re…
eilandert Aug 25, 2026
96d69eb
ci: run the gate on push: master so the default branch has a CI signa…
eilandert Aug 26, 2026
24c29a2
test: run the harness under memcheck and coverage, add an allocation …
eilandert Aug 26, 2026
5f2cc77
test: bump vendored testkit harness to 5f7986c (#194)
eilandert Aug 26, 2026
9251bef
fix(dict): read dictionary files to completion (#195)
eilandert Aug 26, 2026
76f8815
fix: emit a writer-legal zero-size last_buf on a terminal empty frame…
eilandert Aug 26, 2026
c67d0ff
fix: align the directio probe offset so a skippable-prefixed .zst is …
eilandert Aug 26, 2026
9cf7229
fix(dcz): verify the supplied dictionary hash instead of trusting it …
eilandert Aug 27, 2026
185e341
security: resolve strict dictionary paths per component and verify ow…
eilandert Aug 27, 2026
987f39f
Batch MINOR/NIT audit rows: byte counter, Vary dedup, helpers, copyri…
eilandert Aug 27, 2026
c7b190e
tests: pin the lenient Accept-Encoding non-q parse as the intended co…
eilandert Aug 27, 2026
b534d6a
fix(static): defer Vary emission until the .zst is proven a usable va…
eilandert Aug 27, 2026
34a56f4
fix: never cache a CCtx under the INVALID profile sentinel (n12) (#204)
eilandert Aug 27, 2026
15f23dc
test(probe): wire the PALLOC fault site and cover allocation-failure …
eilandert Aug 27, 2026
a3cce59
ci: say the apt conf file is load-bearing (#126 merge note) (#129)
mreiden Aug 27, 2026
bb35c1d
ci: fix apt cache save, cap fuzz timeout, bump Node-24 action pins (#…
eilandert Aug 27, 2026
6038ff2
fix: print $zstd_bytes_* through the unsigned %uL (#207)
eilandert Aug 27, 2026
7a68f92
fix: cap the directio frame-probe alignment at 64 KB (#208)
eilandert Aug 27, 2026
b73ab25
perf: close the frame on the final input buffer's own ZSTD_e_end call…
eilandert Aug 27, 2026
6fa0e77
perf(static): reuse a worker-lifetime directio scratch buffer, combin…
eilandert Aug 27, 2026
74b8e00
perf: skip ZSTD_compressBound() for known-large bodies, unroll the qv…
eilandert Aug 27, 2026
0c3faee
Batch NIT rows: fix volatile test-count documentation and dcz buffer …
eilandert Aug 27, 2026
0d35e52
fix: correct false ILP32 proof in compressBound skip gate, add qvalue…
eilandert Aug 27, 2026
9b45cd1
fix: stop double-counting the dcz 40-byte prefix in $zstd_bytes_out (…
eilandert Aug 27, 2026
09a7dd9
fix: soak.sh ASan/UBSan gate on finding content, not log existence (A…
eilandert Aug 27, 2026
1ab15dc
fix: negotiate across chained Accept-Encoding lines, retry/accumulate…
eilandert Aug 27, 2026
e7203a4
Add perf stat counter-delta recipe for data-layout repack row (#217)
eilandert Aug 27, 2026
83a1763
test: prove all six ZSTD_freeCCtxParams exits in the config-time cctx…
eilandert Aug 27, 2026
ad6cc49
ci: give the smoke-tests leak check a positive control (#219)
eilandert Aug 27, 2026
65c797e
feat(dcz): zstd_dcz_dict_trust_hashes — opt out of hash verification …
mreiden Aug 28, 2026
cb96fa3
test(harness): cover refPrefix failure (#221)
eilandert Aug 28, 2026
8f2778c
feat(static): add dictionary bypass (#222)
eilandert Aug 28, 2026
90eef42
fix(perf): measure the dcz lookup workload (#223)
eilandert Aug 28, 2026
3fe81cf
chore: remove CodeRabbit config (#224)
eilandert Aug 28, 2026
2cc4b69
perf: skip superseded libzstd parameters per dictionary mode (#225)
eilandert Aug 28, 2026
426c41c
parser: single-pass Accept-Encoding parameter scan (#226)
eilandert Aug 28, 2026
0beb26c
fix: 32-bit off_t hardening for the streaming zstd_max_length cap (#227)
eilandert Aug 28, 2026
5f4f7b0
ci: install gcc-multilib so the 32-bit off_t fixtures actually run (#…
eilandert Aug 28, 2026
298579e
fix: guard the output-side zero-delta pointer advance for UB symmetry…
eilandert Aug 28, 2026
ecae878
style: log-text and doc-comment sweep across both modules (#231)
eilandert Aug 28, 2026
4ce7df8
style: name magic numbers, correct stale docs, const-qualify read-onl…
eilandert Aug 28, 2026
e76020a
perf(static): reuse the aligned probe block across the skip-frame wal…
eilandert Aug 28, 2026
73c1119
perf: hoist dcz's cheap gate, fold vary_dcz's two token checks (#235)
eilandert Aug 28, 2026
cd29405
[NIT][perf] dcz window_log computed twice per dcz request (#234)
eilandert Aug 28, 2026
e491e2f
perf(debug): guard profile_unpack behind NGX_DEBUG and the runtime lo…
eilandert Aug 28, 2026
18c0957
fix(build): stop leaking -DZSTD_STATIC_LINKING_ONLY into dynamic fall…
eilandert Aug 28, 2026
deb05b5
docs: fix README compatibility, Vary, and benchmark accuracy (R3-F2/F…
eilandert Aug 28, 2026
0773025
sweep-nit: root t/servroot gitignore, dcz window-cap floor, TEST 49 w…
eilandert Aug 28, 2026
49c37ea
docs(dcz): correct the window-cap floor comment; pin the no-dcz budge…
eilandert Aug 29, 2026
0d7ea97
refactor(static): decompose ngx_http_zstd_static_handler into three h…
eilandert Aug 29, 2026
6abbc35
docs: correct dcz prefix directive, add three missing directive entri…
eilandert Aug 29, 2026
4ab3b8f
ci: close three A29 CI-integrity gaps (CodeQL scope, TAP zero-test pa…
eilandert Aug 29, 2026
fc090db
ci: enforce fuzz regression naming
eilandert Aug 29, 2026
668c6af
ci: smoke-test Windows zstd requests
eilandert Aug 29, 2026
5fbe48f
ci: add native arm64 zstd smoke
eilandert Aug 29, 2026
87101aa
ci: lock Test::Nginx CPAN install
eilandert Aug 29, 2026
b1059b0
ci: forbid static-only zstd imports
eilandert Aug 29, 2026
afd803c
ci: fail closed on indeterminate LSan (#253)
eilandert Aug 29, 2026
141fd33
filter: honor no-transform responses (#251)
eilandert Aug 29, 2026
428dd1c
static: reject reserved zstd descriptor bit (#252)
eilandert Aug 29, 2026
20383e2
ci: bump artifact actions to their Node-24 defaults; cap retention at…
mreiden Aug 29, 2026
9c65227
fix(static): warn at config load when dict_bypass has no filter modul…
mreiden Aug 29, 2026
1269e93
filter: honor a no-transform directive that carries an argument (#254)
mreiden Aug 29, 2026
1ea70dc
ci: close A29 sweep checks
eilandert Aug 29, 2026
0394f3d
Merge pull request #255 from myguard-labs/grind/a29-docs-sweep
eilandert Aug 29, 2026
9e6d648
ci: close A29 second-pass audit gaps (#256)
eilandert Aug 29, 2026
13b40fe
refactor(static): finish probe decomposition (#257)
eilandert Aug 29, 2026
74ee343
perf: reduce compressor allocation overhead (#258)
eilandert Aug 29, 2026
b8f2197
perf: use fixed-width frame decodes (#259)
eilandert Aug 29, 2026
4594bbe
perf(filter): retain input chains lazily (#260)
eilandert Aug 30, 2026
cdda5b5
perf(static): reuse probe read-ahead (#261)
eilandert Aug 30, 2026
04ee7d8
perf(dcz): reuse EVP digest context (#262)
eilandert Aug 30, 2026
b998a19
refactor(vary): share token scanner (#263)
eilandert Aug 30, 2026
a76a435
ci: fail closed on work-list errors (#264)
eilandert Aug 30, 2026
ece1b58
ci: check LSan log-list errors (#265)
eilandert Aug 30, 2026
01db16e
ci: check docs work-list errors (#266)
eilandert Aug 30, 2026
b0616ac
ci: share nginx tarball verification (#267)
eilandert Aug 30, 2026
5d97b3f
ci: optimize four-lane workflow scheduling (#268)
eilandert Aug 30, 2026
9bc3abe
ci: clarify fan-out priority heuristic (#269)
eilandert Aug 30, 2026
3810772
ci: unify persistent build inputs (#272)
eilandert Aug 30, 2026
668b50e
ci: waive zizmor self-repository findings (#276)
eilandert Aug 30, 2026
da759b1
fix(static): allow four skipped frames (#273)
eilandert Aug 30, 2026
588757f
fix: parse quoted Cache-Control extensions (#274)
eilandert Aug 31, 2026
f8de2bd
ci: bootstrap fork fallback dependencies (#277)
eilandert Aug 31, 2026
80815da
fix: negotiate repeated Accept-Encoding on legacy nginx (#275)
eilandert Aug 31, 2026
e815d0b
ci: relocate sanitizer suppressions (#271)
eilandert Aug 31, 2026
b7ef25e
test: pin harness to testkit PR 235 (#280)
eilandert Aug 31, 2026
a07d475
refactor(static): extract the frame probe into one authoritative head…
mreiden Aug 31, 2026
86f930f
gitattributes: repair reorg-stale byte-exact patterns; gen_dict CRLF …
mreiden Aug 31, 2026
3490329
ci: verify sanitizer suite integrity (#281)
eilandert Aug 31, 2026
052ff38
ci: harden assurance sweep (#282)
eilandert Aug 31, 2026
fa73ee0
test: tighten soak and length diagnostics (#283)
eilandert Aug 31, 2026
579e723
fix: enforce runtime libzstd feature floors (#284)
eilandert Aug 31, 2026
e33b1d2
docs: clarify zstd_static always contract (#285)
eilandert Aug 31, 2026
19ab951
fix: harden portability and config probes (#286)
eilandert Aug 31, 2026
7530fc9
perf(static): memoize malformed sidecar verdicts (#287)
eilandert Aug 31, 2026
89199b0
fix: harden zstd terminal observability (#290)
eilandert Aug 31, 2026
a6cbad7
fix(probe): narrow the #278 seam claims; guard the seam in CI (#270) …
mreiden Aug 31, 2026
d17ee2a
fix(ci): scan probe test consumers (#291)
eilandert Sep 1, 2026
624dbd5
docs(zstd): narrow zstd_bypass_vary contract to the bypass fork (#292)
eilandert Sep 1, 2026
65b8de7
docs(zstd): state which build path enables -DZSTD_STATIC_LINKING_ONLY…
eilandert Sep 1, 2026
bbd653d
sweep: overflow-safe $zstd_ratio, doc/diagnostic nits (A31b-F6, A30-N…
eilandert Sep 1, 2026
2768ffe
fix(zstd): bound first output buffer at full off_t width on ILP32 (#295)
eilandert Sep 1, 2026
f3ef9be
test(zstd): cover legacy Accept-Encoding branch-equivalence (A30-F1) …
eilandert Sep 1, 2026
ef2f4c9
ci(zstd): retarget .gitattributes byte-exact rules to fuzz fixture di…
eilandert Sep 1, 2026
2feefc5
ci(zstd): CI reliability sweep (LASTEXITCODE oracle, coverage bailout…
eilandert Sep 1, 2026
89f7845
docs(zstd): correct static-probe skippable-chain and read semantics (…
eilandert Sep 1, 2026
672eed6
test(zstd): measure dcz refPrefix per-request dictionary cost (A31b-F…
eilandert Sep 1, 2026
d140760
ci(zstd): drop obsolescent test -o and gate the A30-F7 prober rebuild…
eilandert Sep 1, 2026
460e1f9
Prove the static/dynamic filter-order agreement, and fix the anchor m…
eilandert Sep 1, 2026
c611aa0
sweep: repair pre-move command paths and shfmt drift (#304)
eilandert Sep 1, 2026
fa8ecef
ci(codeql): scope the Security tab by filtering SARIF, not paths-igno…
eilandert Sep 1, 2026
701a94f
ci(testkit): bump ci/t/harness to 9864052 (#306)
eilandert Sep 1, 2026
fe5db23
fix: start without an http block (#284 follow-up) (#308)
eilandert Sep 1, 2026
d45e3b1
docs: correct three stale release claims, changelog the ratio fix (#307)
eilandert Sep 1, 2026
74d7705
refactor(filter): extract the no-transform detection into one authori…
mreiden Aug 31, 2026
37ab8f8
ci: cover the cache-control seam in the definition gate (review)
mreiden Sep 1, 2026
3a89321
ci(testkit): repoint ci/t/harness forward to b4d8ca9 (repairs #306)
mreiden Sep 1, 2026
2bbc710
refactor(filter): extract the ratio split into one authoritative header
mreiden Sep 2, 2026
eb8a887
test: bind the routing check to the handler; C89-safe ngx_inline fall…
mreiden Sep 2, 2026
93df1b2
Merge pull request #309 from mreiden/harness-pin-forward
eilandert Sep 2, 2026
8e6b82f
Merge branch 'master' into cc-header
eilandert Sep 2, 2026
709e49d
Merge pull request #289 from mreiden/cc-header
eilandert Sep 2, 2026
8f81ca0
Merge branch 'master' into ratio-header
eilandert Sep 2, 2026
8fdd0b1
Merge pull request #310 from mreiden/ratio-header
eilandert Sep 2, 2026
dae83c1
ci: bump the manual pins -- nginx 1.31.5, pcre2 10.48 (Windows + harn…
mreiden Sep 3, 2026
328795c
perf(dcz): prove the CDict hoist is a wire-format change, not a free …
eilandert Sep 3, 2026
982ee5d
static: fail closed on duplicate Available-Dictionary, fix stale-errn…
eilandert Sep 3, 2026
c010a0d
perf(accept-encoding): parse each field line once in the chain walker…
eilandert Sep 3, 2026
0cb114d
security: vet ancestor directories in zstd_dict_strict_path walk (#316)
eilandert Sep 3, 2026
44ff884
build: let the EVP probe see a prepared OpenSSL tree on MSVC (#317)
mreiden Sep 3, 2026
5fd237e
build(windows): pins file, module-derived library builds, fail-fast f…
mreiden Sep 3, 2026
dcaedab
ci: bump-versions.sh learns the harness and Windows pins; windows-bui…
mreiden Sep 3, 2026
e048e8a
fix(static): rate-limit directio probe hard-error log (A33-F4(b)) (#320)
eilandert Sep 4, 2026
2ccb147
perf: A33 micro/substitution NIT sweep (P7-P11, minus one dropped sit…
eilandert Sep 4, 2026
0f14f73
perf(dcz): binary-search the dictionary negotiation lookup above 16 e…
eilandert Sep 4, 2026
ceff8cd
chore: ignore the remaining ci/tests/unit build outputs (#323)
eilandert Sep 4, 2026
1487ff2
perf(vary): fuse the two Vary walks in the dcz dict-bypass path (#324)
eilandert Sep 4, 2026
c33cf13
perf(static): cache the positive frame-probe verdict, not just the ne…
eilandert Sep 4, 2026
427608e
ci(bump): resolve nginx stable/mainline from the GitHub releases feed…
mreiden Sep 4, 2026
e603d9e
feat(packaging): add Arch package (#334)
eilandert Sep 14, 2026
5d62ecc
refactor(filter): extract dictionary file helpers (#328)
mreiden Sep 14, 2026
094ee8c
refactor(filter): move the strict dictionary walk into the dict-file …
mreiden Sep 7, 2026
b9b9fc2
test(dict-file): fixture invariants fail the run; extraction and incl…
mreiden Sep 7, 2026
47be436
test(dict-walk): pass the repository C gates -- no strncpy, no #ifdef…
mreiden Sep 12, 2026
4dcfbf7
test(dict-walk): exercise the logging shell, count every scripted rea…
mreiden Sep 14, 2026
fb27ea3
refactor(filter): split the component scanner out of the strict walk;…
mreiden Sep 7, 2026
cf1ac32
fix(filter): a trailing separator names a directory under the strict …
mreiden Sep 7, 2026
59cc19f
filter: compress 410 Gone responses like 403/404 (core gzip parity, n…
mreiden Sep 9, 2026
2f34a57
filter: the status-set comments name 410 and describe nginx/nginx#146…
mreiden Sep 14, 2026
089479e
test(conf-warn): run the zstd_max_cctx_memory budget block only on an…
mreiden Sep 10, 2026
8a19b92
docs: strict mode refuses a trailing separator as naming a directory
mreiden Sep 15, 2026
4d4c0c7
ci: one nginx release resolver for the workflows, ci-build.sh and the…
mreiden Sep 4, 2026
4231d1f
ci(resolver): check the selector before asking the feed; pin python3 …
mreiden Sep 4, 2026
70bb931
test(bootstrap): check the bootstrap step itself, not the whole file
mreiden Sep 4, 2026
4889ec4
docs(resolver): list stable before mainline, the order the selector a…
mreiden Sep 4, 2026
9f09538
ci(resolver): per-job bootstrap check, a no-mainline control, provena…
mreiden Sep 14, 2026
428c642
ci(resolver): nginx_lines() fails where the feed read fails
mreiden Sep 15, 2026
95b475a
ci(coverage): run the dictionary path-hardening matrix under the inst…
mreiden Sep 10, 2026
f4230c9
test: reach five request/config paths the coverage build never executed
mreiden Sep 10, 2026
baea62c
test: generated dictionary fixtures via File::Temp, writes checked
mreiden Sep 12, 2026
1bd8001
test: anchor the log-phase record whole, probe nginx -V without a she…
mreiden Sep 14, 2026
58bda87
feat(dcz): warn at config load when dictionaries meet an expensive pr…
eilandert Sep 15, 2026
ac748b2
ci: remove Arch packaging workflow (#344)
eilandert Sep 28, 2026
6d8a873
perf(dcz): profile level-3 raw-prefix request cost
eilandert Sep 28, 2026
79422ce
Merge pull request #343 from myguard-labs/grind/A31-dcz-profile
eilandert Sep 30, 2026
d20a673
chore: bump version pins (2026-09-28) (#342)
eilandert Oct 4, 2026
d244366
A31-dcz-cdict: Cache raw-content CDict for dcz requests — Proceed onl…
eilandert Oct 4, 2026
4cb1d4f
static: keep the directio probe's scratch buffer in the main conf, fr…
mreiden Oct 20, 2026
f06d09b
probe hooks: drop the "(Phase 3)" label from the codec fault-injectio…
mreiden Oct 20, 2026
882d6c5
Accept-Encoding parser: one authoritative header, moved verbatim out …
mreiden Oct 20, 2026
0c78af4
packaging(arch): build against nginx 1.30.6 (#339)
mreiden Oct 20, 2026
eeebefa
ci(bump): a fork without BUMP_PR_TOKEN skips green; anywhere else it …
mreiden Oct 20, 2026
2571f4d
ci(bump): carry the Arch package's nginx pin with the other stable pi…
mreiden Oct 20, 2026
28570f3
perf(cctx): return the CCtx when the frame ends, not at request end (…
hsw Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
34 changes: 34 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# nginx coding style for C modules
# Based on nginx source conventions: 4-space indent, 80-col limit,
# aligned struct members and macros (nginx hallmark style).
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 80
BreakBeforeBraces: Linux
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
IndentCaseLabels: false
SpaceBeforeParens: ControlStatements
PointerAlignment: Right
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignConsecutiveAssignments: false
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
SortIncludes: false
ReflowComments: false
BreakBeforeTernaryOperators: true
AlwaysBreakAfterReturnType: None
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceInEmptyParentheses: false
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

[*.{sh,bash}]
indent_style = space
indent_size = 4
switch_case_indent = true
binary_next_line = true
45 changes: 45 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,46 @@
*.t linguist-language=Text

# Files that are executed or sourced by POSIX sh/perl on Linux (including
# WSL builds from a Windows checkout) must stay LF: nginx's ./configure
# sources `config`/`auto/zstd` with sh, which treats a CR as part of the
# line and fails with "$'\r': command not found" when core.autocrlf=true
# has smudged the checkout to CRLF.
config text eol=lf
auto/* text eol=lf
*/config text eol=lf
*.sh text eol=lf
*.t text eol=lf

# Byte-exact fixtures: fuzz corpus entries are raw Accept-Encoding header
# bytes and .zst files are compressed frames — any EOL conversion corrupts
# them.
ci/fuzz/corpus/* -text
ci/fuzz/fuzz.dict -text
*.dict -text
*.zst binary

# t/suite/test's byte length is asserted verbatim by the static suite
# (Content-Length and the size half of the ETag) — CRLF smudging changes
# the on-disk size and fails every identity-response assertion.
ci/t/suite/* -text

# More byte-exact fuzz fixtures: corpus_dcz/* are raw dcz-dict header
# bytes, and regressions{,_dcz}/* are saved crash-reproducer inputs —
# core.autocrlf=true would smudge either and corrupt the fuzzer's inputs
# or make a saved crash stop reproducing. Each regressions dir also has a
# real README.md, which must stay text; order it after the wildcard so
# the more specific rule wins.
ci/fuzz/corpus_dcz/* -text
ci/fuzz/regressions/* -text
ci/fuzz/regressions/README.md text
ci/fuzz/regressions_dcz/* -text
ci/fuzz/regressions_dcz/README.md text

# CI-only stub module (linkage-isolation job); keep it out of release
# tarballs (git archive). Its former sibling, the vary-suppression
# stub, no longer exists in the tree.
/ci/tools/ci-linkcheck-module export-ignore

# Patches are applied with git apply against LF checkouts; CRLF
# smudging would make every context line mismatch.
ci/tools/patches/** text eol=lf
75 changes: 75 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# .githooks/pre-commit -- tracked, reviewable commit gate.
#
# Lives in the repo (unlike .git/hooks/, which is per-clone and invisible to
# review), so a change to what the gate checks arrives as a diff.
#
# Enable once per clone:
# git config core.hooksPath .githooks
# Emergency bypass:
# git commit --no-verify
#
# It lints only the STAGED files, so a commit is never blocked by a finding in
# a file it does not touch. Run the whole tree yourself with:
# ci/linter/run-all.sh
# pre-commit run --all-files
#
# TWO GATES, ONE ENTRY POINT, AND THE REASON THIS FILE CALLS BOTH.
#
# `core.hooksPath` REPLACES .git/hooks/ -- git does not consult both. So the
# hook that `pre-commit install` writes into .git/hooks/pre-commit becomes
# unreachable the moment core.hooksPath is set, and .pre-commit-config.yaml
# stops running on commit while still looking installed from every angle a
# human checks: the config is present, `pre-commit install` reported success,
# and the file is right there in .git/hooks/. Measured 2026-08-02 in this repo:
# a file with trailing whitespace and no closing newline committed clean, past
# hooks whose entire job is those two things -- and past detect-private-key,
# flawfinder and semgrep with it.
#
# Neither list is a superset of the other (ci/linter/ owns the workflow-policy
# and docs-drift checks; .pre-commit-config.yaml owns secret detection and the
# C SAST gates), so this hook runs BOTH and fails on either.
#
# Exit 2 (a tool is not installed) blocks the commit on purpose: a gate that
# skips itself when its tool is missing reports green while checking nothing.
# That applies to pre-commit itself, which is why its absence is fatal here
# rather than a warning.
#
# VERIFY BEFORE TRUSTING (this gate was green and inert for days):
# printf 'probe \n\nno newline at eof' > _p.txt
# git add _p.txt && git commit -m probe -- _p.txt # expect BLOCKED
# git reset -q HEAD _p.txt; rm -f _p.txt
# Both `trim trailing whitespace` and `fix end of files` must report Failed. If
# the commit lands, .pre-commit-config.yaml is not being consulted.
set -uo pipefail

ROOT="$(git rev-parse --show-toplevel)"

"$ROOT/ci/linter/run-all.sh" --staged
rc=$?
if [ "$rc" -eq 2 ]; then
echo "pre-commit: missing linters -- run ci/linter/install-linters.sh" >&2
exit 2
elif [ "$rc" -ne 0 ]; then
echo "pre-commit: lint failed -- fix, or commit with --no-verify" >&2
exit "$rc"
fi

if [ -f "$ROOT/.pre-commit-config.yaml" ]; then
if ! command -v pre-commit >/dev/null 2>&1; then
echo "pre-commit: .pre-commit-config.yaml present but pre-commit is not" \
"installed -- pipx install pre-commit" >&2
exit 2
fi
# No `pre-commit install` needed and none is wanted: that command writes to
# .git/hooks/, which core.hooksPath has already taken out of the picture.
pre-commit run --hook-stage pre-commit
rc=$?
if [ "$rc" -ne 0 ]; then
echo "pre-commit: .pre-commit-config.yaml hooks failed -- fix, or commit" \
"with --no-verify. Fixer hooks may have rewritten files; re-stage." >&2
exit "$rc"
fi
fi

exit 0
2 changes: 2 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
self-hosted-runner:
labels: [builder02, lxc, docker]
19 changes: 19 additions & 0 deletions .github/scripts/configure-msvc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
# Configure the Windows/MSVC CI build after vcvars64.bat has initialized the
# parent cmd process. Kept in a real bash file because a GitHub custom `cmd`
# shell wraps inline run blocks in a .cmd file, which bash cannot parse.

set -euo pipefail

module_dir=$(cygpath -m "$GITHUB_WORKSPACE")
zstd_root=$(cygpath -m \
"$VCPKG_INSTALLATION_ROOT/installed/x64-windows-static")

ZSTD_INC="$zstd_root/include" ZSTD_LIB="$zstd_root/lib" \
./configure \
--crossbuild=win32 \
--with-cc=cl \
--with-cc-opt='-MT -DFD_SETSIZE=1024' \
--with-pcre="$module_dir/pcre2-$PCRE2_VERSION" \
--with-zlib="$module_dir/zlib-$ZLIB_VERSION" \
--add-module="$module_dir"
132 changes: 132 additions & 0 deletions .github/workflows/asan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: A/UBSan

# Dedicated ASan+UBSan soak — mirrors the fast build-asan job in build-test.yml
# (same configure flags, same PGP-verified tarball) but drives it through
# soak.sh's sustained mixed-load traffic instead of the Test::Nginx suite, the
# same way valgrind.yml's memcheck-lite job soaks the debug build. Two
# independent dynamic-analysis lenses on the same binary shape catch different
# things: ASan/UBSan is fast enough to run a real request storm in CI Deep
# and catches heap overflow / UAF outside nginx's pool blocks; Valgrind (20x
# slower) still catches the uninitialised reads and intra-pool UAF that ASan
# cannot see. Complementary, not redundant -- keep both.
#
# The asan build is a STATIC --add-module binary (the module is linked into
# the nginx binary, there is no separate .so), so the sanitizer runtime is
# present on every code path soak.sh exercises.
#
# Action pins (keep in sync with build-test.yml / valgrind.yml headers):
# actions/checkout@v5.1.0 -> fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
NGINX_VERSION: ""

on:
workflow_dispatch: {}
# Called by ci.yml, the single PR entry point.
workflow_call: {}

concurrency:
group: asan-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
asan-soak:
name: ASan/UBSan soak (60s)
runs-on: ${{ fromJSON(vars.POOL || '["ubuntu-latest"]') }}
timeout-minutes: 45
steps:
- name: Checkout module
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false

# `vars.POOL` is absent in forks, so do not rely on the hosted image
# carrying curl before the full dependency installation below.
- name: Install bootstrap dependencies
run: |
sudo apt-get update
sudo apt-get install -y ca-certificates curl python3

- name: Resolve latest mainline nginx
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
ver=$(bash "$GITHUB_WORKSPACE/ci/tools/nginx-releases.sh" mainline)
[ -n "$ver" ] || { echo "::error::cannot resolve nginx version"; exit 1; }
echo "NGINX_VERSION=$ver" >> "$GITHUB_ENV"

- name: Install dependencies
run: |
# builder02 apt profile: loose timeouts — the box runs jobs
# concurrently and never talks to the Azure mirror (PR #121)
printf '%s\n' \
'DPkg::Lock::Timeout "120";' \
'Acquire::Retries "3";' \
'Acquire::http::Timeout "20";' \
'Acquire::https::Timeout "20";' \
| sudo tee /etc/apt/apt.conf.d/99-ci-net > /dev/null
sudo apt-get update
sudo apt-get install -y \
build-essential curl gnupg libpcre2-dev libzstd-dev openssl pkg-config \
wget zlib1g-dev zstd

- name: Cache nginx source tarball
id: nginx-tarball
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
with:
path: nginx-${{ env.NGINX_VERSION }}.tar.gz
key: nginx-src-${{ env.NGINX_VERSION }}

- name: Download nginx source tarball
if: steps.nginx-tarball.outputs.cache-hit != 'true'
run: wget -q "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"

- name: Verify nginx tarball PGP signature
run: |
set -euo pipefail
wget -q "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc" \
-O "nginx-${NGINX_VERSION}.tar.gz.asc"
gnupghome="$(mktemp -d)"
export GNUPGHOME="$gnupghome"
chmod 700 "$gnupghome"
for keyfile in ci/tools/keys/*.key; do
gpg --quiet --import "$keyfile" 2>/dev/null
done
gpg --quiet --verify "nginx-${NGINX_VERSION}.tar.gz.asc" "nginx-${NGINX_VERSION}.tar.gz"
rm -rf "$gnupghome"

# soak.sh requires ok>0 and bad==0 per worker, where a zstd-magic
# response must ALSO decode cleanly (ci/tools/soak.sh's worker()):
# a green result proves the module actually compressed real
# responses under the sanitizer, not merely that nothing crashed.
# It sets its own ASAN_OPTIONS/UBSAN_OPTIONS with halt_on_error=1
# so the soak fails loudly on the first report.
- name: Configure & build nginx with ASAN + UBSAN (static --add-module)
env:
# Keep the portable SHA-256 fallback covered under the sanitizer --
# see build-test.yml's identical build-asan job for why.
NGX_ZSTD_NO_LIBCRYPTO: 1
run: |
tar -xzf "nginx-${NGINX_VERSION}.tar.gz"
cd "nginx-${NGINX_VERSION}"
SAN="-fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer -g3 -O1"
./configure \
--with-compat \
--with-debug \
--with-cc-opt="-DZSTD_STATIC_LINKING_ONLY $SAN $(pkg-config --cflags libzstd zlib libpcre2-8)" \
--with-ld-opt="$SAN $(pkg-config --libs libzstd zlib libpcre2-8)" \
--add-module="$GITHUB_WORKSPACE"
make -j"$(nproc)"
if grep -q 'NGX_HTTP_ZSTD_HAVE_LIBCRYPTO' objs/ngx_auto_config.h; then
echo "libcrypto leaked into the portable-fallback build"; exit 1
fi

- name: ASan/UBSan soak (60s @ 4 conc)
run: |
bash ci/tools/soak.sh \
"$GITHUB_WORKSPACE/nginx-${NGINX_VERSION}/objs/nginx" 60 4
Loading
Loading