Rich Bowen [Mon, 15 Jun 2026 19:14:34 +0000 (19:14 +0000)]
Sync trunk mod_rewrite doc with enhancements to 2.4
At some point, I made an update to the 2.4 doc and didn't make it in
trunk. This improves the "what gets matched" and "per-directory" bits of
the RewriteRule doc.
Rich Bowen [Mon, 15 Jun 2026 18:27:50 +0000 (18:27 +0000)]
Reorg of TestString section of RewriteCond doc
bz#70093 recommended merging all of the RewriteCon test string stuff
into one massive flat list, and the more I worked on it, the more it
seemed that this would make the document more confusing and more
overwhelming. It's already a massive doc, and presenting it without any
internal subdivision makes it a huge wall of text and unreadable.
Instead, it's subdivided into categories of stuff that can go in a
RewriteCond test strong.
Resolves 70093, although in a very different way from what was
requested.
Rich Bowen [Thu, 11 Jun 2026 20:10:17 +0000 (20:10 +0000)]
Refocus install.xml on source builds; style cleanup
- Rewrite summary to lead with "released as source code" framing
- Move RPM/DEB quick-install content to "Third-party packages" at end
- Simplify "Overview for the impatient" to source-build steps only
- Update PCRE requirement to PCRE2 (matching configure.in)
- Fix bare "Apache" → "httpd" throughout (per style guide)
- Remove all double-space-after-period instances
- Rewrite timekeeping paragraph (drop pun, modernize)
- Add <highlight language="sh"> to all shell example blocks
- Rename win_compiling.xml title: "Compiling Apache httpd for Microsoft Windows"
Rich Bowen [Thu, 11 Jun 2026 12:57:46 +0000 (12:57 +0000)]
mod_rewrite: Clarify Substitution description
The opening sentence of the Substitution section implied that Pattern
always matches when a rule fires, which is incorrect for negated rules.
Reword to be neutral about how the rule was triggered, and add a
cross-reference to "What is matched?" for context.
Joe Orton [Thu, 11 Jun 2026 11:38:41 +0000 (11:38 +0000)]
* modules/generators/mod_cgid.c (close_unix_socket): Return errno
on failure rather than -1.
(sock_write): Handle short writes.
(cgid_init): Fix off-by-one in socket path truncation.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
GitHub: resolves PR#669
Joe Orton [Thu, 11 Jun 2026 11:38:22 +0000 (11:38 +0000)]
* modules/generators/mod_cgid.c (get_req): Fix wrong sizeof in
allocation of core_request_config, which used sizeof(core_module).
(cgid_server): Fix stale rv passed to ap_log_error for passed fd
debug message.
(include_cmd): Fix double registration of cleanup_script which
could kill a garbage pid when get_cgi_pid failed. Check return
value of send_req. Change return type to apr_status_t to match
declaration in cgi_common.h
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
GitHub: PR#669
Joe Orton [Thu, 11 Jun 2026 11:37:45 +0000 (11:37 +0000)]
* modules/generators/mod_cgid.c (cgid_req_t): Change env_count to
unsigned. Define ENV_COUNT_MAX.
(get_req): Add upper bounds for uri_len, args_len, and env_count.
Validate per-variable length in environment reading loop.
Move validation before use of loglevel.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
GitHub: PR#669
Submitted by: jorton Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193517213f79535-47bb-0310-9956-ffa450edef68
Joe Orton [Tue, 9 Jun 2026 16:39:56 +0000 (16:39 +0000)]
* test/modules/core: Add test case for CVE_2026-43951.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193517113f79535-47bb-0310-9956-ffa450edef68
Joe Orton [Tue, 9 Jun 2026 06:39:25 +0000 (06:39 +0000)]
* configure.in: Fix cross-compilation:
./configure fails finding .pc files, because it uses the build
architecture pkg-config. It should be using AC_PATH_TOOL (or better
PKG_PROG_PKG_CONFIG) rather than AC_PATH_PROG.
Joe Orton [Mon, 8 Jun 2026 13:13:49 +0000 (13:13 +0000)]
CI: Configure GitHub workflows to use concurrency cancel-in-progress for
pull requests
see recommended best practices at Apache
https://cwiki.apache.org/confluence/pages/viewpage.action?spaceKey=INFRA&title=GitHub+Actions+Recommended+Practices
Rich Bowen [Fri, 5 Jun 2026 19:55:22 +0000 (19:55 +0000)]
Update misc/relevant_standards to reflect current RFCs
Replace obsolete RFC references (2616, 2396, 4346, 2617) with their
modern successors. Add sections for TLS, proxying, WebSocket, CGI, and
WebDAV. Remove HTML section (httpd does not validate content markup).
Remove stale "not yet complete" notice and dead skrb.org errata link.
Jim Jagielski [Fri, 5 Jun 2026 19:07:15 +0000 (19:07 +0000)]
Perl test asserts the opposite of what the server does, and only "passes"
because LWP fabricates the header client-side. Clean this mess up. LWP
is weird.
Jim Jagielski [Fri, 5 Jun 2026 17:48:53 +0000 (17:48 +0000)]
test: port recent httpd-tests 2.4.68 changes to pytest_suite
Reflect the following t/ changes into test/pytest_suite:
* expr: file()/filesize() are restricted in 2.4.68+; gate the
expected results (None => parse error 500) and move file()
into the 2.3.13 block.
* mod_headers: support an optional expected-status field; add
malformed-regex -> 500 and 2.4.68 file()-in-htaccess -> 500.
* mod_dav: PUT to a .DAV state subdir is blocked (403) in
2.4.68+, else 201.
* mod_proxy_html: add multi-substitution buffer-realloc tests
(literal and regex) with ProxyHTMLBufSize 256.
Joe Orton [Fri, 5 Jun 2026 16:54:38 +0000 (16:54 +0000)]
* modules/proxy/mod_proxy_beacon.c (beacon_resolve, beacon_parse_url,
beacon_verify): Use ap_strstr_c and ap_strchr_c for const-correct
string searches, fixing -Werror=discarded-qualifiers errors.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193504013f79535-47bb-0310-9956-ffa450edef68
Joe Orton [Thu, 4 Jun 2026 15:48:00 +0000 (15:48 +0000)]
* modules/proxy/mod_proxy_ftp.c (proxy_ftp_dir_filter): Use
ap_os_escape_path() with ap_escape_html() instead of
ap_escape_uri() for href attributes in generated directory
listing links.
Rich Bowen [Thu, 4 Jun 2026 15:22:55 +0000 (15:22 +0000)]
docs: Rewrite AllowOverride Options= warning
The existing note about implicit disabling of Options was difficult
to parse. Rewrite as a type="warning" note with:
- Clear statement that the restriction controls enabling, not disabling
- Explanation of absolute vs relative (+/-) Options syntax
- Concrete example showing how inherited options get implicitly disabled
Joe Orton [Thu, 4 Jun 2026 09:03:50 +0000 (09:03 +0000)]
mod_proxy_html: Simplify to use the ap_varbuf API.
* modules/filters/mod_proxy_html.c: Include util_varbuf.h.
(saxctxt): Replace buf/offset/avail members with struct ap_varbuf vb.
(DEFAULT_BUFSZ): New macro.
(normalise): Take struct ap_varbuf * parameter instead of char *.
(preserve, pappend): Remove functions, replaced by ap_varbuf_grow
and ap_varbuf_strmemcat respectively.
(dump_content): Use ap_varbuf for regex substitutions via
ap_varbuf_regsub, avoiding manual buffer resizing with
preserve/memmove/memcpy. Use a temporary ap_varbuf for building
regex replacement results.
(pcharacters, pcomment): Use ap_varbuf_strmemcat and ap_varbuf_strcat
in place of pappend.
(pendElement): Check vb.strlen instead of offset.
(pstartElement): Use ap_varbuf for attribute URL rewriting with the
same ap_varbuf_regsub approach. Use a temporary ap_varbuf for
regex replacements.
(proxy_html_filter): Initialize the ap_varbuf with a clamped bufsz.
(proxy_html_merge): Use DEFAULT_BUFSZ macro.
Assisted-by: Claude Opus 4.6 (claude-opus-4-6)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193497513f79535-47bb-0310-9956-ffa450edef68
Jim Jagielski [Wed, 3 Jun 2026 23:23:47 +0000 (23:23 +0000)]
pytest_suite: port Perl todo/xfail gaps found when testing against 2.4.x
Three test files had behaviour differences between the Python port and
the original Perl framework tests when run against a 2.4.x build
(tested with Apache/2.4.68-dev at /opt/local2/apache2).
test_pr64339.py -- LWP vs httpx default charset for raw bodies
For /doc.notxml the proxy returns Content-Type: application/notreallyxml
with no charset and a Latin-1 body. LWP defaults to ISO-8859-1 for
charset-less responses; httpx defaults to UTF-8, decoding 0xF3 as a
replacement character and failing the body match. Add _lwp_text() to
mirror LWP: use the Content-Type charset when present, else Latin-1.
test_session.py -- port Perl @todo for PR 58171 and PR 56052
session.t marks subtests 53/54 (Session writable after decode failure,
PR 58171) and 88/89 (Session writable after expired, PR 56052) as
unconditional @todo. The Python port dropped this bookkeeping. On
2.4.x, ap_session_load() sets zz=NULL on a decode failure and allocates
a fresh session the memoising provider never sees, so nothing is saved;
trunk uses memset-in-place to preserve the provider pointer. Add a
_check(..., todo=True) helper that downgrades failures to warnings,
matching Perl's todo semantics for both subtests.
test_proxy_html.py -- xfail two metafix cases that fail on 2.4.x
other header with Content-Type present: mod_proxy_html metafix emits
no http-equiv headers for meta_contenttype.html because the leading
charset Content-Type meta is consumed by the xml2enc path on 2.4.x.
empty content value: metafix locates the content value via a
case-insensitive search for 'content'; the header name X-Empty-Content
itself matches first, so no value is extracted. Gate both via
pytest.xfail when the server is < 2.5.0, leaving assertions active on
trunk.
Jim Jagielski [Wed, 3 Jun 2026 22:32:17 +0000 (22:32 +0000)]
test/pyhttpd: move pyproject.toml and uv.lock under pyhttpd/
The pyproject.toml and uv.lock belong to the pyhttpd test suite, so move
them from test/ into test/pyhttpd/ where the package itself lives.
Update runtests-pyhttpd.sh to use 'uv sync --project pyhttpd/' and
reference the venv at pyhttpd/.venv/. Fix pyhttpd/env.py to look for
the venv at the same level (pyhttpd/.venv/) instead of the parent dir.
Jim Jagielski [Wed, 3 Jun 2026 21:25:44 +0000 (21:25 +0000)]
test/pytest_suite: fix more tests broken by httpx auto-decompression
httpx transparently inflates gzip/deflate response bodies (it keeps the
Content-Encoding header but .content/.text are the decoded plaintext). Three
more tests asserted on the body of a compressed response and so were wrong:
- pr43939 / pr17629: re-POSTed r.content (decoded plaintext, not the gzip
stream) through the inflate input filter -- same round-trip bug as
pr49328/deflate.
- reflector: 'assert r.text != payload' could never hold, since httpx
decoded the gzip body straight back to the payload.
Generalise the GET_RAW helper into a raw_response(method, path, ...) that
streams the response, reads iter_raw() (undecoded bytes), and stashes them on
.raw_content while leaving .status_code/.headers intact -- so tests can assert
on both the raw body and the headers. GET_RAW now delegates to it; update the
three tests to use raw_response/.raw_content.
The length-based tests (rwrite, passbrigade, getfile, byterange7) are
unaffected: they measure len(.content) after decoding, which equals the
original length regardless of transfer compression.
Jim Jagielski [Wed, 3 Jun 2026 21:14:57 +0000 (21:14 +0000)]
test/pytest_suite: fix deflate round-trip tests to use raw gzip bytes
httpx auto-decompresses gzip responses, so .content returned the decoded
plaintext rather than the gzip stream. Re-POSTing that plaintext with
Content-Encoding: gzip made mod_deflate's inflate input filter fail,
breaking the round-trip assertions in test_pr49328 and test_deflate.
Add a GET_RAW client helper that streams the response and reads iter_raw(),
returning the body undecoded (the analog of LWP not auto-decoding), and use
it in both tests so they exercise a genuine gzip -> inflate round-trip.
Jim Jagielski [Wed, 3 Jun 2026 20:27:40 +0000 (20:27 +0000)]
pyhttpd: fix built-in module loading, add venv support
* detect statically compiled modules via `httpd -l` and skip
LoadModule for them, fixing startup failure when log_config_module
(or others) are built into the httpd binary
* add pyproject.toml with all required Python dependencies
(cryptography, python-multipart, websockets, pyopenssl, etc.)
* add runtests-pyhttpd.sh that creates/reuses a .venv via uv or
plain python3+pip, mirroring pytest_suite/runtests.sh
* prepend .venv/bin to PATH when launching httpd so CGI scripts
forked by httpd also use the venv's Python and find all packages
* update run-all-tests.sh to delegate pyhttpd runs to the new script
Jim Jagielski [Wed, 3 Jun 2026 19:05:31 +0000 (19:05 +0000)]
test/pytest_suite: auto-create .venv via python3+pip when uv is unavailable
runtests.sh already bootstrapped the virtualenv with `uv sync` when uv
was present, but exited with an error when it was not. Fall back to
`python3 -m venv .venv && .venv/bin/pip install -e .` so the suite is
self-bootstrapping on systems that have only a stock Python 3 install.
Bring the pytest suite to parity with the canonical source:
* Add 25 previously-missing test fixture files (deflate images, expires
placeholders, data PNG, rewrite dbm, ssl .pfa placeholders, .empty
dir-keepers, headers htaccess) that several module tests require; their
absence caused spurious 404 failures.
* Set svn:executable on the CGI/shell/perl scripts (and the negotiation
and xbithack content files that carry the bit upstream) so CGI tests no
longer fail with 500 on a fresh checkout.
* Stop tracking the .htaccess/htpasswd files that the tests rewrite at run
time (setenvif/htaccess/.htaccess, autoindex2/dir_broken/.htaccess,
autoindex2/dir_protected/htpasswd) and add svn:ignore for them, matching
the original Perl Apache::Test framework which never versioned them.
* Add per-directory svn:ignore for c-module build artifacts, generated
t/conf configs, generated CGI scripts and runtime dirs, plus a recursive
svn:global-ignores for Python caches (__pycache__, *.pyc, .venv, etc.).
Jim Jagielski [Wed, 3 Jun 2026 17:28:47 +0000 (17:28 +0000)]
pytest_suite: add missing modules/access/htaccess/ directory and index.html
test_access.py (mod_access_compat Order/Allow/Deny tests) writes
.htaccess at runtime for each permutation and then GETs index.html to
verify access is granted or denied. The directory and its empty
index.html must pre-exist; .htaccess itself is written by the test.
Jim Jagielski [Wed, 3 Jun 2026 17:24:44 +0000 (17:24 +0000)]
pytest_suite: fix hardcoded absolute paths in .htaccess files
Both files were committed with /Users/jjagielski/... paths that only
work on one developer's machine.
autoindex2/dir_protected/.htaccess: AuthUserFile now uses a path
relative to ServerRoot (Apache 2.4+ resolves these against the
configured ServerRoot, which the test framework sets to pytest_suite/t/).
setenvif/htaccess/.htaccess: file() argument in SetEnvIfExpr now uses
%{DOCUMENT_ROOT} instead of a hardcoded absolute path.
Jim Jagielski [Wed, 3 Jun 2026 17:21:22 +0000 (17:21 +0000)]
pytest_suite: fix startup failures and add missing Perl helper templates
Three bugs fixed in the pytest framework:
1. cmodules.py: compiled C test modules were not rebuilt when apxs changed
(e.g. upgrading from Apache 2.4 to 2.5). The staleness check now also
compares the .so mtime against apxs itself, so a newer apxs always
triggers a rebuild and prevents API-signature mismatches (AP24 vs AP25).
Add clean_modules() to remove all apxs build artifacts (make clean
equivalent), exposed as --clean-modules pytest option and routed only
to pytest_suite (not pyhttpd) in run-all-tests.sh.
2. server.py: httpd was started without -DFOREGROUND, so the MPM parent
forked and exited (code 0) before the port opened. The framework
misread the fork-exit as a crash and killed the running daemon.
Add -DFOREGROUND so the Popen process IS the httpd parent.
3. Missing Perl helper scripts: t/conf/extra.conf.in declares a prg-type
RewriteMap (numbers-prg) whose program file did not exist, causing
httpd to refuse to start. More broadly, all *.pl CGI scripts,
ext_filter programs, rewrite-map programs, and the SSL passphrase
helper referenced by the config and tests were absent.
Add the full set of *.pl.PL source templates (copied from the
httpd-tests framework), covering:
- t/conf/ssl/httpd-passphrase.pl.PL
- t/htdocs/apache/http_strict/send_hdr.pl.PL (new dir)
- t/htdocs/modules/cgi/ (28 CGI scripts)
- t/htdocs/modules/ext_filter/ (2 filter programs, new dir)
- t/htdocs/modules/negotiation/query/test.pl.PL
- t/htdocs/modules/rewrite/ (numbers, numbers2, db)
generate_pl_scripts() regenerates the .pl executables from these
templates at each test-session start with the correct local perl shebang.
Joe Orton [Wed, 3 Jun 2026 10:40:17 +0000 (10:40 +0000)]
CI: Update used actions to use newer Node.js than 20
CI: Update upload-artifact action, drop unnecessary Ubuntu 22.04 fix
CI: Drop 'shell: cmd', use PowerShell for the Windows workflow
CI: Print used CMake version for Windows workflow
Submitted by: Vladimír Chlup <vchlup ibm.com>
Github: closes #660
Jim Jagielski [Tue, 2 Jun 2026 15:50:29 +0000 (15:50 +0000)]
test/h2: ignore AH02430 for the whole TestRfc9113 class
test_h2_203_02 intentionally triggers AH02430 (illegal response header
char). Over HTTP/2 the error is logged late during stream teardown and
can produce several lines, so the per-case ignore_recent() raced them
and they leaked into a later test's check_error_log(). Move the ignore
to an autouse class fixture (as conftest.py does for AH10400/AH00045)
and add HttpdErrorLog.remove_ignored_lognos() to restore on teardown.
Rich Bowen [Tue, 2 Jun 2026 12:56:14 +0000 (12:56 +0000)]
Fix RedirectMatch regex in ACME exemption recipe (bug 70084)
The negative lookahead (?!...) is zero-width and non-capturing, so
the original pattern matched only the leading slash and \$1 was
undefined. Add a capturing group (.*)$ after the lookahead so that
\$1 contains the remainder of the URL-path.