From a787fc5c556cbbc7f3de308d25b7527f9da5a0da Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 19 Jan 2014 17:41:06 -0800 Subject: [PATCH] 32294: prevent buffer overflow when scanning very long directory paths for symbolic links Upstream-commit: 3e06aeabd8a9e8384ebaa8b08996cd1f64737210 Signed-off-by: Kamil Dudka --- Src/utils.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Src/utils.c b/Src/utils.c index 20fa59d..a197ef8 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -726,32 +726,36 @@ xsymlinks(char *s) char **pp, **opp; char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2]; int t0, ret = 0; + zulong xbuflen = strlen(xbuf); opp = pp = slashsplit(s); - for (; *pp; pp++) { - if (!strcmp(*pp, ".")) { - zsfree(*pp); + for (; xbuflen < sizeof(xbuf) && *pp; pp++) { + if (!strcmp(*pp, ".")) continue; - } if (!strcmp(*pp, "..")) { char *p; - zsfree(*pp); if (!strcmp(xbuf, "/")) continue; if (!*xbuf) continue; - p = xbuf + strlen(xbuf); - while (*--p != '/'); + p = xbuf + xbuflen; + while (*--p != '/') + xbuflen--; *p = '\0'; continue; } sprintf(xbuf2, "%s/%s", xbuf, *pp); t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX); if (t0 == -1) { - strcat(xbuf, "/"); - strcat(xbuf, *pp); - zsfree(*pp); + zulong pplen = strlen(*pp) + 1; + if ((xbuflen += pplen) < sizeof(xbuf)) { + strcat(xbuf, "/"); + strcat(xbuf, *pp); + } else { + *xbuf = 0; + break; + } } else { ret = 1; metafy(xbuf3, t0, META_NOALLOC); @@ -760,10 +764,9 @@ xsymlinks(char *s) xsymlinks(xbuf3 + 1); } else xsymlinks(xbuf3); - zsfree(*pp); } } - free(opp); + freearray(opp); return ret; } @@ -780,8 +783,10 @@ xsymlink(char *s) return NULL; *xbuf = '\0'; xsymlinks(s + 1); - if (!*xbuf) + if (!*xbuf) { + zwarn("path expansion failed, using root directory"); return ztrdup("/"); + } return ztrdup(xbuf); } -- 2.14.3