[hackers] [sbase] tar: fix long names crashing tar archiving

From: Andrea Calligaris <ac89.hk.public_AT_gmail.com>
Date: Thu, 29 Feb 2024 21:28:48 +0100

It was already mentioned in Dec 2016 here:
https://lists.suckless.org/dev/1612/30852.html
but never fixed since.

*Extracting* long paths was added in May 2022 here:
https://lists.suckless.org/hackers/2205/18321.html
but not *archiving*.

Next thing to do should be supporting links while archiving.
---
 tar.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/tar.c b/tar.c
index d3a9f3b..aa81caf 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -187,6 +187,9 @@ archive(const char *path)
 	size_t chksum, i;
 	ssize_t l, r;
 	int fd = -1;
+	size_t path_len;
+	char tmp_prefix[PATH_MAX];
+	char *bsname;
 
 	if (lstat(path, &st) < 0) {
 		weprintf("lstat %s:", path);
_AT_@ -201,7 +204,25 @@ archive(const char *path)
 
 	h = (struct header *)b;
 	memset(b, 0, sizeof(b));
-	estrlcpy(h->name,    path,                        sizeof(h->name));
+
+	path_len = strlen(path);
+	if (path_len > 100 - 1) {
+		// Cover case where path name is too long (in which case we need
+		// to split it to prefix and name).
+		bsname = basename((char *)path);
+		strncpy(tmp_prefix, path, PATH_MAX);
+		dirname(tmp_prefix);
+		// Could still be too long to fit in the struct.
+		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));
+		}
+	} 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));
 	putoctal(h->gid,     (unsigned)st.st_gid,         sizeof(h->gid));
-- 
2.34.1
Received on Thu Feb 29 2024 - 21:28:48 CET

This archive was generated by hypermail 2.3.0 : Sun Mar 03 2024 - 18:00:39 CET