From 961fb96bb7a0aa88bef0b71182cbbcafe3108201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=B1=D0=B1=D0=B8?= <lsm@cesanta.com> Date: Sat, 27 Jan 2018 01:35:00 +0000 Subject: [PATCH] Fix OOB access in mg_match_prefix_n() CL: Fix OOB access in mg_match_prefix_n(). Made mg_match_prefix_n() return non-negative result. PUBLISHED_FROM=611454df6a6c55bfa7ddf05e7d268a86fa0457a8 --- mongoose.c | 48 ++++++++++++++++++++++-------------------------- mongoose.h | 13 ++++++------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/mongoose.c b/mongoose.c index c9b4f0694..f80b4daf3 100644 --- a/mongoose.c +++ b/mongoose.c @@ -612,8 +612,8 @@ int cs_log_print_prefix(enum cs_log_level level, const char *func, if (level > cs_log_threshold) return 0; if (s_filter_pattern != NULL && - mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) < 0 && - mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) < 0) { + mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 && + mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) { return 0; } @@ -1632,9 +1632,9 @@ const char *mg_strstr(const struct mg_str haystack, #ifndef EXCLUDE_COMMON +/* Amalgamated: #include "common/str_util.h" */ /* Amalgamated: #include "common/mg_mem.h" */ /* Amalgamated: #include "common/platform.h" */ -/* Amalgamated: #include "common/str_util.h" */ #ifndef C_DISABLE_BUILTIN_SNPRINTF #define C_DISABLE_BUILTIN_SNPRINTF 0 @@ -2090,11 +2090,10 @@ struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val, return list; } -int mg_match_prefix_n(const struct mg_str, const struct mg_str) WEAK; -int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) { +size_t mg_match_prefix_n(const struct mg_str, const struct mg_str) WEAK; +size_t mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) { const char *or_str; - size_t len, i = 0, j = 0; - int res; + size_t res = 0, len = 0, i = 0, j = 0; if ((or_str = (const char *) memchr(pattern.p, '|', pattern.len)) != NULL || (or_str = (const char *) memchr(pattern.p, ',', pattern.len)) != NULL) { @@ -2106,11 +2105,9 @@ int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) { return mg_match_prefix_n(pstr, str); } - for (; i < pattern.len; i++, j++) { - if (pattern.p[i] == '?' && j != str.len) { + for (; i < pattern.len && j < str.len; i++, j++) { + if (pattern.p[i] == '?') { continue; - } else if (pattern.p[i] == '$') { - return j == str.len ? (int) j : -1; } else if (pattern.p[i] == '*') { i++; if (i < pattern.len && pattern.p[i] == '*') { @@ -2118,29 +2115,29 @@ int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) { len = str.len - j; } else { len = 0; - while (j + len != str.len && str.p[j + len] != '/') { - len++; - } + while (j + len < str.len && str.p[j + len] != '/') len++; } - if (i == pattern.len) { + if (i == pattern.len || (pattern.p[i] == '$' && i == pattern.len - 1)) return j + len; - } do { const struct mg_str pstr = {pattern.p + i, pattern.len - i}; const struct mg_str sstr = {str.p + j + len, str.len - j - len}; res = mg_match_prefix_n(pstr, sstr); - } while (res == -1 && len-- > 0); - return res == -1 ? -1 : (int) (j + res + len); + } while (res == 0 && len != 0 && len-- > 0); + return res == 0 ? 0 : j + res + len; } else if (str_util_lowercase(&pattern.p[i]) != str_util_lowercase(&str.p[j])) { - return -1; + break; } } - return j; + if (i < pattern.len && pattern.p[i] == '$') { + return j == str.len ? str.len : 0; + } + return i == pattern.len ? j : 0; } -int mg_match_prefix(const char *, int, const char *) WEAK; -int mg_match_prefix(const char *pattern, int pattern_len, const char *str) { +size_t mg_match_prefix(const char *, int, const char *) WEAK; +size_t mg_match_prefix(const char *pattern, int pattern_len, const char *str) { const struct mg_str pstr = {pattern, (size_t) pattern_len}; struct mg_str s = {str, 0}; if (str != NULL) s.len = strlen(str); @@ -6234,7 +6231,7 @@ struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc, ep = pd->endpoints; while (ep != NULL) { - if ((matched = mg_match_prefix_n(ep->uri_pattern, *uri_path)) != -1) { + if ((matched = mg_match_prefix_n(ep->uri_pattern, *uri_path)) > 0) { if (matched > matched_max) { /* Looking for the longest suitable handler */ ret = ep; @@ -7291,8 +7288,7 @@ static int mg_is_file_hidden(const char *path, } return (exclude_specials && (!strcmp(path, ".") || !strcmp(path, ".."))) || - (p1 != NULL && - mg_match_prefix(p1, strlen(p1), path) == (int) strlen(p1)) || + (p1 != NULL && mg_match_prefix(p1, strlen(p1), path) == strlen(p1)) || (p2 != NULL && mg_match_prefix(p2, strlen(p2), path) > 0); } @@ -7842,7 +7838,7 @@ MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm, } } else { /* Regular rewrite, URI=directory */ - int match_len = mg_match_prefix_n(a, hm->uri); + size_t match_len = mg_match_prefix_n(a, hm->uri); if (match_len > 0) { file_uri_start = hm->uri.p + match_len; if (*file_uri_start == '/' || file_uri_start == cp_end) { diff --git a/mongoose.h b/mongoose.h index f8767404e..5112294f6 100644 --- a/mongoose.h +++ b/mongoose.h @@ -2076,8 +2076,8 @@ int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len); #include <stdarg.h> #include <stdlib.h> -/* Amalgamated: #include "common/platform.h" */ /* Amalgamated: #include "common/mg_str.h" */ +/* Amalgamated: #include "common/platform.h" */ #ifndef CS_ENABLE_STRDUP #define CS_ENABLE_STRDUP 0 @@ -2221,23 +2221,22 @@ struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val, * - | or , divides alternative patterns * - any other character matches itself * ``` - * Match is case-insensitive. Returns number of bytes matched, or -1 if no - * match. + * Match is case-insensitive. Return number of bytes matched. * Examples: * ``` * mg_match_prefix("a*f", len, "abcdefgh") == 6 - * mg_match_prefix("a*f", len, "abcdexgh") == -1 + * mg_match_prefix("a*f", len, "abcdexgh") == 0 * mg_match_prefix("a*f|de*,xy", len, "defgh") == 5 * mg_match_prefix("?*", len, "abc") == 3 - * mg_match_prefix("?*", len, "") == -1 + * mg_match_prefix("?*", len, "") == 0 * ``` */ -int mg_match_prefix(const char *pattern, int pattern_len, const char *str); +size_t mg_match_prefix(const char *pattern, int pattern_len, const char *str); /* * Like `mg_match_prefix()`, but takes `pattern` and `str` as `struct mg_str`. */ -int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str); +size_t mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str); #ifdef __cplusplus } -- GitLab