commit 20c27b1ad0f2fae65ede721c43f8cb66186d3049
parent cf1e0643396391213056ebae2f5c25611fc20ea4
Author: TahaGTRC <tahamedhous@gmail.com>
Date: Fri, 6 Dec 2024 10:37:20 +0100
tar: fix problem with paths longer than 100 characters
Diffstat:
M | tar.c | | | 25 | +++++++++++++++++++++++-- |
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git 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;