diff options
author | Rob Landley <rob@landley.net> | 2013-01-17 23:16:38 -0600 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2013-01-17 23:16:38 -0600 |
commit | 7c0e2803d2bff7022637fb418de571b470dee2f6 (patch) | |
tree | 4c6372c1e87ecda9c3cc95fa3c6461f8a427cedc | |
parent | 6be5ac6a9287f4c48daf60d36eae44f04d7f9a80 (diff) | |
download | toybox-7c0e2803d2bff7022637fb418de571b470dee2f6.tar.gz |
Fix xabspath() resolving symlink after .., and properly detecting failure for last entry after nondir.
-rw-r--r-- | lib/lib.c | 31 |
1 files changed, 20 insertions, 11 deletions
@@ -375,23 +375,32 @@ char *xabspath(char *path, int exact) // Removable path componenents. if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { - if (new->str[1] && done) free(llist_pop(&done)); + int x = new->str[1]; + free(new); - continue; - } + if (x) { + if (done) free(llist_pop(&done)); + len = 0; + } else continue; // Is this a symlink? - len=readlinkat(dirfd, new->str, buf, 4096); + } else len=readlinkat(dirfd, new->str, buf, 4096); + if (len>4095) goto error; if (len<1) { int fd; - - // Not a symlink: add to linked list, move dirfd, fail if error - if ((exact || todo) && errno != EINVAL) goto error; - new->next = done; - done = new; - fd = openat(dirfd, new->str, O_DIRECTORY); - if (fd == -1 && (exact || todo)) goto error; + char *s = ".."; + + // For .. just move dirfd + if (len) { + // Not a symlink: add to linked list, move dirfd, fail if error + if ((exact || todo) && errno != EINVAL) goto error; + new->next = done; + done = new; + s = new->str; + } + fd = openat(dirfd, s, 0); + if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; close(dirfd); dirfd = fd; continue; |