Introduction
Introduction Statistics Contact Development Disclaimer Help
tar: archive: improve fix for long names crashing - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
commit 39a4c55378294437627421571a51b64bd5e09623
parent 97629ab38692ee65250a882bb88eb31c71e51f00
Author: Andrea Calligaris <[email protected]>
Date: Wed, 26 Feb 2025 11:03:58 +0100
tar: archive: improve fix for long names crashing
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 was [1], and the old patch was [2]. The
code before this commit was not dealing correctly with multiple slashes,
but use of basename(3) and dirname(3) needed a temporary buffer because
otherwise we destroyed the path that was used later in several places.
This solution does not modifies the path and use pointer arithmetic to
solve the problem.
[1] https://lists.suckless.org/hackers/2412/19213.html
[2] https://lists.suckless.org/hackers/2402/19071.html
Co-authored-by: Roberto E. Vargas Caballer <[email protected]>
Diffstat:
M tar.c | 44 +++++++++++++++++------------…
1 file changed, 24 insertions(+), 20 deletions(-)
---
diff --git a/tar.c b/tar.c
@@ -180,11 +180,12 @@ static int
archive(const char *path)
{
char b[BLKSIZ];
+ const char *base, *p;
struct group *gr;
struct header *h;
struct passwd *pw;
struct stat st;
- size_t chksum, i;
+ size_t chksum, i, nlen, plen;
ssize_t l, r;
int fd = -1;
@@ -202,27 +203,27 @@ 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;
- }
-
- /* 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));
+ plen = 0;
+ base = path;
+ if ((nlen = strlen(base)) >= sizeof(h->name)) {
+ /*
+ * Cover case where path name is too long (in which case we
+ * need to split it to prefix and name).
+ */
+ if ((base = strrchr(path, '/')) == NULL)
+ goto too_long;
+ for (p = base++; p > path && *p == '/'; --p)
+ ;
+
+ nlen -= base - path;
+ plen = p - path + 1;
+ if (nlen >= sizeof(h->name) || plen >= sizeof(h->prefix))
+ goto too_long;
}
+ memcpy(h->name, base, nlen);
+ memcpy(h->prefix, path, plen);
+
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));
@@ -270,6 +271,9 @@ archive(const char *path)
}
return 0;
+
+too_long:
+ eprintf("filename too long: %s\n", path);
}
static int
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.