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
@@ -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);
@@ -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


Reply via email to