Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changes-entries/speling-uri-underflow.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*) mod_speling: Avoid an out-of-bounds read in the URL/filename check when a
mapped file's base name is longer than the request URI.
[arshiya tabasum <arshi bugqore.com>]
11 changes: 11 additions & 0 deletions modules/mappers/mod_speling.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ static int check_speling(request_rec *r)
urlen = strlen(r->uri);
pglen = strlen(postgood);

/*
* postgood is meant to be a trailing substring of r->uri. When a mapper
* (e.g. Alias or a RewriteRule) points a short URI at a file whose base
* name is longer, postgood is longer than r->uri and urlen - pglen goes
* negative; r->uri + (urlen - pglen) would then read before the start of
* the buffer. Bail out first so the suffix compare stays in bounds.
*/
if (pglen > urlen) {
return DECLINED;
}

/* Check to see if the URL pieces add up */
if (strcmp(postgood, r->uri + (urlen - pglen))) {
return DECLINED;
Expand Down
4 changes: 4 additions & 0 deletions test/pytest_suite/t/conf/extra.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,10 @@ LimitRequestFields 32
CheckSpelling on
CheckCaseOnly on
</Directory>
# Point a short URI at a longer, nonexistent base name in a CheckSpelling
# directory. This exercised the r->uri + (urlen - pglen) underflow in
# check_speling(); the server must answer cleanly rather than read OOB.
Alias /sp-oob @SERVERROOT@/htdocs/modules/speling/nocase/nonexistent-long-name.html
</IfModule>

<IfModule mod_actions.c>
Expand Down
14 changes: 14 additions & 0 deletions test/pytest_suite/tests/t/modules/test_speling.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,17 @@ def test_speling(http, prefix, code_idx, case):
# Only redirect responses carry a corrected-filename body.
if expected not in (200, 404):
assert t_cmp(r.text, _REDIRECT_BODY), "Redirect ok"


@need_module("mod_speling")
def test_speling_short_uri_alias(http):
"""Regression for the check_speling() out-of-bounds read.

``Alias /sp-oob`` maps a short URI to a longer, nonexistent base name in
a CheckSpelling directory. postgood (the base name) is then longer than
r->uri, so r->uri + (urlen - pglen) underflowed and strcmp read before
the start of the buffer. The server must answer cleanly (404) instead of
crashing or reading out of bounds.
"""
r = http.GET("/sp-oob")
assert t_cmp(r.status_code, 404), "short-URI alias must not read OOB"