]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Reject LHA archives with ridiculously large headers
authorTim Kientzle <kientzle@acm.org>
Sun, 1 Mar 2026 21:45:50 +0000 (13:45 -0800)
committerTim Kientzle <kientzle@acm.org>
Sun, 1 Mar 2026 21:45:50 +0000 (13:45 -0800)
The header is a series of blocks, most of which contain
values of just a few bytes (sizes, times, etc).  The only
exceptions are the filename and directory name attributes,
which will be limited by the MSDOS/Windows maximum file length
limit.  So it seems unlikely that this will ever exceed 64k.
(If we find counter-examples, we can easily extend this limit.)

Makefile.am
libarchive/archive_read_support_format_lha.c
libarchive/test/CMakeLists.txt
libarchive/test/test_read_format_lha_oversize_header.c [new file with mode: 0644]
libarchive/test/test_read_format_lha_oversize_header.lzh.uu [new file with mode: 0644]

index cb19545daa44a5a80633a93bfe17d8658d744452..066c2a28b2892ed15d840662aab38c650fb9e9e2 100644 (file)
@@ -516,6 +516,7 @@ libarchive_test_SOURCES= \
        libarchive/test/test_read_format_lha_bugfix_0.c \
        libarchive/test/test_read_format_lha_filename.c \
        libarchive/test/test_read_format_lha_filename_utf16.c \
+       libarchive/test/test_read_format_lha_oversize_header.c \
        libarchive/test/test_read_format_mtree.c \
        libarchive/test/test_read_format_mtree_crash747.c \
        libarchive/test/test_read_format_pax_bz2.c \
@@ -894,6 +895,7 @@ libarchive_test_EXTRA_DIST=\
        libarchive/test/test_read_format_lha_lh0.lzh.uu \
        libarchive/test/test_read_format_lha_lh6.lzh.uu \
        libarchive/test/test_read_format_lha_lh7.lzh.uu \
+       libarchive/test/test_read_format_lha_oversize_header.lzh.uu \
        libarchive/test/test_read_format_lha_withjunk.lzh.uu \
        libarchive/test/test_read_format_mtree.mtree.uu \
        libarchive/test/test_read_format_mtree_nomagic.mtree.uu \
index cf6a147abda6c3638fbd6c062c0f976f3989445f..ccdf49007cefdc1e536bb785fe882dfe0b4887d8 100644 (file)
@@ -1101,6 +1101,13 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
        header_crc = lha_crc16(0, p, H3_FIXED_SIZE);
        __archive_read_consume(a, H3_FIXED_SIZE);
 
+       /* Reject rediculously large header */
+       if (lha->header_size > 65536) {
+               archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                   "LHa header size too large");
+               return (ARCHIVE_FATAL);
+       }
+
        /* Read extended headers */
        err = lha_read_file_extended_header(a, lha, &header_crc, 4,
                  lha->header_size - H3_FIXED_SIZE, &extdsize);
index 02521c2bc1ad96ee8c2f6eba163ad68e01427e50..da95206dce2b2669aa7b99a486fd32695c2de0cc 100644 (file)
@@ -155,6 +155,7 @@ IF(ENABLE_TEST)
     test_read_format_lha_bugfix_0.c
     test_read_format_lha_filename.c
     test_read_format_lha_filename_utf16.c
+    test_read_format_lha_oversize_header.c
     test_read_format_mtree.c
     test_read_format_mtree_crash747.c
     test_read_format_pax_bz2.c
