urlapi: avoid dedotdotify() if possible
No binary (build failed)
—
(log yok)
| @@ -750,6 +750,29 @@ static bool is_dot(const char **str, size_t *clen) | |
| #define ISSLASH(x) ((x) == '/') | |
| + | /* prescan the string to see if it needs work */ |
| + | static bool needs_dedotdot(const char *p, size_t pn) |
| + | { |
| + | /* a single byte path cannot be cleaned up */ |
| + | if(pn < 2) |
| + | return FALSE; |
| + | while(pn) { |
| + | if(is_dot(&p, &pn)) { |
| + | /* "./" or dot before end of string */ |
| + | if(!pn || ISSLASH(*p)) |
| + | return TRUE; |
| + | /* "../" or ".." before end of string */ |
| + | else if(is_dot(&p, &pn) && (!pn || ISSLASH(*p))) |
| + | return TRUE; |
| + | } |
| + | else { |
| + | p++; |
| + | pn--; |
| + | } |
| + | } |
| + | return FALSE; |
| + | } |
| + | |
| /* | |
| * dedotdotify() | |
| * | |
| @@ -761,7 +784,8 @@ static bool is_dot(const char **str, size_t *clen) | |
| * | |
| * RETURNS | |
| * | |
| - | * Zero for success and 'out' set to an allocated dedotdotified string. |
| + | * Zero for success and 'out' set to an allocated string (or NULL if there's |
| + | * nothing to do). |
| * | |
| * @unittest 1395 | |
| */ | |
| @@ -776,8 +800,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp) | |
| size_t dlen = clen; | |
| *outp = NULL; | |
| - | /* a single byte path cannot be cleaned up */ |
| - | if(clen < 2) |
| + | if(!needs_dedotdot(input, clen)) |
| return 0; | |
| curlx_dyn_init(&out, clen + 1); | |
| @@ -39,33 +39,33 @@ static CURLcode test_unit1395(const char *arg) | |
| { "/%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/", NULL }, |
| + | { "/%2f%2e%2e%2f", NULL }, |
| + | { "/%2f%2e%2e%2", NULL }, |
| + | { "/%2f%2e%2e%", NULL }, |
| { "/%2f%2e%2e", "/%2f%2e%2e" }, | |
| - | { "/%2f%2e%2", "/%2f%2e%2" }, |
| - | { "/%2f%2e%", "/%2f%2e%" }, |
| + | { "/%2f%2e%2", NULL }, |
| + | { "/%2f%2e%", NULL }, |
| { "/%2f%2e", "/%2f%2e" }, | |
| - | { "/%2f%2", "/%2f%2" }, |
| - | { "/%2f%", "/%2f%" }, |
| - | { "/%2f", "/%2f" }, |
| - | { "/%2", "/%2" }, |
| + | { "/%2f%2", NULL }, |
| + | { "/%2f%", NULL }, |
| + | { "/%2f", NULL }, |
| + | { "/%2", NULL }, |
| { "%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/" }, | |
| - | { "%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/", NULL }, |
| + | { "%2f%2e%2e%2f", NULL }, |
| + | { "%2f%2e%2e%2", NULL }, |
| + | { "%2f%2e%2e%", NULL }, |
| { "%2f%2e%2e", "%2f%2e%2e" }, | |
| - | { "%2f%2e%2", "%2f%2e%2" }, |
| - | { "%2f%2e%", "%2f%2e%" }, |
| + | { "%2f%2e%2", NULL }, |
| + | { "%2f%2e%", NULL }, |
| { "%2f%2e", "%2f%2e" }, | |
| - | { "%2f%2", "%2f%2" }, |
| - | { "%2f%", "%2f%" }, |
| - | { "%2f", "%2f" }, |
| - | { "%2", "%2" }, |
| + | { "%2f%2", NULL }, |
| + | { "%2f%", NULL }, |
| + | { "%2f", NULL }, |
| + | { "%2", NULL }, |
| { "%", NULL }, | |
| { "2", NULL }, | |
| { "e", NULL }, | |
| @@ -108,12 +108,12 @@ static CURLcode test_unit1395(const char *arg) | |
| { "/1/./%2e.", "/" }, | |
| { "/1/./../2", "/2" }, | |
| { "/hello/1/./../2", "/hello/2" }, | |
| - | { "test/this", "test/this" }, |
| + | { "test/this", NULL }, |
| { "test/this/../now", "test/now" }, | |
| { "/1../moo../foo", "/1../moo../foo" }, | |
| { "/../../moo", "/moo" }, | |
| { "/../../moo?", "/moo?" }, | |
| - | { "/123?", "/123?" }, |
| + | { "/123?", NULL }, |
| { "/", NULL }, | |
| { "", NULL }, | |
| { "/.../", "/.../" }, | |
| @@ -131,16 +131,16 @@ static CURLcode test_unit1395(const char *arg) | |
| { "/a/%2E%2e/b", "/b" }, | |
| { "/a/%2e./b", "/b" }, | |
| { "/a/.%2e/b", "/b" }, | |
| - | { "/%2f..%2f", "/%2f..%2f" }, |
| + | { "/%2f..%2f", NULL }, |
| { "/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", NULL }, |
| + | { ".well-known", NULL }, |
| + | { "..well-known", NULL }, |
| + | { "...well-known", NULL }, |
| + | { "....well-known", NULL }, |
| + | { "%2ewell-known", NULL }, |
| + | { "%2Ewell-known", NULL }, |
| { "../.well-known", ".well-known" }, | |
| }; | |