diff --git a/src/host/path_getrelative.c b/src/host/path_getrelative.c index 5c3d84aa..06b8a1a5 100644 --- a/src/host/path_getrelative.c +++ b/src/host/path_getrelative.c @@ -8,6 +8,36 @@ #include +static void normalize(char* buffer, const char* path) +{ + strcpy(buffer, path); + do_translate(buffer, '/'); + + /* remove any duplicate slashes within the path */ + char* src = buffer; + char* dst = buffer; + char last = '\0'; + + while (*src != '\0') { + /* if I don't have consecutive slashes, keep the char */ + if (*src != '/' || last != '/') { + *(dst++) = *src; + } + + /* Allow double-slash at the start of the string, so absolute + * UNC paths can be expressed, but nowhere else */ + if (src != buffer) { + last = (*src); + } + + /* check the next one */ + ++src; + } + + *dst = '\0'; +} + + int path_getrelative(lua_State* L) { int i, last, count; @@ -18,10 +48,8 @@ int path_getrelative(lua_State* L) const char* p2 = luaL_checkstring(L, 2); /* normalize the paths */ - strcpy(src, p1); - do_translate(src, '/'); - strcpy(dst, p2); - do_translate(dst, '/'); + normalize(src, p1); + normalize(dst, p2); /* same directory? */ if (strcmp(src, dst) == 0) { diff --git a/tests/base/test_path.lua b/tests/base/test_path.lua index 0908ea90..5c5f73b6 100644 --- a/tests/base/test_path.lua +++ b/tests/base/test_path.lua @@ -176,6 +176,14 @@ test.isequal("/opt/include", path.getrelative("/home/me/src/project", "/opt/include")) end + function suite.ignoresExtraSlashes2() + test.isequal("..", path.getrelative("/a//b/c","/a/b")) + end + + function suite.ignoresExtraSlashes3() + test.isequal("..", path.getrelative("/a///b/c","/a/b")) + end + -- -- path.isabsolute() tests