Module Name: src Committed By: rillig Date: Wed Jan 26 12:41:26 UTC 2022
Modified Files: src/usr.bin/make: meta.c Log Message: make: clean up eat_dots for meta mode, part 2 At least on OpenBSD, "If the src and dst strings overlap, the behavior is undefined" (since 2013-09-25), so rather use memmove instead. Keep all other bugs for now, for example "/a/b//../" is reduced to "/a/b/" instead of the correct "/a/", and for repeated "/././././" in long paths, the performance is quadratic instead of linear. Inline the two calls to eat_dots, turning the first into a two-liner. To generate a diff of this commit: cvs rdiff -u -r1.193 -r1.194 src/usr.bin/make/meta.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/meta.c diff -u src/usr.bin/make/meta.c:1.193 src/usr.bin/make/meta.c:1.194 --- src/usr.bin/make/meta.c:1.193 Wed Jan 26 12:16:03 2022 +++ src/usr.bin/make/meta.c Wed Jan 26 12:41:26 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.193 2022/01/26 12:16:03 rillig Exp $ */ +/* $NetBSD: meta.c,v 1.194 2022/01/26 12:41:26 rillig Exp $ */ /* * Implement 'meta' mode. @@ -205,27 +205,25 @@ filemon_read(FILE *mfp, int fd) * we use this, to clean up ./ and ../ */ static void -eat_dots(char *buf, size_t bufsz, const char *eat, size_t eatlen) +eat_dots(char *buf) { - char *cp; - char *cp2; + char *p; - do { - cp = strstr(buf, eat); - if (cp != NULL) { - cp2 = cp + eatlen; - if (eatlen == 3 && cp > buf) { - do { - cp--; - } while (cp > buf && *cp != '/'); - } - if (*cp == '/') { - strlcpy(cp, cp2, bufsz - (size_t)(cp - buf)); - } else { - return; /* can't happen? */ - } + while ((p = strstr(buf, "/./")) != NULL) + memmove(p, p + 2, strlen(p + 2) + 1); + + while ((p = strstr(buf, "/../")) != NULL) { + char *p2 = p + 3; + if (p > buf) { + do { + p--; + } while (p > buf && *p != '/'); } - } while (cp != NULL); + if (*p == '/') + memmove(p, p2, strlen(p2) + 1); + else + return; /* can't happen? */ + } } static char * @@ -269,8 +267,7 @@ meta_name(char *mname, size_t mnamelen, } else { snprintf(buf, sizeof buf, "%s/%s", cwd, tname); } - eat_dots(buf, sizeof buf, "/./", 2); - eat_dots(buf, sizeof buf, "/../", 3); + eat_dots(buf); tname = buf; } }