diff --git a/libarchive/test/test_read_format_lha_oversize_header.c b/libarchive/test/test_read_format_lha_oversize_header.c
new file mode 100644 (file)
index 0000000..e178e3a
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2026 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_format_lha_oversize_header)
+{
+       const char *refname = "test_read_format_lha_oversize_header.lzh";
+       extract_reference_file(refname);
+       struct archive_entry *ae;
+       struct archive *a;
+       int ret;
+
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
+
+       /* First 18 entries in the test file are well-formed */
+       for (int i = 0; i < 18; i++) {
+         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       }
+
+       /* 19th has an oversized header */
+       assertEqualInt(ARCHIVE_FATAL, archive_read_next_header(a, &ae));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/libarchive/test/test_read_format_lha_oversize_header.lzh.uu b/libarchive/test/test_read_format_lha_oversize_header.lzh.uu
new file mode 100644 (file)
index 0000000..e562e44
--- /dev/null
@@ -0,0 +1,60 @@
+begin 644 test_read_format_lha_oversize_header.lzh
+M)L`M;&AD+0```````````$@B[!``!&1I<EP``%4`@5$!`.A!Z0/I`R?X+6QH
+M9"T```````````!((NP0``5D:7(R7```50"!40$`[4'I`^D#.'PM;&AD+0``
+M`````````4@C[!``%F1I<C)<<WEM;&EN:S%\+BY<9FEL93$``%4``J,"`.VA
+MZ0/I`SA^+6QH9"T```````````%((^P0`!9D:7(R7'-Y;6QI;FLR?"XN7&9I
+M;&4R``!5``*C`@#MH>D#Z0,GO2UL:#4M(@```#P`````2"+L(``%9FEL93&D
+MYU4`@5$!`*2!Z0/I`P`80FYIQ>/Z`=-:'>9%#"P%J!\CH0"/GE$,.W6FMSD%
+M*_4G02UL:#4M(@```$X`````2"+L(``%9FEL93+5%54`@5$!`+:!Z0/I`P`8
+M0FYIQV/Z`=.:'.9%#"P%J-\+H0"/'E$,.W6FMSD%*_T9?RUL:&0M&@``````
+M````2"+L(`$```!5!P`"9&ER_P4`4.A!!P!1Z0/I`P<`5(%1`0```!F!+6QH
+M9"T;``````````!((NP@`0```%4(``)D:7(R_P4`4.U!!P!1Z0/I`P<`5(%1
+M`0```!YQ+6QH9"TG``````````%((^P@`05F:6QE,0``510``F1I<C+_<WEM
+M;&EN:S%\+B[_!0!0[:$'`%'I`^D#!P!4`J,"````'G(M;&AD+2<`````````
+M`4@C["`!!69I;&4R``!5%``"9&ER,O]S>6UL:6YK,GPN+O\%`%#MH0<`4>D#
+MZ0,'`%0"HP(````>!BUL:#4M-0```#P`````2"+L(`$%9FEL93&DYU4%`%"D
+M@0<`4>D#Z0,'`%2!40$`````&$)N:<7C^@'36AWF10PL!:@?(Z$`CYY1##MU
+MIK<Y!2OU'G@M;&@U+34```!.`````$@B["`!!69I;&4RU155!0!0MH$'`%'I
+M`^D#!P!4@5$!`````!A";FG'8_H!TYH<YD4,+`6HWPNA`(\>40P[=::W.04K
+M_34`+6QH9"T``````````(%1`0`@`@``504```7>`P`!!P`"9&ER_P4`4.A!
+M!P!1Z0/I`P``-@`M;&AD+0``````````@5$!`"`"``!5!0``")D#``$(``)D
+M:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0```````````J,"`"`"``!5!0``
+MM*D(``%F:6QE,10``F1I<C+_<WEM;&EN:S%\+B[_!0!0[:$'`%'I`^D#``!'
+M`"UL:&0M```````````"HP(`(`(``%4%``"'[0@``69I;&4R%``"9&ER,O]S
+M>6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,`+6QH-2TB````/````(%1`0`@
+M`J3G504``/T!"``!9FEL93$%`%"D@0<`4>D#Z0,````80FYIQ>/Z`=-:'>9%
+M#"P%J!\CH0"/GE$,.W6FMSD%*_4S`"UL:#4M(@```$X```"!40$`(`+5%54%
+M```OQ@@``69I;&4R!0!0MH$'`%'I`^D#````&$)N:<=C^@'3FASF10PL!:C?
+M"Z$`CQY1##MUIK<Y!2O]!``M;&AD+0``````````@5$!`"`#``!-?/[___\`
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````$:D`P``!0````$)`````F1I
+M<O\'````0!``&0```/_M00`````````````,%?Y,1!K^3!T```!!S-]1M/Z5
+MRP&`UD``J+*=`0!Z#]`!ELL!"``````NKP<`````!``M;&AD+0``````````
+M@5$!`"`#``!-?0````D```!&I`,```4````!"@````)D:7(R_P<```!`$``9
+M````_^U!`````````````"$:_DQ$&OY,'0```$%*@6Z[`9;+`8#60`"HLIT!
+M`'H/T`&6RP$(`````'T7!P`````$`"UL:#4M)````#P```"!40$`(`.DYTUQ
+M````"0```$:D`P``"@````%F:6QE,1D```#_I($`````````````QQ3^3",:
+M_DP=````031"HHK^E<L!@-9``*BRG0'^<J2\`9;+`0@`````"O$'```````9
+M0FV1J+1V@'IK0ZGID/-H#J@6.H0"'V^-&353:F^XA-UZ@`0`+6QH-2TD````
+M3@```(%1`0`@`]4537$````)````1J0#```*`````69I;&4R&0```/^D@0``
+M```````````A&OY,(QK^3!T```!!_D5SNP&6RP&`UD``J+*=`5C5IKP!ELL!
+M"`````!!W@<``````!E";9&H[':`>G-#B>F0\V@.J,8:A`(>;XT9-5-J;[B$
+MW7Z`-0`M;&AD+0``````````@5$!`"`"``!5!40:_DP=````0<S?4;3^E<L!
+M@-9``*BRG0$`>@_0`9;+`0@`````+J\'``````0`+6QH9"T``````````(%1
+M`0`@`P``37T````)````1J0#```%`````0H````"9&ER,O\'````0!``&0``
+M`/_M00`````````````A&OY,1!K^3!T```!!2H%NNP&6RP&`UD``J+*=`0!Z
+M#]`!ELL!"`````!]%P<`````!``M;&@U+20````\````@5$!`"`#I.=-<0``
+M``D```!&I`,```H````!9FEL93$9````_Z2!`````````````,<4_DPC&OY,
+M'0```$$T0J**_I7+`8#60`"HLIT!_G*DO`&6RP$(``````KQ!P``````&4)M
+MD:BT=H!Z:T.IZ9!1Z0/I`P```FUK=XVV['"Z\`>$(6[`2-EZ5P&P^!J*0MPV
+M*IM]&^L37/)<Y+,0WC;RYN647;X'R_\P`E;2>[SD(6GCE`4$+,RA<%QVYXC%
+M'H1Q`I@_B\H/L@(+W3`0@5CY6X%Q%WW+@7<`8(F7=77U]%5YG?`;3N&I:_6Y
+MWA$,3F@?:)>FZ!<!"?.:#C/:',\PG@>:WRP0:TH8%&:/A#VMNUUD[D?+:#XK
+M%3NMR(PSF4;V"^\X0/E3JMRQ46+7\I]S@7ZJNTX[ROSD+=\7\.O#I:W._S>P
+M-B(W4`=N<T/$OT+5];U>*!<4AM0Y4$L'"(=02P,$\$*.O%TM;&@U+0``KPLX
+M+4``2@````````"``````/________\`````````V0````"A````````````
+M````````````+6QH-RT```!8$,P.0&OJER*:CF[S6/=2*T4J8HB@[:HP^'7*
+MK?(\7:Y+-"U'*^OXT210`,J%*>9(T9[(@N(DJ+A)A```3`]%Z8U.^3!F0_G-
+17YFUYB_%6DWMSZ8'\Z-^CR@`
+`
+end