[hackers] [sbase][PATCH] tar: archive: improve fix for long names crashing

From: Andrea Calligaris <ac89.hk.public_AT_gmail.com>
Date: Mon, 24 Feb 2025 19:00:43 +0100

As requested, I resend my old patch for fixing the crashing while archiving
with names longer than 100 characters.

Last patch dealing with the issue: https://lists.suckless.org/hackers/2412/19213.html
My old patch: https://lists.suckless.org/hackers/2402/19071.html
---
 tar.c | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/tar.c b/tar.c
index e4701dc..ddc56ea 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -187,6 +187,8 @@ archive(const char *path)
 	size_t chksum, i;
 	ssize_t l, r;
 	int fd = -1;
+	char tmp_prefix[PATH_MAX];
+	char *bsname;
 
 	if (lstat(path, &st) < 0) {
 		weprintf("lstat %s:", path);
_AT_@ -202,26 +204,22 @@ archive(const char *path)
 	h = (struct header *)b;
 	memset(b, 0, sizeof(b));
 
-	if (strlen(path) > 255) {
-		const char *reason = "path exceeds 255 character limit";
-		eprintf("malformed tar archive: %s\n", reason);
-	} else if (strlen(path) >= 100) {
-		size_t prefix_len = 155;
-		const char *last_slash = strrchr(path, '/');
-
-		if (last_slash && last_slash < path + prefix_len) {
-		    prefix_len = last_slash - path + 1;
+	if (strlen(path) >= 100) {
+		// Cover case where path name is too long (in which case we need
+		// to split it to prefix and name).
+		bsname = basename((char *)path);
+		estrlcpy(tmp_prefix, path, PATH_MAX);
+		dirname(tmp_prefix);
+		// Could still be too long to fit in the fields.
+		if (strlen(bsname) >= sizeof(h->name) ||
+		    strlen(tmp_prefix) >= sizeof(h->prefix)) {
+			eprintf("filename too long: %s\n", path);
+		} else {
+			estrlcpy(h->name, bsname, sizeof(h->name));
+			estrlcpy(h->prefix, tmp_prefix, sizeof(h->prefix));
 		}
-
-		/* strlcpy is fine here - for path ONLY -,
-		 * since we're splitting the path.
-		 * It's not an issue if the prefix can't hold
-		 * the full path — name will take the rest. */
-		strlcpy(h->prefix, path, prefix_len);
-		estrlcpy(h->name, path + prefix_len, sizeof(h->name));
-	} else {
-		estrlcpy(h->name, path,		sizeof(h->name));
-	}
+	} else
+		estrlcpy(h->name, path, sizeof(h->name));
 
 	putoctal(h->mode,    (unsigned)st.st_mode & 0777, sizeof(h->mode));
 	putoctal(h->uid,     (unsigned)st.st_uid,         sizeof(h->uid));
-- 
2.34.1
Received on Mon Feb 24 2025 - 19:00:43 CET

This archive was generated by hypermail 2.3.0 : Mon Feb 24 2025 - 21:36:38 CET