From 715f7eac02e4c9f3b440a04fec1d5da9ce7ad823 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Tue, 27 May 2025 19:57:05 +0200 Subject: [PATCH] tar: Handle extra bytes after sparse entries 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 --- libarchive/archive_read_support_format_tar.c | 25 ++++++------------- ...ead_format_gtar_sparse_skip_entry.tar.Z.uu | 18 ++++++------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 1cc667169..67d8477f3 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -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; diff --git a/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu b/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu index 634ac0673..1aff5d386 100644 --- a/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu +++ b/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu @@ -1,15 +1,15 @@ begin 644 test_read_format_gtar_sparse_skip_entry.tar.Z M'YV04,+@05(F#)DRBD:;,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[=$V -M9]RY=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,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 -- 2.47.2