From 53f4fbb1b4f185da8b57a9f0ab521106a1cd4bdc Mon Sep 17 00:00:00 2001 From: Koda Reef Date: Sun, 22 Mar 2026 22:07:34 +0000 Subject: [PATCH 1/2] Add integer overflow checks to URL escape allocation functions ap_escape_path_segment, ap_os_escape_path, and ap_escape_urlencoded allocate output buffers using 3 * strlen(input) + constant without checking for overflow. On platforms where size_t is 32-bit, large inputs cause the multiplication to wrap, resulting in undersized allocation. The HTML escape function ap_escape_html2 in the same file already has overflow protection (abort on overflow). Apply the same pattern to the three URL escape functions for consistency. --- server/util.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/server/util.c b/server/util.c index bca2636fd2b..97abdd7c278 100644 --- a/server/util.c +++ b/server/util.c @@ -2073,7 +2073,11 @@ AP_DECLARE(char *) ap_escape_path_segment_buffer(char *copy, const char *segment AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment) { - return ap_escape_path_segment_buffer(apr_palloc(p, 3 * strlen(segment) + 1), segment); + apr_size_t len = strlen(segment); + if (len > (APR_SIZE_MAX - 1) / 3) { + abort(); + } + return ap_escape_path_segment_buffer(apr_palloc(p, 3 * len + 1), segment); } AP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partial) @@ -2082,11 +2086,19 @@ AP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partia * Allocate another +1 to allow the caller to add a trailing '/' (see * comment in 'ap_sub_req_lookup_dirent') */ - char *copy = apr_palloc(p, 3 * strlen(path) + 3 + 1); - const unsigned char *s = (const unsigned char *)path; - unsigned char *d = (unsigned char *)copy; + apr_size_t len = strlen(path); + char *copy; + const unsigned char *s; + unsigned char *d; unsigned c; + if (len > (APR_SIZE_MAX - 4) / 3) { + abort(); + } + copy = apr_palloc(p, 3 * len + 3 + 1); + s = (const unsigned char *)path; + d = (unsigned char *)copy; + if (!partial) { const char *colon = ap_strchr_c(path, ':'); const char *slash = ap_strchr_c(path, '/'); @@ -2133,7 +2145,11 @@ AP_DECLARE(char *) ap_escape_urlencoded_buffer(char *copy, const char *buffer) AP_DECLARE(char *) ap_escape_urlencoded(apr_pool_t *p, const char *buffer) { - return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * strlen(buffer) + 1), buffer); + apr_size_t len = strlen(buffer); + if (len > (APR_SIZE_MAX - 1) / 3) { + abort(); + } + return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * len + 1), buffer); } /* ap_escape_uri is now a macro for os_escape_path */ From 7076612eb185e60cf9b5513a3a57ad70deb101dd Mon Sep 17 00:00:00 2001 From: Koda Reef Date: Mon, 23 Mar 2026 12:36:59 +0000 Subject: [PATCH 2/2] Add integer overflow check to ap_escape_shell_cmd() ap_escape_shell_cmd at line 1820 computes 2 * strlen(str) + 1 without checking for overflow. Same pattern as the URL escape functions fixed in the previous commit. Add (APR_SIZE_MAX - 1) / 2 guard, consistent with ap_escape_html2's overflow protection. --- server/util.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/util.c b/server/util.c index 97abdd7c278..b09568838fb 100644 --- a/server/util.c +++ b/server/util.c @@ -1816,8 +1816,12 @@ AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str) char *cmd; unsigned char *d; const unsigned char *s; + apr_size_t len = strlen(str); - cmd = apr_palloc(p, 2 * strlen(str) + 1); /* Be safe */ + if (len > (APR_SIZE_MAX - 1) / 2) { + abort(); + } + cmd = apr_palloc(p, 2 * len + 1); d = (unsigned char *)cmd; s = (const unsigned char *)str; for (; *s; ++s) {