← Commit list

eae88a7473

Daniel Stenberg
Daniel Stenberg
2026-08-12
SUCCESS Duration: 412s

Subject

urlapi: avoid dedotdotify() if possible

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/urlapi.c+26 -3
@@ -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);
tests/unit/unit1395.c+30 -30
@@ -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" },
};