]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
tar: Handle extra bytes after sparse entries 2643/head
authorTobias Stoeckmann <tobias@stoeckmann.org>
Tue, 27 May 2025 17:57:05 +0000 (19:57 +0200)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Tue, 27 May 2025 17:57:05 +0000 (19:57 +0200)
Skip all entry bytes after sparse entries were encountered. This matches
GNU tar behavior.

I have adjusted (and fixed) the existing test case for this. The test
case test_read_format_gtar_sparse_skip_entry did not work with GNU tar.

In #2558 it was explained that the pax size always overrides the header
size (correct). Since the pax size in the test case was way larger than
the actual entry bytes in archive, GNU tar choke on the test file.

The libarchive parser did not skip any bytes not already read due to
references by sparse entries, so the huge pax size was not detected.

By adjusting the test case to have a leftover byte (only 3 bytes are
referenced through sparse entry now, leaving one extra byte) with a
correct pax size and an invalid header size (after all it is overridden
by pax size), GNU tar works and libarchive gets off its 512 byte
alignment, not being able to read the next entry.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
libarchive/archive_read_support_format_tar.c
libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu

index 1cc66716904510560cad482501615173afd80fae..67d8477f33c97dd249c3c003d21dcb4024775ca7 100644 (file)
@@ -628,7 +628,10 @@ archive_read_format_tar_read_data(struct archive_read *a,
                /* If we're at end of file, return EOF. */
                if (tar->sparse_list == NULL ||
                    tar->entry_bytes_remaining == 0) {
-                       if (__archive_read_consume(a, tar->entry_padding) < 0)
+                       int64_t request = tar->entry_bytes_remaining +
+                           tar->entry_padding;
+
+                       if (__archive_read_consume(a, request) != request)
                                return (ARCHIVE_FATAL);
                        tar->entry_padding = 0;
                        *buff = NULL;
@@ -666,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
 static int
 archive_read_format_tar_skip(struct archive_read *a)
 {
-       int64_t bytes_skipped;
        int64_t request;
-       struct sparse_block *p;
        struct tar* tar;
 
        tar = (struct tar *)(a->format->data);
 
-       /* Do not consume the hole of a sparse file. */
-       request = 0;
-       for (p = tar->sparse_list; p != NULL; p = p->next) {
-               if (!p->hole) {
-                       if (p->remaining >= INT64_MAX - request) {
-                               return ARCHIVE_FATAL;
-                       }
-                       request += p->remaining;
-               }
-       }
-       if (request > tar->entry_bytes_remaining)
-               request = tar->entry_bytes_remaining;
-       request += tar->entry_padding + tar->entry_bytes_unconsumed;
+       request = tar->entry_bytes_remaining + tar->entry_padding +
+           tar->entry_bytes_unconsumed;
 
-       bytes_skipped = __archive_read_consume(a, request);
-       if (bytes_skipped < 0)
+       if (__archive_read_consume(a, request) != request)
                return (ARCHIVE_FATAL);
 
        tar->entry_bytes_remaining = 0;
index 634ac0673db7582ed0e1911b6ce971bb6c843045..1aff5d386bdbbdaacb2110318a8bb858ce4ae81b 100644 (file)
@@ -1,15 +1,15 @@
 begin 644 test_read_format_gtar_sparse_skip_entry.tar.Z
 M'YV04,+@05(F#)DR<EZ$`<"PH<.'$"-*G$BQHL6*,#+:L$$#!(",,6[4@.$1
 MI$B2'S.JS#A#A@P0,63,L`$C!HP9-VB\K"FCAHT8`$#@N4BTJ-&C2"/6F4,G
-MC)R48^J424HQZE2J$E=F+*G5(]:O8,.*'3M6!LDY:?24Z6'S!DX:,7#(H$%#
-MP0R2;>BD:;,V!@T8-6)NE&'#10T<-#;>R(%CAEV28_3R9?LW\(P8-F[`<#%C
-M)@T<->#6>`PBC.2^E07;J#'#Q>J-F5DJ<`GBB),J+N;`<3JGC(LV8=2\D<-V
-M]DO;N'7S]MTFC9OA/6#,CE'[=N[=<GJ[<!-F<AB[-:HGQZY=3D$V:-6RA>$V
-M9]RY=<G*GT^_OOW[^/.#13Z%?!DC:;!1AD+Z%6B12AMUE%)((W'%($I:U603
-M#!W%-%---^6T4PPM8184#`:&"-9233V5D57SH2A?A%RMY)6(,,8HHPP*2/=7
-M#C8HT-9;[_VE0'PR!BGDD$06:>212"9YD1EOO*&`DE!&*>645%9IY9589JGE
+MC)R48^J424HQZE2J$E=F+*G5(]:O8,.*'3M6!LDY:?24Z:$U(XV?,A3,(-F&
+M3IHV:V/0@%$CYD89-ES4P/'6QHT<.&;()3G&+MX>>OG&F!'#,`P7,V;2P%&#
+M1HP:BT&$<9QW;U_`-FK,<)%ZH^6;"ER"..*DBHLY<)S.*>.B31@U;^1`COV2
+MMFW<NGFW2>,F.-O8,6;7OIU;SFX7;L(\#B.WAO3CU:_+*<@&K5K(,&[@](Q#
+M!@T:"LC*GT^_OOW[^/.#-3XE?!DC:;!1AD+Z%6B12AMUE%)((W'%($IMK=11
+M3#/5=%-..TTF@UY!P6#@AV`MU=13&5DUGXGRM<752EZ!Z.*+,,8%@P)[Y6"#
+M`C:IEU,,[>TE5WPP!BGDD$06:>212"9YD1EOO`&DDE!&*>645%9IY9589JGE
 MEEQVZ>678(8IYIADEFGFF6BFJ>::;+;IYIMPQBGGG'36:>>=>.:IYYY\]NGG
-MGX`&*NB@A!9JJ)YB](D@1PZ>U&B#*468484RT11###7<8!8(&-)4PX=^DN@4
-B5%*E6.J*746JTHN'2LFDDZW&*NNLM-9JZZVXYJKKKKR&!0``
+MGX`&*NB@A!9J*)YB](D@1PZ>U&B#*44(PX0RT13#9S>8!8*%--70H9\B.@65
+A5">2FF)7D:K4XJ%2,NDDJ[#&*NNLM-9JZZVXYJKKKF$!
 `
 end