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;
 	}
     }

Reply via email to