From 54cc53eb4b6a5407d3c96337ecb40fd14e2c8371 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sat, 17 Oct 2026 11:18:52 +0000 Subject: [PATCH] mod_autoindex: fix one-byte over-read past end of description Stop reading (and writing) one byte past the end of a file description when it ends inside an unterminated "&" entity or "<" tag, as a ScanHTMLTitles title can. * modules/generators/mod_autoindex.c (terminate_description): Check for the terminating NUL before advancing past it when scanning an unterminated "<" tag or "&" entity, and break out of the loop at end of string rather than continuing past it. * test/modules/generators/env.py (GeneratorsTestSetup.__init__): Load mod_autoindex for the generators test suite. * test/modules/generators/htdocs/autoindex/: New test content. * test/modules/generators/test_002_autoindex.py (TestAutoindex): New test that a ScanHTMLTitles description ending in a bare "&" is rendered without reading past the end of the description. Submitted by: arshiya tabasum GitHub: closes #812 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1939181 13f79535-47bb-0310-9956-ffa450edef68 --- ...autoindex-terminate-description-bounds.txt | 3 ++ modules/generators/mod_autoindex.c | 19 +++++------ test/modules/generators/env.py | 2 +- .../generators/htdocs/autoindex/index.html | 1 + .../htdocs/autoindex/listing/att.html | 1 + test/modules/generators/test_002_autoindex.py | 34 +++++++++++++++++++ 6 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 changes-entries/autoindex-terminate-description-bounds.txt create mode 100644 test/modules/generators/htdocs/autoindex/index.html create mode 100644 test/modules/generators/htdocs/autoindex/listing/att.html create mode 100644 test/modules/generators/test_002_autoindex.py diff --git a/changes-entries/autoindex-terminate-description-bounds.txt b/changes-entries/autoindex-terminate-description-bounds.txt new file mode 100644 index 0000000000..820ca384f3 --- /dev/null +++ b/changes-entries/autoindex-terminate-description-bounds.txt @@ -0,0 +1,3 @@ + *) mod_autoindex: Stop reading (and writing) one byte past the end of a + file description when it ends inside an unterminated "&" entity or "<" + tag, as a ScanHTMLTitles title can. [arshiya tabasum] diff --git a/modules/generators/mod_autoindex.c b/modules/generators/mod_autoindex.c index 602b2e51ce..37bed118b0 100644 --- a/modules/generators/mod_autoindex.c +++ b/modules/generators/mod_autoindex.c @@ -1452,22 +1452,21 @@ static char *terminate_description(autoindex_config_rec *d, char *desc, } for (x = 0; desc[x] && ((maxsize > 0) || (desc[x] == '<')); x++) { if (desc[x] == '<') { - while (desc[x] != '>') { - if (!desc[x]) { - maxsize = 0; - break; - } + while (desc[x] && desc[x] != '>') { ++x; } + if (!desc[x]) { + break; + } } else if (desc[x] == '&') { /* entities like ä count as one character */ --maxsize; - for ( ; desc[x] != ';'; ++x) { - if (desc[x] == '\0') { - maxsize = 0; - break; - } + for ( ; desc[x] && desc[x] != ';'; ++x) { + ; + } + if (!desc[x]) { + break; } } else { diff --git a/test/modules/generators/env.py b/test/modules/generators/env.py index 3fa111716c..69f4793732 100644 --- a/test/modules/generators/env.py +++ b/test/modules/generators/env.py @@ -13,7 +13,7 @@ class GeneratorsTestSetup(HttpdTestSetup): def __init__(self, env: 'HttpdTestEnv'): super().__init__(env=env) self.add_source_dir(os.path.dirname(inspect.getfile(GeneratorsTestSetup))) - self.add_modules(["cgid", "include", "headers"]) + self.add_modules(["cgid", "include", "headers", "autoindex"]) class GeneratorsTestEnv(HttpdTestEnv): diff --git a/test/modules/generators/htdocs/autoindex/index.html b/test/modules/generators/htdocs/autoindex/index.html new file mode 100644 index 0000000000..f16b89d986 --- /dev/null +++ b/test/modules/generators/htdocs/autoindex/index.html @@ -0,0 +1 @@ +autoindex testsautoindex tests diff --git a/test/modules/generators/htdocs/autoindex/listing/att.html b/test/modules/generators/htdocs/autoindex/listing/att.html new file mode 100644 index 0000000000..2334b3a4bd --- /dev/null +++ b/test/modules/generators/htdocs/autoindex/listing/att.html @@ -0,0 +1 @@ +AT&Tpage diff --git a/test/modules/generators/test_002_autoindex.py b/test/modules/generators/test_002_autoindex.py new file mode 100644 index 0000000000..14d05bdc3f --- /dev/null +++ b/test/modules/generators/test_002_autoindex.py @@ -0,0 +1,34 @@ +import textwrap + +import pytest + +from pyhttpd.conf import HttpdConf + + +class TestAutoindex: + + @pytest.fixture(autouse=True, scope='class') + def _class_scope(self, env): + domain = f"autoindex.{env.http_tld}" + conf = HttpdConf(env, extras={ + 'base': textwrap.dedent(f""" + LogLevel autoindex:trace1 + + Options +Indexes + IndexOptions FancyIndexing ScanHTMLTitles + + """), + }) + conf.add_vhost(domains=[domain], port=env.http_port, + doc_root="htdocs/autoindex") + conf.install() + assert env.apache_restart() == 0 + + def test_generators_002_01_scan_title_bare_amp(self, env): + """A ScanHTMLTitles description ending in a bare '&' (no ';'), as in + an "AT&T" , must be rendered without reading past the end of + the description. Before the fix this walked one byte past the + terminating NUL, which ASAN flags as a heap over-read.""" + r = env.curl_get(env.mkurl("http", "autoindex", "/listing/")) + assert r.response["status"] == 200 + assert "AT&T" in r.response["body"].decode()