You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ab...@apache.org on 2026/10/14 17:07:23 UTC

svn commit: r1939121 - in httpd/httpd/trunk: changes-entries server test/modules/core

Author: abernal
Date: Wed Oct 14 17:07:23 2026
New Revision: 1939121

Log:
core: Reject invalid values of LimitXMLRequestBody.

set_limit_xml_req_body() used atol(), so "abc123" and "123abc" were
accepted as 0 and 123, and a value out of range of a long gave an
undefined result. Parse the whole argument with apr_strtoff() like
LimitRequestBody, and reject values that do not fit in limit_xml_body
or exceed AP_MAX_LIMIT_XML_BODY.

PR: 69975
GitHub: closes #825

Added:
   httpd/httpd/trunk/changes-entries/limit-xml-request-body.txt
   httpd/httpd/trunk/test/modules/core/test_010_limit_xml_request_body.py
Modified:
   httpd/httpd/trunk/server/core.c

Added: httpd/httpd/trunk/changes-entries/limit-xml-request-body.txt
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ httpd/httpd/trunk/changes-entries/limit-xml-request-body.txt	Wed Oct 14 17:07:23 2026	(r1939121)
@@ -0,0 +1,2 @@
+  *) core: Reject invalid non-numeric values of LimitXMLRequestBody, as
+     LimitRequestBody does.  PR 69975.  [Arturo Bernal]

Modified: httpd/httpd/trunk/server/core.c
==============================================================================
--- httpd/httpd/trunk/server/core.c	Wed Oct 14 15:06:16 2026	(r1939120)
+++ httpd/httpd/trunk/server/core.c	Wed Oct 14 17:07:23 2026	(r1939121)
@@ -59,6 +59,8 @@
 
 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
 
+#include <limits.h>     /* for LONG_MAX */
+
 #if defined(RLIMIT_CPU) || defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) || defined (RLIMIT_NPROC)
 #include "unixd.h"
 #endif
@@ -3914,16 +3916,29 @@ static const char *set_limit_xml_req_bod
                                           const char *arg)
 {
     core_dir_config *conf = conf_;
+    apr_uint64_t max = AP_MAX_LIMIT_XML_BODY;
+    apr_off_t limit;
+    char *errp;
 
-    conf->limit_xml_body = atol(arg);
-    if (conf->limit_xml_body < 0)
+    if (APR_SUCCESS != apr_strtoff(&limit, arg, &errp, 10)) {
+        return "LimitXMLRequestBody argument is not parsable.";
+    }
+    if (*errp || limit < 0) {
         return "LimitXMLRequestBody requires a non-negative integer.";
+    }
 
-    /* zero is AP_MAX_LIMIT_XML_BODY (implicitly) */
-    if ((apr_size_t)conf->limit_xml_body > AP_MAX_LIMIT_XML_BODY)
+    /* zero is AP_MAX_LIMIT_XML_BODY (implicitly), and limit_xml_body is
+     * a long, which is narrower than apr_size_t on some platforms.
+     */
+    if (max > LONG_MAX) {
+        max = LONG_MAX;
+    }
+    if ((apr_uint64_t)limit > max) {
         return apr_psprintf(cmd->pool, "LimitXMLRequestBody must not exceed "
-                            "%" APR_SIZE_T_FMT, AP_MAX_LIMIT_XML_BODY);
+                            "%" APR_UINT64_T_FMT, max);
+    }
 
+    conf->limit_xml_body = (long)limit;
     return NULL;
 }
 

Added: httpd/httpd/trunk/test/modules/core/test_010_limit_xml_request_body.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ httpd/httpd/trunk/test/modules/core/test_010_limit_xml_request_body.py	Wed Oct 14 17:07:23 2026	(r1939121)
@@ -0,0 +1,41 @@
+import os
+
+import pytest
+
+from pyhttpd.conf import HttpdConf
+
+
+class TestLimitXMLRequestBody:
+
+    # have httpd parse the configuration, like "httpd -t" does
+    def check_config(self, env, value):
+        conf = HttpdConf(env)
+        conf.add(f"LimitXMLRequestBody {value}")
+        conf.add_vhost_test1()
+        conf.install()
+        return env.run([os.path.join(env.bin_dir, 'httpd'),
+                        "-t", "-d", env.server_dir,
+                        "-f", os.path.join(env.server_dir, 'conf', 'httpd.conf')])
+
+    @pytest.mark.parametrize("value", ["0", "1", "123", "1000000"])
+    def test_core_010_001(self, env, value):
+        r = self.check_config(env, value)
+        assert r.exit_code == 0, f"{r.stderr}"
+
+    # only a whole non-negative decimal number is a valid limit
+    @pytest.mark.parametrize("value", [
+        "abc123", "123abc", "123foo456", "-1", "1.5", "0x10", "+", "-",
+    ])
+    def test_core_010_002(self, env, value):
+        r = self.check_config(env, value)
+        assert r.exit_code != 0, f"{value} was accepted"
+        assert "LimitXMLRequestBody requires a non-negative integer" in r.stderr
+
+    # more than can be stored or than the directive permits
+    @pytest.mark.parametrize("value", [
+        "9223372036854775807", "9223372036854775808", "9" * 40,
+    ])
+    def test_core_010_003(self, env, value):
+        r = self.check_config(env, value)
+        assert r.exit_code != 0, f"{value} was accepted"
+        assert "LimitXMLRequestBody" in r.stderr