From 3ec67c97dfa3037889e56b478b923838dc714d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Mon, 22 Oct 2018 14:12:12 +0200 Subject: [PATCH] combine_path: Fixed corner case. combine_path() on strings starting with "./../" used to gain one directory level. Eg: Old behavior: > combine_path(".", "../foo"); (1) Result: "../foo" > combine_path("./..", "foo"); (2) Result: "foo" > combine_path("./../foo"); (3) Result: "foo" New (fixed) behavior: > combine_path(".", "../foo"); (1) Result: "../foo" > combine_path("./..", "foo"); (2) Result: "../foo" > combine_path("./../foo"); (3) Result: "../foo" Fixes [PIKE-137]. --- src/combine_path.h | 42 ++++++++++++++++++++++++++++++++++-------- src/testsuite.in | 3 +++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/combine_path.h b/src/combine_path.h index 988f55eca4..909dfef27a 100644 --- a/src/combine_path.h +++ b/src/combine_path.h @@ -210,16 +210,42 @@ static void APPEND_PATH(struct string_builder *s, } else if (IS_SEP(index_shared_string(s->s, 0))) { tmp++; } - + if (tmp < abs) tmp = abs; - else - if ((tmp+1 < s->s->len) && - (index_shared_string(s->s,tmp)=='.') && - (index_shared_string(s->s,tmp+1)=='.') && - ( (tmp+2 == s->s->len) || - IS_SEP(index_shared_string(s->s,tmp+2)))) - break; + else { + if (index_shared_string(s->s,tmp)=='.') { + if ((tmp+1 < s->s->len) && + (index_shared_string(s->s,tmp+1)=='.') && + ( (tmp+2 == s->s->len) || + IS_SEP(index_shared_string(s->s,tmp+2)))) { + break; + } else if ((tmp+1 == s->s->len) || + IS_SEP(index_shared_string(s->s,tmp+1))) { + /* Previous is "." or "./". + * Replace it with "..". + */ + if (tmp+1 != s->s->len) { + /* Remove the separator. */ + s->s->len--; + } + PUSH('.'); + from += 2; + if (c3) { + PUSH('/'); + from++; + } +#if COMBINE_PATH_DEBUG > 0 + /* s->s->str[s->s->len]=0; */ + fprintf(stderr,"combine_path(2), TO: %s[%d]\n", + s->s->str, s->s->len); + fprintf(stderr,"combine_path(2), FROM (%d): %s[%d]\n", + from, path.ptr+from, len-from); +#endif + continue; + } + } + } from+=(c3? 3:2); s->s->len=tmp; diff --git a/src/testsuite.in b/src/testsuite.in index 91cacc8849..8e87b0e01f 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -10750,6 +10750,9 @@ test_eq([[combine_path(".", "bar")]],"bar") test_eq([[combine_path("./", "bar")]],"bar") test_eq([[combine_path(".", "../bar")]],"../bar") test_eq([[combine_path("./", "../bar")]],"../bar") +test_eq([[combine_path("./bar")]],"bar") +test_eq([[combine_path("./bar")]],"bar") +test_eq([[combine_path("./../bar")]],"../bar") // - combine_path_nt test_eq([[combine_path_nt("/","/fo\1111/bar/gazonk/../../")]],"/fo\1111/") -- GitLab