From: Aki Tuomi Date: Fri, 9 Jun 2017 10:15:35 +0000 (+0300) Subject: lib: Fix infinite loop in path-util.c X-Git-Tag: 2.3.0.rc1~1465 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dfe2b5d36666dfc941821dadf59267d28ff58ff5;p=thirdparty%2Fdovecot%2Fcore.git lib: Fix infinite loop in path-util.c Infinite loop was reached if the path was longer than 128 bytes, and the 128 boundary was in middle of path name component. --- diff --git a/src/lib/path-util.c b/src/lib/path-util.c index d678909e4c..d23d12790b 100644 --- a/src/lib/path-util.c +++ b/src/lib/path-util.c @@ -175,9 +175,12 @@ static int path_normalize(const char *path, bool resolve_links, return -1; } - /* try again with bigger buffer */ + /* try again with bigger buffer, + we need to allocate more space as well if lsize == ret, + because the returned link may have gotten truncated */ espace = ltlen + tlen + 2; - if ((npath_pos + espace + lsize) >= (npath + asize)) { + if ((npath_pos + espace + lsize) >= (npath + asize) || + lsize == (size_t)ret) { ptrdiff_t npath_offset = npath_pos - npath; asize = nearest_power((npath_offset + espace + lsize) + 1); lsize = asize - (npath_offset + espace); diff --git a/src/lib/test-path-util.c b/src/lib/test-path-util.c index 9c736224db..e0db0b6550 100644 --- a/src/lib/test-path-util.c +++ b/src/lib/test-path-util.c @@ -3,6 +3,7 @@ #include "test-lib.h" #include "path-util.h" #include "unlink-directory.h" +#include "str.h" #include #include @@ -109,6 +110,49 @@ static void test_abspath_vs_normpath() { test_assert_strcmp(norm, "/bin"); } +static void test_link_alloc() { +#define COMPONENT_COMPONENT "/component-component" + const char *o_tmpdir; + + /* idea here is to make sure component-component + would optimally hit to the nearest_power value. + + it has to be big enough to cause requirement for + allocation in t_realpath. */ + string_t *basedir = t_str_new(256); + str_append(basedir, cwd); + str_append(basedir, "/"TEMP_DIRNAME); + size_t len = nearest_power(I_MAX(127, str_len(basedir))) - + strlen(COMPONENT_COMPONENT); + + while(str_len(basedir) < len) { + str_append(basedir, COMPONENT_COMPONENT); + (void)mkdir(str_c(basedir), 0700); + } + o_tmpdir = tmpdir; + tmpdir = str_c(basedir); + + link1 = t_strconcat(tmpdir, "/link1", NULL); + if (symlink(tmpdir, link1) < 0) { + i_fatal("symlink(%s, %s) failed: %m", tmpdir, link1); + } + + /* link2 and link3 point to each other to create a loop */ + link2 = t_strconcat(tmpdir, "/link2", NULL); + link3 = t_strconcat(tmpdir, "/link3", NULL); + if (symlink(link3, link2) < 0) { + i_fatal("symlink(%s, %s) failed: %m", link3, link2); + } + if (symlink(link2, link3) < 0) { + i_fatal("symlink(%s, %s) failed: %m", link2, link3); + } + + test_link1(); + test_link_loop(); + + tmpdir = o_tmpdir; +} + static void test_cleanup(void) { const char *error; @@ -145,6 +189,7 @@ static void test_init(void) { void test_path_util(void) { test_begin("test_path_util"); + alarm(20); test_init(); test_local_path(); test_absolute_path_no_change(); @@ -155,6 +200,8 @@ void test_path_util(void) { test_link1(); test_link_loop(); test_abspath_vs_normpath(); + test_link_alloc(); test_cleanup(); + alarm(0); test_end(); }