diff --git a/lib/urlapi.c b/lib/urlapi.c index e49291f41b..e9262b42fc 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -718,8 +718,12 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp) struct dynbuf out; CURLcode result = CURLE_OK; + /* variables for leading dot checks */ + const char *dinput = input; + size_t dlen = clen; + *outp = NULL; - /* the path always starts with a slash, and a slash has not dot */ + /* a single byte path cannot be cleaned up */ if(clen < 2) return 0; @@ -727,9 +731,9 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp) /* A. If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, */ - if(is_dot(&input, &clen)) { - const char *p = input; - size_t blen = clen; + if(is_dot(&dinput, &dlen)) { + const char *p = dinput; + size_t blen = dlen; if(!clen) /* . [end] */ @@ -737,7 +741,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp) else if(ISSLASH(*p)) { /* one dot followed by a slash */ input = p + 1; - clen--; + clen = dlen - 1; } /* D. if the input buffer consists only of "." or "..", then remove diff --git a/tests/unit/unit1395.c b/tests/unit/unit1395.c index 7ca7f22c10..b80f9927d6 100644 --- a/tests/unit/unit1395.c +++ b/tests/unit/unit1395.c @@ -37,6 +37,21 @@ static CURLcode test_unit1395(const char *arg) }; const struct dotdot pairs[] = { + { "/%2f%2e%2e%2f/../a", "/a" }, + { "/%2f%2e%2e%2f/../", "/" }, + { "/%2f%2e%2e%2f/.", "/%2f%2e%2e%2f/" }, + { "/%2f%2e%2e%2f/", "/%2f%2e%2e%2f/" }, + { "/%2f%2e%2e%2f", "/%2f%2e%2e%2f" }, + { "/%2f%2e%2e%2", "/%2f%2e%2e%2" }, + { "/%2f%2e%2e%", "/%2f%2e%2e%" }, + { "/%2f%2e%2e", "/%2f%2e%2e" }, + { "/%2f%2e%2", "/%2f%2e%2" }, + { "/%2f%2e%", "/%2f%2e%" }, + { "/%2f%2e", "/%2f%2e" }, + { "/%2f%2", "/%2f%2" }, + { "/%2f%", "/%2f%" }, + { "/%2f", "/%2f" }, + { "/%2", "/%2" }, { "%2f%2e%2e%2f/../a", "%2f%2e%2e%2f/a" }, { "%2f%2e%2e%2f/../", "%2f%2e%2e%2f/" }, { "%2f%2e%2e%2f/.", "%2f%2e%2e%2f/" }, @@ -108,6 +123,26 @@ static CURLcode test_unit1395(const char *arg) { "/moo/..", "/" }, { "/..", "/" }, { "/.", "/" }, + { "////../a", "///a" }, + { "/../../../../../../", "/" }, + { "/..//..//", "//" }, + { "/.config/../ssh", "/ssh" }, + { "/..config/..", "/" }, + { "/.../a", "/.../a" }, + { "/a/%2E%2e/b", "/b" }, + { "/a/%2e./b", "/b" }, + { "/a/.%2e/b", "/b" }, + { "/%2f..%2f", "/%2f..%2f" }, + { "/a/b/.", "/a/b/" }, + { "/a/b/..", "/a/" }, + { "well-known", "well-known" }, + { ".well-known", ".well-known" }, + { "..well-known", "..well-known" }, + { "...well-known", "...well-known" }, + { "....well-known", "....well-known" }, + { "%2ewell-known", "%2ewell-known" }, + { "%2Ewell-known", "%2Ewell-known" }, + { "../.well-known", ".well-known" }, }; for(i = 0; i < CURL_ARRAYSIZE(pairs); i++) {