Thanks for the bug report and test case. I'm puzzled about the symptoms reported, as my copy of GNU tar 1.35, when built on Ubuntu 23.10 x86-64, outputs this confusing diagnostic:

  tar: rmtlseek not stopped at a record boundary
  tar: Error is not recoverable: exiting now

when I run 'tar tvf gtar13c.tar', whereas your copy apparently does not. However, your test case with 'tar --delete' indeed has a segmentation violation.

I installed the attached three patches into the master repository <https://savannah.gnu.org/git/?group=tar>. The first fixes the confusing diagnostic. The second fixes an unchecked integer overflow nearby. And the third should fix the bug you reported.

Thanks again.
From 21318f385627a30da5d92811dd80f70abbe80ee7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sun, 3 Mar 2024 13:17:32 -0800
Subject: [PATCH 1/3] tar: improve diagnostic for truncated archive
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/buffer.c (seek_archive): If EOF has been read, don’t attempt
to seek past it.  This replaces a bogus "rmtlseek not stopped at a
record boundary" message with a better "Unexpected EOF in archive"
when I run ‘tar tvf gtar13c.tar’ using the gtar13.tar file here:
https://lists.gnu.org/r/bug-tar/2024-03/msg00001.html
---
 src/buffer.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/buffer.c b/src/buffer.c
index 56273642..9da6747a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1072,6 +1072,11 @@ seek_archive (off_t size)
   off_t start = current_block_ordinal ();
   off_t offset;
   off_t nrec, nblk;
+
+  /* If low level I/O is already at EOF, do not try to seek further.  */
+  if (record_end < record_start + blocking_factor)
+    return 0;
+
   off_t skipped = (blocking_factor - (current_block - record_start))
                   * BLOCKSIZE;
 
-- 
2.40.1

From 628c49250ad2257063f35a0780eba847e9ca78c5 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sun, 3 Mar 2024 13:20:23 -0800
Subject: [PATCH 2/3] tar: fix unlikely overflow

* src/delete.c (flush_file): Fix arithmetic overflow if
TYPE_MAXIMUM (off_t) - BLOCKSIZE < current_stat_info.stat.st_size.
---
 src/delete.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/delete.c b/src/delete.c
index 2b46e23b..4808a27b 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -139,11 +139,9 @@ write_recent_bytes (char *data, size_t bytes)
 static void
 flush_file (void)
 {
-  off_t blocks_to_skip;
-
   set_next_block_after (current_header);
-  blocks_to_skip = (current_stat_info.stat.st_size
-			  + BLOCKSIZE - 1) / BLOCKSIZE;
+  off_t size = current_stat_info.stat.st_size;
+  off_t blocks_to_skip = size / BLOCKSIZE + (size % BLOCKSIZE != 0);
 
   while (record_end - current_block <= blocks_to_skip)
     {
-- 
2.40.1

From 883f2e6dcaf87b4b449e55ed4f08dda1e701dae7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sun, 3 Mar 2024 13:27:32 -0800
Subject: [PATCH 3/3] tar: fix current_block confusion

Problem reported by Robert Morris in:
https://lists.gnu.org/r/bug-tar/2024-03/msg00001.html
* src/delete.c (flush_file): Simply return at EOF,
so that current_block continues to point to end of input.
---
 src/delete.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/delete.c b/src/delete.c
index 4808a27b..8303415f 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -149,7 +149,7 @@ flush_file (void)
       flush_archive ();
       if (record_end == current_block)
 	/* Hit EOF */
-	break;
+	return;
     }
   current_block += blocks_to_skip;
 }
-- 
2.40.1

Reply via email to