Not done yet but it's being addressed.

Richard

Sent by mobile; excuse my brevity.
---------- Forwarded message ----------
From: "Bart Schaefer" <schae...@brasslantern.com>
Date: Jan 20, 2014 2:11 AM
Subject: Re: segfault with exceedingly long path
To: <zsh-work...@zsh.org>
Cc:

On Jan 19,  4:02pm, Bart Schaefer wrote:
}
} I don't think we want to let this can of worms out of Pandora's box,
} or we'll be chasing geese until the cows come home to roost.

In spite of that ... we could at least not dump core in this specific
case.  There are probably many other core dumps waiting to be exposed.

Behavior becomes undefined once the path gets too long, but:

diff --git a/Src/utils.c b/Src/utils.c
index c6d178c..705d2c4 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -725,32 +725,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);
@@ -759,10 +763,9 @@ xsymlinks(char *s)
                xsymlinks(xbuf3 + 1);
            } else
                xsymlinks(xbuf3);
-           zsfree(*pp);
        }
     }
-    free(opp);
+    freearray(opp);
     return ret;
 }

@@ -779,8 +782,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);
 }


--
Barton E. Schaefer

Reply via email to