The following tar can contain two header blocks, and the second
header block describes the same file `foo` as a hardlink:

 $ touch foo
 $ tar cf foo.tar foo foo
 $ mkfs.erofs --tar=f foo.erofs foo.tar
 mkfs.erofs 1.8.10
 Segmentation fault (core dumped)

Closes: https://github.com/erofs/erofs-utils/issues/32
Fixes: 95d315fd7958 ("erofs-utils: introduce tarerofs")
Signed-off-by: Gao Xiang <[email protected]>
---
 lib/tar.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/lib/tar.c b/lib/tar.c
index 8aa90c7dc0d4..d5095169f9ba 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -995,12 +995,6 @@ out_eot:
                        goto out;
                }
 
-               if (d->type != EROFS_FT_UNKNOWN) {
-                       tarerofs_remove_inode(d->inode);
-                       erofs_iput(d->inode);
-               }
-               d->inode = NULL;
-
                d2 = erofs_rebuild_get_dentry(root, eh.link, tar->aufs,
                                              &dumb, &dumb, false);
                if (IS_ERR(d2)) {
@@ -1011,14 +1005,23 @@ out_eot:
                        ret = -ENOENT;
                        goto out;
                }
+               if (d == d2) {
+                       ret = 0;
+                       goto out;
+               }
                if (S_ISDIR(d2->inode->i_mode)) {
                        ret = -EISDIR;
                        goto out;
                }
+
                inode = erofs_igrab(d2->inode);
+               ++inode->i_nlink;
+               if (d->type != EROFS_FT_UNKNOWN) {
+                       tarerofs_remove_inode(d->inode);
+                       erofs_iput(d->inode);
+               }
                d->inode = inode;
                d->type = d2->type;
-               ++inode->i_nlink;
                ret = 0;
                goto out;
        } else if (d->type != EROFS_FT_UNKNOWN) {
-- 
2.43.5


Reply via email to