Skip to content

Commit 53f4fbb

Browse files
committed
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.
1 parent 3b3af44 commit 53f4fbb

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

server/util.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,7 +2073,11 @@ AP_DECLARE(char *) ap_escape_path_segment_buffer(char *copy, const char *segment
20732073

20742074
AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
20752075
{
2076-
return ap_escape_path_segment_buffer(apr_palloc(p, 3 * strlen(segment) + 1), segment);
2076+
apr_size_t len = strlen(segment);
2077+
if (len > (APR_SIZE_MAX - 1) / 3) {
2078+
abort();
2079+
}
2080+
return ap_escape_path_segment_buffer(apr_palloc(p, 3 * len + 1), segment);
20772081
}
20782082

20792083
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
20822086
* Allocate another +1 to allow the caller to add a trailing '/' (see
20832087
* comment in 'ap_sub_req_lookup_dirent')
20842088
*/
2085-
char *copy = apr_palloc(p, 3 * strlen(path) + 3 + 1);
2086-
const unsigned char *s = (const unsigned char *)path;
2087-
unsigned char *d = (unsigned char *)copy;
2089+
apr_size_t len = strlen(path);
2090+
char *copy;
2091+
const unsigned char *s;
2092+
unsigned char *d;
20882093
unsigned c;
20892094

2095+
if (len > (APR_SIZE_MAX - 4) / 3) {
2096+
abort();
2097+
}
2098+
copy = apr_palloc(p, 3 * len + 3 + 1);
2099+
s = (const unsigned char *)path;
2100+
d = (unsigned char *)copy;
2101+
20902102
if (!partial) {
20912103
const char *colon = ap_strchr_c(path, ':');
20922104
const char *slash = ap_strchr_c(path, '/');
@@ -2133,7 +2145,11 @@ AP_DECLARE(char *) ap_escape_urlencoded_buffer(char *copy, const char *buffer)
21332145

21342146
AP_DECLARE(char *) ap_escape_urlencoded(apr_pool_t *p, const char *buffer)
21352147
{
2136-
return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * strlen(buffer) + 1), buffer);
2148+
apr_size_t len = strlen(buffer);
2149+
if (len > (APR_SIZE_MAX - 1) / 3) {
2150+
abort();
2151+
}
2152+
return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * len + 1), buffer);
21372153
}
21382154

21392155
/* ap_escape_uri is now a macro for os_escape_path */

0 commit comments

Comments
 (0)