1
0
mirror of https://github.com/apache/httpd.git synced 2026-10-23 22:49:01 +03:00

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 <arshi bugqore.com>
GitHub: closes #812


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1939181 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Joe Orton
2026-10-17 11:18:52 +00:00
parent 72af198632
commit 54cc53eb4b
6 changed files with 49 additions and 11 deletions

View File

@@ -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]

View File

@@ -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 &auml; 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 {

View File

@@ -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):

View File

@@ -0,0 +1 @@
<html><head><title>autoindex tests</title></head><body>autoindex tests</body></html>

View File

@@ -0,0 +1 @@
<html><head><title>AT&T</title></head><body>page</body></html>

View File

@@ -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
<Directory "{env.server_docs_dir}/autoindex/listing">
Options +Indexes
IndexOptions FancyIndexing ScanHTMLTitles
</Directory>
"""),
})
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" <title>, 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()