erofs-utils: lib: tar: allow pax headers with empty names
authorGao Xiang <hsiangkao@linux.alibaba.com>
Mon, 9 Sep 2024 09:33:54 +0000 (17:33 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Mon, 9 Sep 2024 11:18:39 +0000 (19:18 +0800)
Usually, `exthdr.name`s are set as "%d/PaxHeaders.%p/%f" [1].

However, since both `GNU tar` and `bsdtar` can process empty
`exthdr.name`s, let's allow them too.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html

Reported-by: Colin Walters <walters@verbum.org>
Fixes: 95d315fd7958 ("erofs-utils: introduce tarerofs")
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20240909093354.1712460-1-hsiangkao@linux.alibaba.com
lib/tar.c

index 7e89b9290fd499ed3c7289af90d4b3037f4bab32..6d3529235a7032fceaadb65e6451cd3e6cbe2a22 100644 (file)
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -283,9 +283,9 @@ static long long tarerofs_otoi(const char *ptr, int len)
        inp[len] = '\0';
 
        errno = 0;
-       val = strtol(ptr, &endp, 8);
-       if ((!val && endp == inp) |
-            (*endp && *endp != ' '))
+       val = strtol(inp, &endp, 8);
+       if ((*endp == '\0' && endp == inp) |
+           (*endp != '\0' && *endp != ' '))
                errno = EINVAL;
        return val;
 }
@@ -663,18 +663,19 @@ restart:
                goto out;
        }
        tar->offset += sizeof(*th);
-       if (*th->name == '\0') {
-               if (e) {        /* end of tar 2 empty blocks */
-                       ret = 1;
-                       goto out;
-               }
-               e = true;       /* empty jump to next block */
-               goto restart;
-       }
 
        /* chksum field itself treated as ' ' */
        csum = tarerofs_otoi(th->chksum, sizeof(th->chksum));
        if (errno) {
+               if (*th->name == '\0') {
+out_eot:
+                       if (e) {        /* end of tar 2 empty blocks */
+                               ret = 1;
+                               goto out;
+                       }
+                       e = true;       /* empty jump to next block */
+                       goto restart;
+               }
                erofs_err("invalid chksum @ %llu", tar_offset);
                ret = -EBADMSG;
                goto out;
@@ -692,6 +693,11 @@ restart:
                ckksum += (int)((char*)th)[j];
        }
        if (!tar->ddtaridx_mode && csum != cksum && csum != ckksum) {
+               /* should not bail out here, just in case */
+               if (*th->name == '\0') {
+                       DBG_BUGON(1);
+                       goto out_eot;
+               }
                erofs_err("chksum mismatch @ %llu", tar_offset);
                ret = -EBADMSG;
                goto out;