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:
@@ -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]
|
||||
@@ -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 {
|
||||
|
||||
@@ -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):
|
||||
|
||||
1
test/modules/generators/htdocs/autoindex/index.html
Normal file
1
test/modules/generators/htdocs/autoindex/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><head><title>autoindex tests</title></head><body>autoindex tests</body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><title>AT&T</title></head><body>page</body></html>
|
||||
34
test/modules/generators/test_002_autoindex.py
Normal file
34
test/modules/generators/test_002_autoindex.py
Normal 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()
|
||||
Reference in New Issue
Block a user