commit 20c27b1ad0f2fae65ede721c43f8cb66186d3049
Author:     TahaGTRC <tahamedh...@gmail.com>
AuthorDate: Fri Dec 6 10:37:20 2024 +0100
Commit:     Roberto E. Vargas Caballero <k...@shike2.com>
CommitDate: Tue Dec 17 11:18:06 2024 +0100

    tar: fix problem with paths longer than 100 characters

diff --git a/tar.c b/tar.c
index 7529997..dd4fc19 100644
--- a/tar.c
+++ b/tar.c
@@ -201,7 +201,28 @@ archive(const char *path)
 
        h = (struct header *)b;
        memset(b, 0, sizeof(b));
-       estrlcpy(h->name,    path,                        sizeof(h->name));
+
+       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;
+               }
+
+               /* 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));
+       }
+
        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));
@@ -456,7 +477,7 @@ xt(int argc, char *argv[], int mode)
        int i, n;
        int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ? unarchive : 
print;
 
-       while (eread(tarfd, b, BLKSIZ) > 0 && h->name[0]) {
+       while (eread(tarfd, b, BLKSIZ) > 0 && (h->name[0] || h->prefix[0])) {
                chktar(h);
                sanitize(h), n = 0;
 

Reply via email to