16c95142eSMartin Matuska /*-
26c95142eSMartin Matuska  * Copyright (c) 2010-2012 Michihiro NAKAJIMA
36c95142eSMartin Matuska  * All rights reserved.
46c95142eSMartin Matuska  *
56c95142eSMartin Matuska  * Redistribution and use in source and binary forms, with or without
66c95142eSMartin Matuska  * modification, are permitted provided that the following conditions
76c95142eSMartin Matuska  * are met:
86c95142eSMartin Matuska  * 1. Redistributions of source code must retain the above copyright
96c95142eSMartin Matuska  *    notice, this list of conditions and the following disclaimer.
106c95142eSMartin Matuska  * 2. Redistributions in binary form must reproduce the above copyright
116c95142eSMartin Matuska  *    notice, this list of conditions and the following disclaimer in the
126c95142eSMartin Matuska  *    documentation and/or other materials provided with the distribution.
136c95142eSMartin Matuska  *
146c95142eSMartin Matuska  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
156c95142eSMartin Matuska  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
166c95142eSMartin Matuska  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
176c95142eSMartin Matuska  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
186c95142eSMartin Matuska  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
196c95142eSMartin Matuska  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
206c95142eSMartin Matuska  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
216c95142eSMartin Matuska  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
226c95142eSMartin Matuska  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
236c95142eSMartin Matuska  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
246c95142eSMartin Matuska  */
256c95142eSMartin Matuska 
266c95142eSMartin Matuska #include "archive_platform.h"
276c95142eSMartin Matuska 
286c95142eSMartin Matuska #ifdef HAVE_ERRNO_H
296c95142eSMartin Matuska #include <errno.h>
306c95142eSMartin Matuska #endif
316c95142eSMartin Matuska #ifdef HAVE_LIMITS_H
326c95142eSMartin Matuska #include <limits.h>
336c95142eSMartin Matuska #endif
346c95142eSMartin Matuska #ifdef HAVE_STDLIB_H
356c95142eSMartin Matuska #include <stdlib.h>
366c95142eSMartin Matuska #endif
376c95142eSMartin Matuska #ifdef HAVE_STRING_H
386c95142eSMartin Matuska #include <string.h>
396c95142eSMartin Matuska #endif
406c95142eSMartin Matuska #ifdef HAVE_ZLIB_H
416c95142eSMartin Matuska #include <zlib.h>
426c95142eSMartin Matuska #endif
436c95142eSMartin Matuska 
446c95142eSMartin Matuska #include "archive.h"
456c95142eSMartin Matuska #include "archive_entry.h"
466c95142eSMartin Matuska #include "archive_entry_locale.h"
476c95142eSMartin Matuska #include "archive_private.h"
486c95142eSMartin Matuska #include "archive_read_private.h"
496c95142eSMartin Matuska #include "archive_endian.h"
506c95142eSMartin Matuska 
516c95142eSMartin Matuska 
526c95142eSMartin Matuska struct lzx_dec {
536c95142eSMartin Matuska 	/* Decoding status. */
546c95142eSMartin Matuska 	int     		 state;
556c95142eSMartin Matuska 
566c95142eSMartin Matuska 	/*
576c95142eSMartin Matuska 	 * Window to see last decoded data, from 32KBi to 2MBi.
586c95142eSMartin Matuska 	 */
596c95142eSMartin Matuska 	int			 w_size;
606c95142eSMartin Matuska 	int			 w_mask;
616c95142eSMartin Matuska 	/* Window buffer, which is a loop buffer. */
626c95142eSMartin Matuska 	unsigned char		*w_buff;
636c95142eSMartin Matuska 	/* The insert position to the window. */
646c95142eSMartin Matuska 	int			 w_pos;
656c95142eSMartin Matuska 	/* The position where we can copy decoded code from the window. */
666c95142eSMartin Matuska 	int     		 copy_pos;
676c95142eSMartin Matuska 	/* The length how many bytes we can copy decoded code from
686c95142eSMartin Matuska 	 * the window. */
696c95142eSMartin Matuska 	int     		 copy_len;
70a2e802b7SMartin Matuska 	/* Translation reversal for x86 processor CALL byte sequence(E8).
716c95142eSMartin Matuska 	 * This is used for LZX only. */
726c95142eSMartin Matuska 	uint32_t		 translation_size;
736c95142eSMartin Matuska 	char			 translation;
746c95142eSMartin Matuska 	char			 block_type;
756c95142eSMartin Matuska #define VERBATIM_BLOCK		1
766c95142eSMartin Matuska #define ALIGNED_OFFSET_BLOCK	2
776c95142eSMartin Matuska #define UNCOMPRESSED_BLOCK	3
786c95142eSMartin Matuska 	size_t			 block_size;
796c95142eSMartin Matuska 	size_t			 block_bytes_avail;
806c95142eSMartin Matuska 	/* Repeated offset. */
816c95142eSMartin Matuska 	int			 r0, r1, r2;
826c95142eSMartin Matuska 	unsigned char		 rbytes[4];
836c95142eSMartin Matuska 	int			 rbytes_avail;
846c95142eSMartin Matuska 	int			 length_header;
856c95142eSMartin Matuska 	int			 position_slot;
866c95142eSMartin Matuska 	int			 offset_bits;
876c95142eSMartin Matuska 
886c95142eSMartin Matuska 	struct lzx_pos_tbl {
896c95142eSMartin Matuska 		int		 base;
906c95142eSMartin Matuska 		int		 footer_bits;
916c95142eSMartin Matuska 	}			*pos_tbl;
926c95142eSMartin Matuska 	/*
936c95142eSMartin Matuska 	 * Bit stream reader.
946c95142eSMartin Matuska 	 */
956c95142eSMartin Matuska 	struct lzx_br {
966c95142eSMartin Matuska #define CACHE_TYPE		uint64_t
976c95142eSMartin Matuska #define CACHE_BITS		(8 * sizeof(CACHE_TYPE))
986c95142eSMartin Matuska 	 	/* Cache buffer. */
996c95142eSMartin Matuska 		CACHE_TYPE	 cache_buffer;
1006c95142eSMartin Matuska 		/* Indicates how many bits avail in cache_buffer. */
1016c95142eSMartin Matuska 		int		 cache_avail;
1026c95142eSMartin Matuska 		unsigned char	 odd;
1036c95142eSMartin Matuska 		char		 have_odd;
1046c95142eSMartin Matuska 	} br;
1056c95142eSMartin Matuska 
1066c95142eSMartin Matuska 	/*
1076c95142eSMartin Matuska 	 * Huffman coding.
1086c95142eSMartin Matuska 	 */
1096c95142eSMartin Matuska 	struct huffman {
1106c95142eSMartin Matuska 		int		 len_size;
1116c95142eSMartin Matuska 		int		 freq[17];
1126c95142eSMartin Matuska 		unsigned char	*bitlen;
1136c95142eSMartin Matuska 
1146c95142eSMartin Matuska 		/*
1156c95142eSMartin Matuska 		 * Use a index table. It's faster than searching a huffman
1166c95142eSMartin Matuska 		 * coding tree, which is a binary tree. But a use of a large
1176c95142eSMartin Matuska 		 * index table causes L1 cache read miss many times.
1186c95142eSMartin Matuska 		 */
1196c95142eSMartin Matuska #define HTBL_BITS	10
1206c95142eSMartin Matuska 		int		 max_bits;
1216c95142eSMartin Matuska 		int		 shift_bits;
1226c95142eSMartin Matuska 		int		 tbl_bits;
1236c95142eSMartin Matuska 		int		 tree_used;
1246c95142eSMartin Matuska 		int		 tree_avail;
1256c95142eSMartin Matuska 		/* Direct access table. */
1266c95142eSMartin Matuska 		uint16_t	*tbl;
1276c95142eSMartin Matuska 		/* Binary tree table for extra bits over the direct access. */
1286c95142eSMartin Matuska 		struct htree_t {
1296c95142eSMartin Matuska 			uint16_t left;
1306c95142eSMartin Matuska 			uint16_t right;
1316c95142eSMartin Matuska 		}		*tree;
1326c95142eSMartin Matuska 	}			 at, lt, mt, pt;
1336c95142eSMartin Matuska 
1346c95142eSMartin Matuska 	int			 loop;
1356c95142eSMartin Matuska 	int			 error;
1366c95142eSMartin Matuska };
1376c95142eSMartin Matuska 
1386c95142eSMartin Matuska static const int slots[] = {
1396c95142eSMartin Matuska 	30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
1406c95142eSMartin Matuska };
1416c95142eSMartin Matuska #define SLOT_BASE	15
1426c95142eSMartin Matuska #define SLOT_MAX	21/*->25*/
1436c95142eSMartin Matuska 
1446c95142eSMartin Matuska struct lzx_stream {
1456c95142eSMartin Matuska 	const unsigned char	*next_in;
1466c95142eSMartin Matuska 	int64_t			 avail_in;
1476c95142eSMartin Matuska 	int64_t			 total_in;
1486c95142eSMartin Matuska 	unsigned char		*next_out;
1496c95142eSMartin Matuska 	int64_t			 avail_out;
1506c95142eSMartin Matuska 	int64_t			 total_out;
1516c95142eSMartin Matuska 	struct lzx_dec		*ds;
1526c95142eSMartin Matuska };
1536c95142eSMartin Matuska 
1546c95142eSMartin Matuska /*
1556c95142eSMartin Matuska  * Cabinet file definitions.
1566c95142eSMartin Matuska  */
1576c95142eSMartin Matuska /* CFHEADER offset */
1586c95142eSMartin Matuska #define CFHEADER_signature	0
1596c95142eSMartin Matuska #define CFHEADER_cbCabinet	8
1606c95142eSMartin Matuska #define CFHEADER_coffFiles	16
1616c95142eSMartin Matuska #define CFHEADER_versionMinor	24
1626c95142eSMartin Matuska #define CFHEADER_versionMajor	25
1636c95142eSMartin Matuska #define CFHEADER_cFolders	26
1646c95142eSMartin Matuska #define CFHEADER_cFiles		28
1656c95142eSMartin Matuska #define CFHEADER_flags		30
1666c95142eSMartin Matuska #define CFHEADER_setID		32
1676c95142eSMartin Matuska #define CFHEADER_iCabinet	34
1686c95142eSMartin Matuska #define CFHEADER_cbCFHeader	36
1696c95142eSMartin Matuska #define CFHEADER_cbCFFolder	38
1706c95142eSMartin Matuska #define CFHEADER_cbCFData	39
1716c95142eSMartin Matuska 
1726c95142eSMartin Matuska /* CFFOLDER offset */
1736c95142eSMartin Matuska #define CFFOLDER_coffCabStart	0
1746c95142eSMartin Matuska #define CFFOLDER_cCFData	4
1756c95142eSMartin Matuska #define CFFOLDER_typeCompress	6
1766c95142eSMartin Matuska #define CFFOLDER_abReserve	8
1776c95142eSMartin Matuska 
1786c95142eSMartin Matuska /* CFFILE offset */
1796c95142eSMartin Matuska #define CFFILE_cbFile		0
1806c95142eSMartin Matuska #define CFFILE_uoffFolderStart	4
1816c95142eSMartin Matuska #define CFFILE_iFolder		8
1826c95142eSMartin Matuska #define CFFILE_date_time	10
1836c95142eSMartin Matuska #define CFFILE_attribs		14
1846c95142eSMartin Matuska 
1856c95142eSMartin Matuska /* CFDATA offset */
1866c95142eSMartin Matuska #define CFDATA_csum		0
1876c95142eSMartin Matuska #define CFDATA_cbData		4
1886c95142eSMartin Matuska #define CFDATA_cbUncomp		6
1896c95142eSMartin Matuska 
190*a7f7e457SMartin Matuska static const char * const compression_name[] = {
1916c95142eSMartin Matuska 	"NONE",
1926c95142eSMartin Matuska 	"MSZIP",
1936c95142eSMartin Matuska 	"Quantum",
1946c95142eSMartin Matuska 	"LZX",
1956c95142eSMartin Matuska };
1966c95142eSMartin Matuska 
1976c95142eSMartin Matuska struct cfdata {
1986c95142eSMartin Matuska 	/* Sum value of this CFDATA. */
1996c95142eSMartin Matuska 	uint32_t		 sum;
2006c95142eSMartin Matuska 	uint16_t		 compressed_size;
2016c95142eSMartin Matuska 	uint16_t		 compressed_bytes_remaining;
2026c95142eSMartin Matuska 	uint16_t		 uncompressed_size;
2036c95142eSMartin Matuska 	uint16_t		 uncompressed_bytes_remaining;
2046c95142eSMartin Matuska 	/* To know how many bytes we have decompressed. */
2056c95142eSMartin Matuska 	uint16_t		 uncompressed_avail;
2066c95142eSMartin Matuska 	/* Offset from the beginning of compressed data of this CFDATA */
2076c95142eSMartin Matuska 	uint16_t		 read_offset;
2086c95142eSMartin Matuska 	int64_t			 unconsumed;
2096c95142eSMartin Matuska 	/* To keep memory image of this CFDATA to compute the sum. */
2106c95142eSMartin Matuska 	size_t			 memimage_size;
2116c95142eSMartin Matuska 	unsigned char		*memimage;
2126c95142eSMartin Matuska 	/* Result of calculation of sum. */
2136c95142eSMartin Matuska 	uint32_t		 sum_calculated;
2146c95142eSMartin Matuska 	unsigned char		 sum_extra[4];
2156c95142eSMartin Matuska 	int			 sum_extra_avail;
2166c95142eSMartin Matuska 	const void		*sum_ptr;
2176c95142eSMartin Matuska };
2186c95142eSMartin Matuska 
2196c95142eSMartin Matuska struct cffolder {
2206c95142eSMartin Matuska 	uint32_t		 cfdata_offset_in_cab;
2216c95142eSMartin Matuska 	uint16_t		 cfdata_count;
2226c95142eSMartin Matuska 	uint16_t		 comptype;
2236c95142eSMartin Matuska #define COMPTYPE_NONE		0x0000
2246c95142eSMartin Matuska #define COMPTYPE_MSZIP		0x0001
2256c95142eSMartin Matuska #define COMPTYPE_QUANTUM	0x0002
2266c95142eSMartin Matuska #define COMPTYPE_LZX		0x0003
2276c95142eSMartin Matuska 	uint16_t		 compdata;
2286c95142eSMartin Matuska 	const char		*compname;
2296c95142eSMartin Matuska 	/* At the time reading CFDATA */
2306c95142eSMartin Matuska 	struct cfdata		 cfdata;
2316c95142eSMartin Matuska 	int			 cfdata_index;
2326c95142eSMartin Matuska 	/* Flags to mark progress of decompression. */
2336c95142eSMartin Matuska 	char			 decompress_init;
2346c95142eSMartin Matuska };
2356c95142eSMartin Matuska 
2366c95142eSMartin Matuska struct cffile {
2376c95142eSMartin Matuska 	uint32_t		 uncompressed_size;
2386c95142eSMartin Matuska 	uint32_t		 offset;
2396c95142eSMartin Matuska 	time_t			 mtime;
2406c95142eSMartin Matuska 	uint16_t	 	 folder;
2416c95142eSMartin Matuska #define iFoldCONTINUED_FROM_PREV	0xFFFD
2426c95142eSMartin Matuska #define iFoldCONTINUED_TO_NEXT		0xFFFE
2436c95142eSMartin Matuska #define iFoldCONTINUED_PREV_AND_NEXT	0xFFFF
2446c95142eSMartin Matuska 	unsigned char		 attr;
2456c95142eSMartin Matuska #define ATTR_RDONLY		0x01
2466c95142eSMartin Matuska #define ATTR_NAME_IS_UTF	0x80
2476c95142eSMartin Matuska 	struct archive_string 	 pathname;
2486c95142eSMartin Matuska };
2496c95142eSMartin Matuska 
2506c95142eSMartin Matuska struct cfheader {
2516c95142eSMartin Matuska 	/* Total bytes of all file size in a Cabinet. */
2526c95142eSMartin Matuska 	uint32_t		 total_bytes;
2536c95142eSMartin Matuska 	uint32_t		 files_offset;
2546c95142eSMartin Matuska 	uint16_t		 folder_count;
2556c95142eSMartin Matuska 	uint16_t		 file_count;
2566c95142eSMartin Matuska 	uint16_t		 flags;
2576c95142eSMartin Matuska #define PREV_CABINET	0x0001
2586c95142eSMartin Matuska #define NEXT_CABINET	0x0002
2596c95142eSMartin Matuska #define RESERVE_PRESENT	0x0004
2606c95142eSMartin Matuska 	uint16_t		 setid;
2616c95142eSMartin Matuska 	uint16_t		 cabinet;
2626c95142eSMartin Matuska 	/* Version number. */
2636c95142eSMartin Matuska 	unsigned char		 major;
2646c95142eSMartin Matuska 	unsigned char		 minor;
2656c95142eSMartin Matuska 	unsigned char		 cffolder;
2666c95142eSMartin Matuska 	unsigned char		 cfdata;
2676c95142eSMartin Matuska 	/* All folders in a cabinet. */
2686c95142eSMartin Matuska 	struct cffolder		*folder_array;
2696c95142eSMartin Matuska 	/* All files in a cabinet. */
2706c95142eSMartin Matuska 	struct cffile		*file_array;
2716c95142eSMartin Matuska 	int			 file_index;
2726c95142eSMartin Matuska };
2736c95142eSMartin Matuska 
2746c95142eSMartin Matuska struct cab {
2756c95142eSMartin Matuska 	/* entry_bytes_remaining is the number of bytes we expect.	    */
2766c95142eSMartin Matuska 	int64_t			 entry_offset;
2776c95142eSMartin Matuska 	int64_t			 entry_bytes_remaining;
2786c95142eSMartin Matuska 	int64_t			 entry_unconsumed;
2796c95142eSMartin Matuska 	int64_t			 entry_compressed_bytes_read;
2806c95142eSMartin Matuska 	int64_t			 entry_uncompressed_bytes_read;
2816c95142eSMartin Matuska 	struct cffolder		*entry_cffolder;
2826c95142eSMartin Matuska 	struct cffile		*entry_cffile;
2836c95142eSMartin Matuska 	struct cfdata		*entry_cfdata;
2846c95142eSMartin Matuska 
2856c95142eSMartin Matuska 	/* Offset from beginning of a cabinet file. */
2866c95142eSMartin Matuska 	int64_t			 cab_offset;
2876c95142eSMartin Matuska 	struct cfheader		 cfheader;
2886c95142eSMartin Matuska 	struct archive_wstring	 ws;
2896c95142eSMartin Matuska 
2906c95142eSMartin Matuska 	/* Flag to mark progress that an archive was read their first header.*/
2916c95142eSMartin Matuska 	char			 found_header;
2926c95142eSMartin Matuska 	char			 end_of_archive;
2936c95142eSMartin Matuska 	char			 end_of_entry;
2946c95142eSMartin Matuska 	char			 end_of_entry_cleanup;
295fd082e96SMartin Matuska 	char			 read_data_invoked;
296fd082e96SMartin Matuska 	int64_t			 bytes_skipped;
2976c95142eSMartin Matuska 
2986c95142eSMartin Matuska 	unsigned char		*uncompressed_buffer;
2996c95142eSMartin Matuska 	size_t			 uncompressed_buffer_size;
3006c95142eSMartin Matuska 
3016c95142eSMartin Matuska 	int			 init_default_conversion;
3026c95142eSMartin Matuska 	struct archive_string_conv *sconv;
3036c95142eSMartin Matuska 	struct archive_string_conv *sconv_default;
3046c95142eSMartin Matuska 	struct archive_string_conv *sconv_utf8;
3056c95142eSMartin Matuska 	char			 format_name[64];
3066c95142eSMartin Matuska 
3076c95142eSMartin Matuska #ifdef HAVE_ZLIB_H
3086c95142eSMartin Matuska 	z_stream		 stream;
3096c95142eSMartin Matuska 	char			 stream_valid;
3106c95142eSMartin Matuska #endif
3116c95142eSMartin Matuska 	struct lzx_stream	 xstrm;
3126c95142eSMartin Matuska };
3136c95142eSMartin Matuska 
3146c95142eSMartin Matuska static int	archive_read_format_cab_bid(struct archive_read *, int);
3156c95142eSMartin Matuska static int	archive_read_format_cab_options(struct archive_read *,
3166c95142eSMartin Matuska 		    const char *, const char *);
3176c95142eSMartin Matuska static int	archive_read_format_cab_read_header(struct archive_read *,
3186c95142eSMartin Matuska 		    struct archive_entry *);
3196c95142eSMartin Matuska static int	archive_read_format_cab_read_data(struct archive_read *,
3206c95142eSMartin Matuska 		    const void **, size_t *, int64_t *);
3216c95142eSMartin Matuska static int	archive_read_format_cab_read_data_skip(struct archive_read *);
3226c95142eSMartin Matuska static int	archive_read_format_cab_cleanup(struct archive_read *);
3236c95142eSMartin Matuska 
3246c95142eSMartin Matuska static int	cab_skip_sfx(struct archive_read *);
3256c95142eSMartin Matuska static time_t	cab_dos_time(const unsigned char *);
3266c95142eSMartin Matuska static int	cab_read_data(struct archive_read *, const void **,
3276c95142eSMartin Matuska 		    size_t *, int64_t *);
3286c95142eSMartin Matuska static int	cab_read_header(struct archive_read *);
3296c95142eSMartin Matuska static uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t);
3306c95142eSMartin Matuska static uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t);
3316c95142eSMartin Matuska static void	cab_checksum_update(struct archive_read *, size_t);
3326c95142eSMartin Matuska static int	cab_checksum_finish(struct archive_read *);
3336c95142eSMartin Matuska static int	cab_next_cfdata(struct archive_read *);
3346c95142eSMartin Matuska static const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *);
3356c95142eSMartin Matuska static const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *);
3366c95142eSMartin Matuska static const void *cab_read_ahead_cfdata_deflate(struct archive_read *,
3376c95142eSMartin Matuska 		    ssize_t *);
3386c95142eSMartin Matuska static const void *cab_read_ahead_cfdata_lzx(struct archive_read *,
3396c95142eSMartin Matuska 		    ssize_t *);
3406c95142eSMartin Matuska static int64_t	cab_consume_cfdata(struct archive_read *, int64_t);
3416c95142eSMartin Matuska static int64_t	cab_minimum_consume_cfdata(struct archive_read *, int64_t);
3426c95142eSMartin Matuska static int	lzx_decode_init(struct lzx_stream *, int);
3436c95142eSMartin Matuska static int	lzx_read_blocks(struct lzx_stream *, int);
3446c95142eSMartin Matuska static int	lzx_decode_blocks(struct lzx_stream *, int);
3456c95142eSMartin Matuska static void	lzx_decode_free(struct lzx_stream *);
3466c95142eSMartin Matuska static void	lzx_translation(struct lzx_stream *, void *, size_t, uint32_t);
3476c95142eSMartin Matuska static void	lzx_cleanup_bitstream(struct lzx_stream *);
3486c95142eSMartin Matuska static int	lzx_decode(struct lzx_stream *, int);
3496c95142eSMartin Matuska static int	lzx_read_pre_tree(struct lzx_stream *);
3506c95142eSMartin Matuska static int	lzx_read_bitlen(struct lzx_stream *, struct huffman *, int);
3516c95142eSMartin Matuska static int	lzx_huffman_init(struct huffman *, size_t, int);
3526c95142eSMartin Matuska static void	lzx_huffman_free(struct huffman *);
3536c95142eSMartin Matuska static int	lzx_make_huffman_table(struct huffman *);
3546c95142eSMartin Matuska static inline int lzx_decode_huffman(struct huffman *, unsigned);
3556c95142eSMartin Matuska static int	lzx_decode_huffman_tree(struct huffman *, unsigned, int);
3566c95142eSMartin Matuska 
3576c95142eSMartin Matuska 
3586c95142eSMartin Matuska int
3596c95142eSMartin Matuska archive_read_support_format_cab(struct archive *_a)
3606c95142eSMartin Matuska {
3616c95142eSMartin Matuska 	struct archive_read *a = (struct archive_read *)_a;
3626c95142eSMartin Matuska 	struct cab *cab;
3636c95142eSMartin Matuska 	int r;
3646c95142eSMartin Matuska 
3656c95142eSMartin Matuska 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
3666c95142eSMartin Matuska 	    ARCHIVE_STATE_NEW, "archive_read_support_format_cab");
3676c95142eSMartin Matuska 
3686c95142eSMartin Matuska 	cab = (struct cab *)calloc(1, sizeof(*cab));
3696c95142eSMartin Matuska 	if (cab == NULL) {
3706c95142eSMartin Matuska 		archive_set_error(&a->archive, ENOMEM,
3716c95142eSMartin Matuska 		    "Can't allocate CAB data");
3726c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
3736c95142eSMartin Matuska 	}
3746c95142eSMartin Matuska 	archive_string_init(&cab->ws);
3756c95142eSMartin Matuska 	archive_wstring_ensure(&cab->ws, 256);
3766c95142eSMartin Matuska 
3776c95142eSMartin Matuska 	r = __archive_read_register_format(a,
3786c95142eSMartin Matuska 	    cab,
3796c95142eSMartin Matuska 	    "cab",
3806c95142eSMartin Matuska 	    archive_read_format_cab_bid,
3816c95142eSMartin Matuska 	    archive_read_format_cab_options,
3826c95142eSMartin Matuska 	    archive_read_format_cab_read_header,
3836c95142eSMartin Matuska 	    archive_read_format_cab_read_data,
3846c95142eSMartin Matuska 	    archive_read_format_cab_read_data_skip,
385acc60b03SMartin Matuska 	    NULL,
386cdf63a70SMartin Matuska 	    archive_read_format_cab_cleanup,
387cdf63a70SMartin Matuska 	    NULL,
388cdf63a70SMartin Matuska 	    NULL);
3896c95142eSMartin Matuska 
3906c95142eSMartin Matuska 	if (r != ARCHIVE_OK)
3916c95142eSMartin Matuska 		free(cab);
3926c95142eSMartin Matuska 	return (ARCHIVE_OK);
3936c95142eSMartin Matuska }
3946c95142eSMartin Matuska 
3956c95142eSMartin Matuska static int
3966c95142eSMartin Matuska find_cab_magic(const char *p)
3976c95142eSMartin Matuska {
3986c95142eSMartin Matuska 	switch (p[4]) {
3996c95142eSMartin Matuska 	case 0:
4006c95142eSMartin Matuska 		/*
4016c95142eSMartin Matuska 		 * Note: Self-Extraction program has 'MSCF' string in their
4026c95142eSMartin Matuska 		 * program. If we were finding 'MSCF' string only, we got
4036c95142eSMartin Matuska 		 * wrong place for Cabinet header, thus, we have to check
4046c95142eSMartin Matuska 		 * following four bytes which are reserved and must be set
4056c95142eSMartin Matuska 		 * to zero.
4066c95142eSMartin Matuska 		 */
4076c95142eSMartin Matuska 		if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
4086c95142eSMartin Matuska 			return 0;
4096c95142eSMartin Matuska 		return 5;
4106c95142eSMartin Matuska 	case 'F': return 1;
4116c95142eSMartin Matuska 	case 'C': return 2;
4126c95142eSMartin Matuska 	case 'S': return 3;
4136c95142eSMartin Matuska 	case 'M': return 4;
4146c95142eSMartin Matuska 	default:  return 5;
4156c95142eSMartin Matuska 	}
4166c95142eSMartin Matuska }
4176c95142eSMartin Matuska 
4186c95142eSMartin Matuska static int
4196c95142eSMartin Matuska archive_read_format_cab_bid(struct archive_read *a, int best_bid)
4206c95142eSMartin Matuska {
4216c95142eSMartin Matuska 	const char *p;
4226c95142eSMartin Matuska 	ssize_t bytes_avail, offset, window;
4236c95142eSMartin Matuska 
4246c95142eSMartin Matuska 	/* If there's already a better bid than we can ever
4256c95142eSMartin Matuska 	   make, don't bother testing. */
4266c95142eSMartin Matuska 	if (best_bid > 64)
4276c95142eSMartin Matuska 		return (-1);
4286c95142eSMartin Matuska 
4296c95142eSMartin Matuska 	if ((p = __archive_read_ahead(a, 8, NULL)) == NULL)
4306c95142eSMartin Matuska 		return (-1);
4316c95142eSMartin Matuska 
4326c95142eSMartin Matuska 	if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
4336c95142eSMartin Matuska 		return (64);
4346c95142eSMartin Matuska 
4356c95142eSMartin Matuska 	/*
4366c95142eSMartin Matuska 	 * Attempt to handle self-extracting archives
4376c95142eSMartin Matuska 	 * by noting a PE header and searching forward
4386c95142eSMartin Matuska 	 * up to 128k for a 'MSCF' marker.
4396c95142eSMartin Matuska 	 */
4406c95142eSMartin Matuska 	if (p[0] == 'M' && p[1] == 'Z') {
4416c95142eSMartin Matuska 		offset = 0;
4426c95142eSMartin Matuska 		window = 4096;
4436c95142eSMartin Matuska 		while (offset < (1024 * 128)) {
4446c95142eSMartin Matuska 			const char *h = __archive_read_ahead(a, offset + window,
4456c95142eSMartin Matuska 			    &bytes_avail);
4466c95142eSMartin Matuska 			if (h == NULL) {
4476c95142eSMartin Matuska 				/* Remaining bytes are less than window. */
4486c95142eSMartin Matuska 				window >>= 1;
4496c95142eSMartin Matuska 				if (window < 128)
4506c95142eSMartin Matuska 					return (0);
4516c95142eSMartin Matuska 				continue;
4526c95142eSMartin Matuska 			}
4536c95142eSMartin Matuska 			p = h + offset;
4546c95142eSMartin Matuska 			while (p + 8 < h + bytes_avail) {
4556c95142eSMartin Matuska 				int next;
4566c95142eSMartin Matuska 				if ((next = find_cab_magic(p)) == 0)
4576c95142eSMartin Matuska 					return (64);
4586c95142eSMartin Matuska 				p += next;
4596c95142eSMartin Matuska 			}
4606c95142eSMartin Matuska 			offset = p - h;
4616c95142eSMartin Matuska 		}
4626c95142eSMartin Matuska 	}
4636c95142eSMartin Matuska 	return (0);
4646c95142eSMartin Matuska }
4656c95142eSMartin Matuska 
4666c95142eSMartin Matuska static int
4676c95142eSMartin Matuska archive_read_format_cab_options(struct archive_read *a,
4686c95142eSMartin Matuska     const char *key, const char *val)
4696c95142eSMartin Matuska {
4706c95142eSMartin Matuska 	struct cab *cab;
4716c95142eSMartin Matuska 	int ret = ARCHIVE_FAILED;
4726c95142eSMartin Matuska 
4736c95142eSMartin Matuska 	cab = (struct cab *)(a->format->data);
4746c95142eSMartin Matuska 	if (strcmp(key, "hdrcharset")  == 0) {
4756c95142eSMartin Matuska 		if (val == NULL || val[0] == 0)
4766c95142eSMartin Matuska 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4776c95142eSMartin Matuska 			    "cab: hdrcharset option needs a character-set name");
4786c95142eSMartin Matuska 		else {
4796c95142eSMartin Matuska 			cab->sconv = archive_string_conversion_from_charset(
4806c95142eSMartin Matuska 			    &a->archive, val, 0);
4816c95142eSMartin Matuska 			if (cab->sconv != NULL)
4826c95142eSMartin Matuska 				ret = ARCHIVE_OK;
4836c95142eSMartin Matuska 			else
4846c95142eSMartin Matuska 				ret = ARCHIVE_FATAL;
4856c95142eSMartin Matuska 		}
4866c95142eSMartin Matuska 		return (ret);
4876c95142eSMartin Matuska 	}
4886c95142eSMartin Matuska 
4896c95142eSMartin Matuska 	/* Note: The "warn" return is just to inform the options
4906c95142eSMartin Matuska 	 * supervisor that we didn't handle it.  It will generate
4916c95142eSMartin Matuska 	 * a suitable error if no one used this option. */
4926c95142eSMartin Matuska 	return (ARCHIVE_WARN);
4936c95142eSMartin Matuska }
4946c95142eSMartin Matuska 
4956c95142eSMartin Matuska static int
4966c95142eSMartin Matuska cab_skip_sfx(struct archive_read *a)
4976c95142eSMartin Matuska {
4986c95142eSMartin Matuska 	const char *p, *q;
4996c95142eSMartin Matuska 	size_t skip;
5006c95142eSMartin Matuska 	ssize_t bytes, window;
5016c95142eSMartin Matuska 
5026c95142eSMartin Matuska 	window = 4096;
5036c95142eSMartin Matuska 	for (;;) {
5046c95142eSMartin Matuska 		const char *h = __archive_read_ahead(a, window, &bytes);
5056c95142eSMartin Matuska 		if (h == NULL) {
5066c95142eSMartin Matuska 			/* Remaining size are less than window. */
5076c95142eSMartin Matuska 			window >>= 1;
5086c95142eSMartin Matuska 			if (window < 128) {
5096c95142eSMartin Matuska 				archive_set_error(&a->archive,
5106c95142eSMartin Matuska 				    ARCHIVE_ERRNO_FILE_FORMAT,
5116c95142eSMartin Matuska 				    "Couldn't find out CAB header");
5126c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
5136c95142eSMartin Matuska 			}
5146c95142eSMartin Matuska 			continue;
5156c95142eSMartin Matuska 		}
5166c95142eSMartin Matuska 		p = h;
5176c95142eSMartin Matuska 		q = p + bytes;
5186c95142eSMartin Matuska 
5196c95142eSMartin Matuska 		/*
5206c95142eSMartin Matuska 		 * Scan ahead until we find something that looks
5216c95142eSMartin Matuska 		 * like the cab header.
5226c95142eSMartin Matuska 		 */
5236c95142eSMartin Matuska 		while (p + 8 < q) {
5246c95142eSMartin Matuska 			int next;
5256c95142eSMartin Matuska 			if ((next = find_cab_magic(p)) == 0) {
5266c95142eSMartin Matuska 				skip = p - h;
5276c95142eSMartin Matuska 				__archive_read_consume(a, skip);
5286c95142eSMartin Matuska 				return (ARCHIVE_OK);
5296c95142eSMartin Matuska 			}
5306c95142eSMartin Matuska 			p += next;
5316c95142eSMartin Matuska 		}
5326c95142eSMartin Matuska 		skip = p - h;
5336c95142eSMartin Matuska 		__archive_read_consume(a, skip);
5346c95142eSMartin Matuska 	}
5356c95142eSMartin Matuska }
5366c95142eSMartin Matuska 
5376c95142eSMartin Matuska static int
5386c95142eSMartin Matuska truncated_error(struct archive_read *a)
5396c95142eSMartin Matuska {
5406c95142eSMartin Matuska 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
5416c95142eSMartin Matuska 	    "Truncated CAB header");
5426c95142eSMartin Matuska 	return (ARCHIVE_FATAL);
5436c95142eSMartin Matuska }
5446c95142eSMartin Matuska 
545acc60b03SMartin Matuska static ssize_t
5466c95142eSMartin Matuska cab_strnlen(const unsigned char *p, size_t maxlen)
5476c95142eSMartin Matuska {
5486c95142eSMartin Matuska 	size_t i;
5496c95142eSMartin Matuska 
5506c95142eSMartin Matuska 	for (i = 0; i <= maxlen; i++) {
5516c95142eSMartin Matuska 		if (p[i] == 0)
5526c95142eSMartin Matuska 			break;
5536c95142eSMartin Matuska 	}
5546c95142eSMartin Matuska 	if (i > maxlen)
5556c95142eSMartin Matuska 		return (-1);/* invalid */
556acc60b03SMartin Matuska 	return ((ssize_t)i);
5576c95142eSMartin Matuska }
5586c95142eSMartin Matuska 
5596c95142eSMartin Matuska /* Read bytes as much as remaining. */
5606c95142eSMartin Matuska static const void *
5616c95142eSMartin Matuska cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail)
5626c95142eSMartin Matuska {
5636c95142eSMartin Matuska 	const void *p;
5646c95142eSMartin Matuska 
5656c95142eSMartin Matuska 	while (min > 0) {
5666c95142eSMartin Matuska 		p = __archive_read_ahead(a, min, avail);
5676c95142eSMartin Matuska 		if (p != NULL)
5686c95142eSMartin Matuska 			return (p);
5696c95142eSMartin Matuska 		min--;
5706c95142eSMartin Matuska 	}
5716c95142eSMartin Matuska 	return (NULL);
5726c95142eSMartin Matuska }
5736c95142eSMartin Matuska 
5746c95142eSMartin Matuska /* Convert a path separator '\' -> '/' */
5756c95142eSMartin Matuska static int
5766c95142eSMartin Matuska cab_convert_path_separator_1(struct archive_string *fn, unsigned char attr)
5776c95142eSMartin Matuska {
5786c95142eSMartin Matuska 	size_t i;
5796c95142eSMartin Matuska 	int mb;
5806c95142eSMartin Matuska 
5816c95142eSMartin Matuska 	/* Easy check if we have '\' in multi-byte string. */
5826c95142eSMartin Matuska 	mb = 0;
5836c95142eSMartin Matuska 	for (i = 0; i < archive_strlen(fn); i++) {
5846c95142eSMartin Matuska 		if (fn->s[i] == '\\') {
5856c95142eSMartin Matuska 			if (mb) {
5866c95142eSMartin Matuska 				/* This may be second byte of multi-byte
5876c95142eSMartin Matuska 				 * character. */
5886c95142eSMartin Matuska 				break;
5896c95142eSMartin Matuska 			}
5906c95142eSMartin Matuska 			fn->s[i] = '/';
5916c95142eSMartin Matuska 			mb = 0;
5926c95142eSMartin Matuska 		} else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF))
5936c95142eSMartin Matuska 			mb = 1;
5946c95142eSMartin Matuska 		else
5956c95142eSMartin Matuska 			mb = 0;
5966c95142eSMartin Matuska 	}
5976c95142eSMartin Matuska 	if (i == archive_strlen(fn))
5986c95142eSMartin Matuska 		return (0);
5996c95142eSMartin Matuska 	return (-1);
6006c95142eSMartin Matuska }
6016c95142eSMartin Matuska 
6026c95142eSMartin Matuska /*
6036c95142eSMartin Matuska  * Replace a character '\' with '/' in wide character.
6046c95142eSMartin Matuska  */
6056c95142eSMartin Matuska static void
6066c95142eSMartin Matuska cab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry)
6076c95142eSMartin Matuska {
6086c95142eSMartin Matuska 	const wchar_t *wp;
6096c95142eSMartin Matuska 	size_t i;
6106c95142eSMartin Matuska 
6116c95142eSMartin Matuska 	/* If a conversion to wide character failed, force the replacement. */
6126c95142eSMartin Matuska 	if ((wp = archive_entry_pathname_w(entry)) != NULL) {
6136c95142eSMartin Matuska 		archive_wstrcpy(&(cab->ws), wp);
6146c95142eSMartin Matuska 		for (i = 0; i < archive_strlen(&(cab->ws)); i++) {
6156c95142eSMartin Matuska 			if (cab->ws.s[i] == L'\\')
6166c95142eSMartin Matuska 				cab->ws.s[i] = L'/';
6176c95142eSMartin Matuska 		}
6186c95142eSMartin Matuska 		archive_entry_copy_pathname_w(entry, cab->ws.s);
6196c95142eSMartin Matuska 	}
6206c95142eSMartin Matuska }
6216c95142eSMartin Matuska 
6226c95142eSMartin Matuska /*
6236c95142eSMartin Matuska  * Read CFHEADER, CFFOLDER and CFFILE.
6246c95142eSMartin Matuska  */
6256c95142eSMartin Matuska static int
6266c95142eSMartin Matuska cab_read_header(struct archive_read *a)
6276c95142eSMartin Matuska {
6286c95142eSMartin Matuska 	const unsigned char *p;
6296c95142eSMartin Matuska 	struct cab *cab;
6306c95142eSMartin Matuska 	struct cfheader *hd;
6316c95142eSMartin Matuska 	size_t bytes, used;
632acc60b03SMartin Matuska 	ssize_t len;
6336c95142eSMartin Matuska 	int64_t skip;
634acc60b03SMartin Matuska 	int err, i;
6356c95142eSMartin Matuska 	int cur_folder, prev_folder;
6366c95142eSMartin Matuska 	uint32_t offset32;
6376c95142eSMartin Matuska 
6386c95142eSMartin Matuska 	a->archive.archive_format = ARCHIVE_FORMAT_CAB;
6396c95142eSMartin Matuska 	if (a->archive.archive_format_name == NULL)
6406c95142eSMartin Matuska 		a->archive.archive_format_name = "CAB";
6416c95142eSMartin Matuska 
6426c95142eSMartin Matuska 	if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
6436c95142eSMartin Matuska 		return (truncated_error(a));
6446c95142eSMartin Matuska 
6456c95142eSMartin Matuska 	cab = (struct cab *)(a->format->data);
6466c95142eSMartin Matuska 	if (cab->found_header == 0 &&
6476c95142eSMartin Matuska 	    p[0] == 'M' && p[1] == 'Z') {
6486c95142eSMartin Matuska 		/* This is an executable?  Must be self-extracting... */
6496c95142eSMartin Matuska 		err = cab_skip_sfx(a);
6506c95142eSMartin Matuska 		if (err < ARCHIVE_WARN)
6516c95142eSMartin Matuska 			return (err);
6526c95142eSMartin Matuska 
653c4247af4SMartin Matuska 		/* Re-read header after processing the SFX. */
654c4247af4SMartin Matuska 		if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
6556c95142eSMartin Matuska 			return (truncated_error(a));
6566c95142eSMartin Matuska 	}
6576c95142eSMartin Matuska 
6586c95142eSMartin Matuska 	cab->cab_offset = 0;
6596c95142eSMartin Matuska 	/*
6606c95142eSMartin Matuska 	 * Read CFHEADER.
6616c95142eSMartin Matuska 	 */
6626c95142eSMartin Matuska 	hd = &cab->cfheader;
6636c95142eSMartin Matuska 	if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' ||
6646c95142eSMartin Matuska 	    p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') {
6656c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
6666c95142eSMartin Matuska 		    "Couldn't find out CAB header");
6676c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
6686c95142eSMartin Matuska 	}
6696c95142eSMartin Matuska 	hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet);
6706c95142eSMartin Matuska 	hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles);
6716c95142eSMartin Matuska 	hd->minor = p[CFHEADER_versionMinor];
6726c95142eSMartin Matuska 	hd->major = p[CFHEADER_versionMajor];
6736c95142eSMartin Matuska 	hd->folder_count = archive_le16dec(p + CFHEADER_cFolders);
6746c95142eSMartin Matuska 	if (hd->folder_count == 0)
6756c95142eSMartin Matuska 		goto invalid;
6766c95142eSMartin Matuska 	hd->file_count = archive_le16dec(p + CFHEADER_cFiles);
6776c95142eSMartin Matuska 	if (hd->file_count == 0)
6786c95142eSMartin Matuska 		goto invalid;
6796c95142eSMartin Matuska 	hd->flags = archive_le16dec(p + CFHEADER_flags);
6806c95142eSMartin Matuska 	hd->setid = archive_le16dec(p + CFHEADER_setID);
6816c95142eSMartin Matuska 	hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet);
6826c95142eSMartin Matuska 	used = CFHEADER_iCabinet + 2;
6836c95142eSMartin Matuska 	if (hd->flags & RESERVE_PRESENT) {
6846c95142eSMartin Matuska 		uint16_t cfheader;
6856c95142eSMartin Matuska 		cfheader = archive_le16dec(p + CFHEADER_cbCFHeader);
6866c95142eSMartin Matuska 		if (cfheader > 60000U)
6876c95142eSMartin Matuska 			goto invalid;
6886c95142eSMartin Matuska 		hd->cffolder = p[CFHEADER_cbCFFolder];
6896c95142eSMartin Matuska 		hd->cfdata = p[CFHEADER_cbCFData];
6906c95142eSMartin Matuska 		used += 4;/* cbCFHeader, cbCFFolder and cbCFData */
6916c95142eSMartin Matuska 		used += cfheader;/* abReserve */
6926c95142eSMartin Matuska 	} else
6936c95142eSMartin Matuska 		hd->cffolder = 0;/* Avoid compiling warning. */
6946c95142eSMartin Matuska 	if (hd->flags & PREV_CABINET) {
6956c95142eSMartin Matuska 		/* How many bytes are used for szCabinetPrev. */
6966c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
6976c95142eSMartin Matuska 			return (truncated_error(a));
6986c95142eSMartin Matuska 		if ((len = cab_strnlen(p + used, 255)) <= 0)
6996c95142eSMartin Matuska 			goto invalid;
7006c95142eSMartin Matuska 		used += len + 1;
7016c95142eSMartin Matuska 		/* How many bytes are used for szDiskPrev. */
7026c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
7036c95142eSMartin Matuska 			return (truncated_error(a));
7046c95142eSMartin Matuska 		if ((len = cab_strnlen(p + used, 255)) <= 0)
7056c95142eSMartin Matuska 			goto invalid;
7066c95142eSMartin Matuska 		used += len + 1;
7076c95142eSMartin Matuska 	}
7086c95142eSMartin Matuska 	if (hd->flags & NEXT_CABINET) {
7096c95142eSMartin Matuska 		/* How many bytes are used for szCabinetNext. */
7106c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
7116c95142eSMartin Matuska 			return (truncated_error(a));
7126c95142eSMartin Matuska 		if ((len = cab_strnlen(p + used, 255)) <= 0)
7136c95142eSMartin Matuska 			goto invalid;
7146c95142eSMartin Matuska 		used += len + 1;
7156c95142eSMartin Matuska 		/* How many bytes are used for szDiskNext. */
7166c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
7176c95142eSMartin Matuska 			return (truncated_error(a));
7186c95142eSMartin Matuska 		if ((len = cab_strnlen(p + used, 255)) <= 0)
7196c95142eSMartin Matuska 			goto invalid;
7206c95142eSMartin Matuska 		used += len + 1;
7216c95142eSMartin Matuska 	}
7226c95142eSMartin Matuska 	__archive_read_consume(a, used);
7236c95142eSMartin Matuska 	cab->cab_offset += used;
7246c95142eSMartin Matuska 	used = 0;
7256c95142eSMartin Matuska 
7266c95142eSMartin Matuska 	/*
7276c95142eSMartin Matuska 	 * Read CFFOLDER.
7286c95142eSMartin Matuska 	 */
7296c95142eSMartin Matuska 	hd->folder_array = (struct cffolder *)calloc(
7306c95142eSMartin Matuska 	    hd->folder_count, sizeof(struct cffolder));
7316c95142eSMartin Matuska 	if (hd->folder_array == NULL)
7326c95142eSMartin Matuska 		goto nomem;
7336c95142eSMartin Matuska 
7346c95142eSMartin Matuska 	bytes = 8;
7356c95142eSMartin Matuska 	if (hd->flags & RESERVE_PRESENT)
7366c95142eSMartin Matuska 		bytes += hd->cffolder;
7376c95142eSMartin Matuska 	bytes *= hd->folder_count;
7386c95142eSMartin Matuska 	if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL)
7396c95142eSMartin Matuska 		return (truncated_error(a));
7406c95142eSMartin Matuska 	offset32 = 0;
7416c95142eSMartin Matuska 	for (i = 0; i < hd->folder_count; i++) {
7426c95142eSMartin Matuska 		struct cffolder *folder = &(hd->folder_array[i]);
7436c95142eSMartin Matuska 		folder->cfdata_offset_in_cab =
7446c95142eSMartin Matuska 		    archive_le32dec(p + CFFOLDER_coffCabStart);
7456c95142eSMartin Matuska 		folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData);
7466c95142eSMartin Matuska 		folder->comptype =
7476c95142eSMartin Matuska 		    archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F;
7486c95142eSMartin Matuska 		folder->compdata =
7496c95142eSMartin Matuska 		    archive_le16dec(p+CFFOLDER_typeCompress) >> 8;
7506c95142eSMartin Matuska 		/* Get a compression name. */
7516c95142eSMartin Matuska 		if (folder->comptype <
7526c95142eSMartin Matuska 		    sizeof(compression_name) / sizeof(compression_name[0]))
7536c95142eSMartin Matuska 			folder->compname = compression_name[folder->comptype];
7546c95142eSMartin Matuska 		else
7556c95142eSMartin Matuska 			folder->compname = "UNKNOWN";
7566c95142eSMartin Matuska 		p += 8;
7576c95142eSMartin Matuska 		used += 8;
7586c95142eSMartin Matuska 		if (hd->flags & RESERVE_PRESENT) {
7596c95142eSMartin Matuska 			p += hd->cffolder;/* abReserve */
7606c95142eSMartin Matuska 			used += hd->cffolder;
7616c95142eSMartin Matuska 		}
7626c95142eSMartin Matuska 		/*
7636c95142eSMartin Matuska 		 * Sanity check if each data is acceptable.
7646c95142eSMartin Matuska 		 */
7656c95142eSMartin Matuska 		if (offset32 >= folder->cfdata_offset_in_cab)
7666c95142eSMartin Matuska 			goto invalid;
7676c95142eSMartin Matuska 		offset32 = folder->cfdata_offset_in_cab;
7686c95142eSMartin Matuska 
7696c95142eSMartin Matuska 		/* Set a request to initialize zlib for the CFDATA of
7706c95142eSMartin Matuska 		 * this folder. */
7716c95142eSMartin Matuska 		folder->decompress_init = 0;
7726c95142eSMartin Matuska 	}
7736c95142eSMartin Matuska 	__archive_read_consume(a, used);
7746c95142eSMartin Matuska 	cab->cab_offset += used;
7756c95142eSMartin Matuska 
7766c95142eSMartin Matuska 	/*
7776c95142eSMartin Matuska 	 * Read CFFILE.
7786c95142eSMartin Matuska 	 */
7796c95142eSMartin Matuska 	/* Seek read pointer to the offset of CFFILE if needed. */
7806c95142eSMartin Matuska 	skip = (int64_t)hd->files_offset - cab->cab_offset;
7816c95142eSMartin Matuska 	if (skip <  0) {
7826c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7836c95142eSMartin Matuska 		    "Invalid offset of CFFILE %jd < %jd",
7846c95142eSMartin Matuska 		    (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset);
7856c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
7866c95142eSMartin Matuska 	}
7876c95142eSMartin Matuska 	if (skip) {
7886c95142eSMartin Matuska 		__archive_read_consume(a, skip);
7896c95142eSMartin Matuska 		cab->cab_offset += skip;
7906c95142eSMartin Matuska 	}
7916c95142eSMartin Matuska 	/* Allocate memory for CFDATA */
7926c95142eSMartin Matuska 	hd->file_array = (struct cffile *)calloc(
7936c95142eSMartin Matuska 	    hd->file_count, sizeof(struct cffile));
7946c95142eSMartin Matuska 	if (hd->file_array == NULL)
7956c95142eSMartin Matuska 		goto nomem;
7966c95142eSMartin Matuska 
7976c95142eSMartin Matuska 	prev_folder = -1;
7986c95142eSMartin Matuska 	for (i = 0; i < hd->file_count; i++) {
7996c95142eSMartin Matuska 		struct cffile *file = &(hd->file_array[i]);
8006c95142eSMartin Matuska 		ssize_t avail;
8016c95142eSMartin Matuska 
8026c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, 16, NULL)) == NULL)
8036c95142eSMartin Matuska 			return (truncated_error(a));
8046c95142eSMartin Matuska 		file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile);
8056c95142eSMartin Matuska 		file->offset = archive_le32dec(p + CFFILE_uoffFolderStart);
8066c95142eSMartin Matuska 		file->folder = archive_le16dec(p + CFFILE_iFolder);
8076c95142eSMartin Matuska 		file->mtime = cab_dos_time(p + CFFILE_date_time);
808fd082e96SMartin Matuska 		file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs);
8096c95142eSMartin Matuska 		__archive_read_consume(a, 16);
8106c95142eSMartin Matuska 
8116c95142eSMartin Matuska 		cab->cab_offset += 16;
8126c95142eSMartin Matuska 		if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL)
8136c95142eSMartin Matuska 			return (truncated_error(a));
8146c95142eSMartin Matuska 		if ((len = cab_strnlen(p, avail-1)) <= 0)
8156c95142eSMartin Matuska 			goto invalid;
8166c95142eSMartin Matuska 
8176c95142eSMartin Matuska 		/* Copy a pathname.  */
8186c95142eSMartin Matuska 		archive_string_init(&(file->pathname));
8196c95142eSMartin Matuska 		archive_strncpy(&(file->pathname), p, len);
8206c95142eSMartin Matuska 		__archive_read_consume(a, len + 1);
8216c95142eSMartin Matuska 		cab->cab_offset += len + 1;
8226c95142eSMartin Matuska 
8236c95142eSMartin Matuska 		/*
8246c95142eSMartin Matuska 		 * Sanity check if each data is acceptable.
8256c95142eSMartin Matuska 		 */
8266c95142eSMartin Matuska 		if (file->uncompressed_size > 0x7FFF8000)
8276c95142eSMartin Matuska 			goto invalid;/* Too large */
8286c95142eSMartin Matuska 		if ((int64_t)file->offset + (int64_t)file->uncompressed_size
8296c95142eSMartin Matuska 		    > ARCHIVE_LITERAL_LL(0x7FFF8000))
8306c95142eSMartin Matuska 			goto invalid;/* Too large */
8316c95142eSMartin Matuska 		switch (file->folder) {
8326c95142eSMartin Matuska 		case iFoldCONTINUED_TO_NEXT:
8336c95142eSMartin Matuska 			/* This must be last file in a folder. */
8346c95142eSMartin Matuska 			if (i != hd->file_count -1)
8356c95142eSMartin Matuska 				goto invalid;
8366c95142eSMartin Matuska 			cur_folder = hd->folder_count -1;
8376c95142eSMartin Matuska 			break;
8386c95142eSMartin Matuska 		case iFoldCONTINUED_PREV_AND_NEXT:
8396c95142eSMartin Matuska 			/* This must be only one file in a folder. */
8406c95142eSMartin Matuska 			if (hd->file_count != 1)
8416c95142eSMartin Matuska 				goto invalid;
8426c95142eSMartin Matuska 			/* FALL THROUGH */
8436c95142eSMartin Matuska 		case iFoldCONTINUED_FROM_PREV:
8446c95142eSMartin Matuska 			/* This must be first file in a folder. */
8456c95142eSMartin Matuska 			if (i != 0)
8466c95142eSMartin Matuska 				goto invalid;
8476c95142eSMartin Matuska 			prev_folder = cur_folder = 0;
8486c95142eSMartin Matuska 			offset32 = file->offset;
8496c95142eSMartin Matuska 			break;
8506c95142eSMartin Matuska 		default:
8516c95142eSMartin Matuska 			if (file->folder >= hd->folder_count)
8526c95142eSMartin Matuska 				goto invalid;
8536c95142eSMartin Matuska 			cur_folder = file->folder;
8546c95142eSMartin Matuska 			break;
8556c95142eSMartin Matuska 		}
8566c95142eSMartin Matuska 		/* Dot not back track. */
8576c95142eSMartin Matuska 		if (cur_folder < prev_folder)
8586c95142eSMartin Matuska 			goto invalid;
8596c95142eSMartin Matuska 		if (cur_folder != prev_folder)
8606c95142eSMartin Matuska 			offset32 = 0;
8616c95142eSMartin Matuska 		prev_folder = cur_folder;
8626c95142eSMartin Matuska 
8636c95142eSMartin Matuska 		/* Make sure there are not any blanks from last file
8646c95142eSMartin Matuska 		 * contents. */
8656c95142eSMartin Matuska 		if (offset32 != file->offset)
8666c95142eSMartin Matuska 			goto invalid;
8676c95142eSMartin Matuska 		offset32 += file->uncompressed_size;
8686c95142eSMartin Matuska 
8696c95142eSMartin Matuska 		/* CFDATA is available for file contents. */
8706c95142eSMartin Matuska 		if (file->uncompressed_size > 0 &&
8716c95142eSMartin Matuska 		    hd->folder_array[cur_folder].cfdata_count == 0)
8726c95142eSMartin Matuska 			goto invalid;
8736c95142eSMartin Matuska 	}
8746c95142eSMartin Matuska 
8756c95142eSMartin Matuska 	if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) {
8766c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
8776c95142eSMartin Matuska 		    "Multivolume cabinet file is unsupported");
8786c95142eSMartin Matuska 		return (ARCHIVE_WARN);
8796c95142eSMartin Matuska 	}
8806c95142eSMartin Matuska 	return (ARCHIVE_OK);
8816c95142eSMartin Matuska invalid:
8826c95142eSMartin Matuska 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
8836c95142eSMartin Matuska 	    "Invalid CAB header");
8846c95142eSMartin Matuska 	return (ARCHIVE_FATAL);
8856c95142eSMartin Matuska nomem:
8866c95142eSMartin Matuska 	archive_set_error(&a->archive, ENOMEM,
8876c95142eSMartin Matuska 	    "Can't allocate memory for CAB data");
8886c95142eSMartin Matuska 	return (ARCHIVE_FATAL);
8896c95142eSMartin Matuska }
8906c95142eSMartin Matuska 
8916c95142eSMartin Matuska static int
8926c95142eSMartin Matuska archive_read_format_cab_read_header(struct archive_read *a,
8936c95142eSMartin Matuska     struct archive_entry *entry)
8946c95142eSMartin Matuska {
8956c95142eSMartin Matuska 	struct cab *cab;
8966c95142eSMartin Matuska 	struct cfheader *hd;
8976c95142eSMartin Matuska 	struct cffolder *prev_folder;
8986c95142eSMartin Matuska 	struct cffile *file;
8996c95142eSMartin Matuska 	struct archive_string_conv *sconv;
9006c95142eSMartin Matuska 	int err = ARCHIVE_OK, r;
9016c95142eSMartin Matuska 
9026c95142eSMartin Matuska 	cab = (struct cab *)(a->format->data);
9036c95142eSMartin Matuska 	if (cab->found_header == 0) {
9046c95142eSMartin Matuska 		err = cab_read_header(a);
9056c95142eSMartin Matuska 		if (err < ARCHIVE_WARN)
9066c95142eSMartin Matuska 			return (err);
9076c95142eSMartin Matuska 		/* We've found the header. */
9086c95142eSMartin Matuska 		cab->found_header = 1;
9096c95142eSMartin Matuska 	}
9106c95142eSMartin Matuska 	hd = &cab->cfheader;
9116c95142eSMartin Matuska 
9126c95142eSMartin Matuska 	if (hd->file_index >= hd->file_count) {
9136c95142eSMartin Matuska 		cab->end_of_archive = 1;
9146c95142eSMartin Matuska 		return (ARCHIVE_EOF);
9156c95142eSMartin Matuska 	}
9166c95142eSMartin Matuska 	file = &hd->file_array[hd->file_index++];
9176c95142eSMartin Matuska 
9186c95142eSMartin Matuska 	cab->end_of_entry = 0;
9196c95142eSMartin Matuska 	cab->end_of_entry_cleanup = 0;
9206c95142eSMartin Matuska 	cab->entry_compressed_bytes_read = 0;
9216c95142eSMartin Matuska 	cab->entry_uncompressed_bytes_read = 0;
9226c95142eSMartin Matuska 	cab->entry_unconsumed = 0;
9236c95142eSMartin Matuska 	cab->entry_cffile = file;
9246c95142eSMartin Matuska 
9256c95142eSMartin Matuska 	/*
9266c95142eSMartin Matuska 	 * Choose a proper folder.
9276c95142eSMartin Matuska 	 */
9286c95142eSMartin Matuska 	prev_folder = cab->entry_cffolder;
9296c95142eSMartin Matuska 	switch (file->folder) {
9306c95142eSMartin Matuska 	case iFoldCONTINUED_FROM_PREV:
9316c95142eSMartin Matuska 	case iFoldCONTINUED_PREV_AND_NEXT:
9326c95142eSMartin Matuska 		cab->entry_cffolder = &hd->folder_array[0];
9336c95142eSMartin Matuska 		break;
9346c95142eSMartin Matuska 	case iFoldCONTINUED_TO_NEXT:
9356c95142eSMartin Matuska 		cab->entry_cffolder = &hd->folder_array[hd->folder_count-1];
9366c95142eSMartin Matuska 		break;
9376c95142eSMartin Matuska 	default:
9386c95142eSMartin Matuska 		cab->entry_cffolder = &hd->folder_array[file->folder];
9396c95142eSMartin Matuska 		break;
9406c95142eSMartin Matuska 	}
9416c95142eSMartin Matuska 	/* If a cffolder of this file is changed, reset a cfdata to read
9426c95142eSMartin Matuska 	 * file contents from next cfdata. */
9436c95142eSMartin Matuska 	if (prev_folder != cab->entry_cffolder)
9446c95142eSMartin Matuska 		cab->entry_cfdata = NULL;
9456c95142eSMartin Matuska 
9466c95142eSMartin Matuska 	/* If a pathname is UTF-8, prepare a string conversion object
9476c95142eSMartin Matuska 	 * for UTF-8 and use it. */
9486c95142eSMartin Matuska 	if (file->attr & ATTR_NAME_IS_UTF) {
9496c95142eSMartin Matuska 		if (cab->sconv_utf8 == NULL) {
9506c95142eSMartin Matuska 			cab->sconv_utf8 =
9516c95142eSMartin Matuska 			    archive_string_conversion_from_charset(
9526c95142eSMartin Matuska 				&(a->archive), "UTF-8", 1);
9536c95142eSMartin Matuska 			if (cab->sconv_utf8 == NULL)
9546c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
9556c95142eSMartin Matuska 		}
9566c95142eSMartin Matuska 		sconv = cab->sconv_utf8;
9576c95142eSMartin Matuska 	} else if (cab->sconv != NULL) {
9586c95142eSMartin Matuska 		/* Choose the conversion specified by the option. */
9596c95142eSMartin Matuska 		sconv = cab->sconv;
9606c95142eSMartin Matuska 	} else {
9616c95142eSMartin Matuska 		/* Choose the default conversion. */
9626c95142eSMartin Matuska 		if (!cab->init_default_conversion) {
9636c95142eSMartin Matuska 			cab->sconv_default =
9646c95142eSMartin Matuska 			    archive_string_default_conversion_for_read(
9656c95142eSMartin Matuska 			      &(a->archive));
9666c95142eSMartin Matuska 			cab->init_default_conversion = 1;
9676c95142eSMartin Matuska 		}
9686c95142eSMartin Matuska 		sconv = cab->sconv_default;
9696c95142eSMartin Matuska 	}
9706c95142eSMartin Matuska 
9716c95142eSMartin Matuska 	/*
9726c95142eSMartin Matuska 	 * Set a default value and common data
9736c95142eSMartin Matuska 	 */
9746c95142eSMartin Matuska 	r = cab_convert_path_separator_1(&(file->pathname), file->attr);
9756c95142eSMartin Matuska 	if (archive_entry_copy_pathname_l(entry, file->pathname.s,
9766c95142eSMartin Matuska 	    archive_strlen(&(file->pathname)), sconv) != 0) {
9776c95142eSMartin Matuska 		if (errno == ENOMEM) {
9786c95142eSMartin Matuska 			archive_set_error(&a->archive, ENOMEM,
9796c95142eSMartin Matuska 			    "Can't allocate memory for Pathname");
9806c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
9816c95142eSMartin Matuska 		}
9826c95142eSMartin Matuska 		archive_set_error(&a->archive,
9836c95142eSMartin Matuska 		    ARCHIVE_ERRNO_FILE_FORMAT,
9846c95142eSMartin Matuska 		    "Pathname cannot be converted "
9856c95142eSMartin Matuska 		    "from %s to current locale.",
9866c95142eSMartin Matuska 		    archive_string_conversion_charset_name(sconv));
9876c95142eSMartin Matuska 		err = ARCHIVE_WARN;
9886c95142eSMartin Matuska 	}
9896c95142eSMartin Matuska 	if (r < 0) {
9906c95142eSMartin Matuska 		/* Convert a path separator '\' -> '/' */
9916c95142eSMartin Matuska 		cab_convert_path_separator_2(cab, entry);
9926c95142eSMartin Matuska 	}
9936c95142eSMartin Matuska 
9946c95142eSMartin Matuska 	archive_entry_set_size(entry, file->uncompressed_size);
9956c95142eSMartin Matuska 	if (file->attr & ATTR_RDONLY)
9966c95142eSMartin Matuska 		archive_entry_set_mode(entry, AE_IFREG | 0555);
9976c95142eSMartin Matuska 	else
998fd082e96SMartin Matuska 		archive_entry_set_mode(entry, AE_IFREG | 0666);
9996c95142eSMartin Matuska 	archive_entry_set_mtime(entry, file->mtime, 0);
10006c95142eSMartin Matuska 
10016c95142eSMartin Matuska 	cab->entry_bytes_remaining = file->uncompressed_size;
10026c95142eSMartin Matuska 	cab->entry_offset = 0;
10036c95142eSMartin Matuska 	/* We don't need compress data. */
10046c95142eSMartin Matuska 	if (file->uncompressed_size == 0)
10056c95142eSMartin Matuska 		cab->end_of_entry_cleanup = cab->end_of_entry = 1;
10066c95142eSMartin Matuska 
10076c95142eSMartin Matuska 	/* Set up a more descriptive format name. */
10086c95142eSMartin Matuska 	sprintf(cab->format_name, "CAB %d.%d (%s)",
10096c95142eSMartin Matuska 	    hd->major, hd->minor, cab->entry_cffolder->compname);
10106c95142eSMartin Matuska 	a->archive.archive_format_name = cab->format_name;
10116c95142eSMartin Matuska 
10126c95142eSMartin Matuska 	return (err);
10136c95142eSMartin Matuska }
10146c95142eSMartin Matuska 
10156c95142eSMartin Matuska static int
10166c95142eSMartin Matuska archive_read_format_cab_read_data(struct archive_read *a,
10176c95142eSMartin Matuska     const void **buff, size_t *size, int64_t *offset)
10186c95142eSMartin Matuska {
10196c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
10206c95142eSMartin Matuska 	int r;
10216c95142eSMartin Matuska 
10226c95142eSMartin Matuska 	switch (cab->entry_cffile->folder) {
10236c95142eSMartin Matuska 	case iFoldCONTINUED_FROM_PREV:
10246c95142eSMartin Matuska 	case iFoldCONTINUED_TO_NEXT:
10256c95142eSMartin Matuska 	case iFoldCONTINUED_PREV_AND_NEXT:
10266c95142eSMartin Matuska 		*buff = NULL;
10276c95142eSMartin Matuska 		*size = 0;
10286c95142eSMartin Matuska 		*offset = 0;
10296c95142eSMartin Matuska 		archive_clear_error(&a->archive);
10306c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
10316c95142eSMartin Matuska 		    "Cannot restore this file split in multivolume.");
10326c95142eSMartin Matuska 		return (ARCHIVE_FAILED);
10336c95142eSMartin Matuska 	default:
10346c95142eSMartin Matuska 		break;
10356c95142eSMartin Matuska 	}
1036fd082e96SMartin Matuska 	if (cab->read_data_invoked == 0) {
1037fd082e96SMartin Matuska 		if (cab->bytes_skipped) {
1038fd082e96SMartin Matuska 			if (cab->entry_cfdata == NULL) {
1039fd082e96SMartin Matuska 				r = cab_next_cfdata(a);
1040fd082e96SMartin Matuska 				if (r < 0)
1041fd082e96SMartin Matuska 					return (r);
1042fd082e96SMartin Matuska 			}
1043fd082e96SMartin Matuska 			if (cab_consume_cfdata(a, cab->bytes_skipped) < 0)
1044fd082e96SMartin Matuska 				return (ARCHIVE_FATAL);
1045fd082e96SMartin Matuska 			cab->bytes_skipped = 0;
1046fd082e96SMartin Matuska 		}
1047fd082e96SMartin Matuska 		cab->read_data_invoked = 1;
1048fd082e96SMartin Matuska 	}
10496c95142eSMartin Matuska 	if (cab->entry_unconsumed) {
10506c95142eSMartin Matuska 		/* Consume as much as the compressor actually used. */
1051fd082e96SMartin Matuska 		r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
10526c95142eSMartin Matuska 		cab->entry_unconsumed = 0;
10536c95142eSMartin Matuska 		if (r < 0)
10546c95142eSMartin Matuska 			return (r);
10556c95142eSMartin Matuska 	}
10566c95142eSMartin Matuska 	if (cab->end_of_archive || cab->end_of_entry) {
10576c95142eSMartin Matuska 		if (!cab->end_of_entry_cleanup) {
10586c95142eSMartin Matuska 			/* End-of-entry cleanup done. */
10596c95142eSMartin Matuska 			cab->end_of_entry_cleanup = 1;
10606c95142eSMartin Matuska 		}
10616c95142eSMartin Matuska 		*offset = cab->entry_offset;
10626c95142eSMartin Matuska 		*size = 0;
10636c95142eSMartin Matuska 		*buff = NULL;
10646c95142eSMartin Matuska 		return (ARCHIVE_EOF);
10656c95142eSMartin Matuska 	}
10666c95142eSMartin Matuska 
10676c95142eSMartin Matuska 	return (cab_read_data(a, buff, size, offset));
10686c95142eSMartin Matuska }
10696c95142eSMartin Matuska 
10706c95142eSMartin Matuska static uint32_t
10716c95142eSMartin Matuska cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
10726c95142eSMartin Matuska {
10736c95142eSMartin Matuska 	const unsigned char *b;
1074acc60b03SMartin Matuska 	unsigned u32num;
10756c95142eSMartin Matuska 	uint32_t sum;
10766c95142eSMartin Matuska 
1077acc60b03SMartin Matuska 	u32num = (unsigned)bytes / 4;
10786c95142eSMartin Matuska 	sum = seed;
10796c95142eSMartin Matuska 	b = p;
1080acc60b03SMartin Matuska 	for (;u32num > 0; --u32num) {
10816c95142eSMartin Matuska 		sum ^= archive_le32dec(b);
10826c95142eSMartin Matuska 		b += 4;
10836c95142eSMartin Matuska 	}
10846c95142eSMartin Matuska 	return (sum);
10856c95142eSMartin Matuska }
10866c95142eSMartin Matuska 
10876c95142eSMartin Matuska static uint32_t
10886c95142eSMartin Matuska cab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed)
10896c95142eSMartin Matuska {
10906c95142eSMartin Matuska 	const unsigned char *b;
10916c95142eSMartin Matuska 	uint32_t sum;
10926c95142eSMartin Matuska 	uint32_t t;
10936c95142eSMartin Matuska 
10946c95142eSMartin Matuska 	sum = cab_checksum_cfdata_4(p, bytes, seed);
10956c95142eSMartin Matuska 	b = p;
10966c95142eSMartin Matuska 	b += bytes & ~3;
10976c95142eSMartin Matuska 	t = 0;
10986c95142eSMartin Matuska 	switch (bytes & 3) {
10996c95142eSMartin Matuska 	case 3:
11006c95142eSMartin Matuska 		t |= ((uint32_t)(*b++)) << 16;
11016c95142eSMartin Matuska 		/* FALL THROUGH */
11026c95142eSMartin Matuska 	case 2:
11036c95142eSMartin Matuska 		t |= ((uint32_t)(*b++)) << 8;
11046c95142eSMartin Matuska 		/* FALL THROUGH */
11056c95142eSMartin Matuska 	case 1:
11066c95142eSMartin Matuska 		t |= *b;
11076c95142eSMartin Matuska 		/* FALL THROUGH */
11086c95142eSMartin Matuska 	default:
11096c95142eSMartin Matuska 		break;
11106c95142eSMartin Matuska 	}
11116c95142eSMartin Matuska 	sum ^= t;
11126c95142eSMartin Matuska 
11136c95142eSMartin Matuska 	return (sum);
11146c95142eSMartin Matuska }
11156c95142eSMartin Matuska 
11166c95142eSMartin Matuska static void
11176c95142eSMartin Matuska cab_checksum_update(struct archive_read *a, size_t bytes)
11186c95142eSMartin Matuska {
11196c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
11206c95142eSMartin Matuska 	struct cfdata *cfdata = cab->entry_cfdata;
11216c95142eSMartin Matuska 	const unsigned char *p;
11226c95142eSMartin Matuska 	size_t sumbytes;
11236c95142eSMartin Matuska 
11246c95142eSMartin Matuska 	if (cfdata->sum == 0 || cfdata->sum_ptr == NULL)
11256c95142eSMartin Matuska 		return;
11266c95142eSMartin Matuska 	/*
11276c95142eSMartin Matuska 	 * Calculate the sum of this CFDATA.
11286c95142eSMartin Matuska 	 * Make sure CFDATA must be calculated in four bytes.
11296c95142eSMartin Matuska 	 */
11306c95142eSMartin Matuska 	p = cfdata->sum_ptr;
11316c95142eSMartin Matuska 	sumbytes = bytes;
11326c95142eSMartin Matuska 	if (cfdata->sum_extra_avail) {
11336c95142eSMartin Matuska 		while (cfdata->sum_extra_avail < 4 && sumbytes > 0) {
11346c95142eSMartin Matuska 			cfdata->sum_extra[
11356c95142eSMartin Matuska 			    cfdata->sum_extra_avail++] = *p++;
11366c95142eSMartin Matuska 			sumbytes--;
11376c95142eSMartin Matuska 		}
11386c95142eSMartin Matuska 		if (cfdata->sum_extra_avail == 4) {
11396c95142eSMartin Matuska 			cfdata->sum_calculated = cab_checksum_cfdata_4(
11406c95142eSMartin Matuska 			    cfdata->sum_extra, 4, cfdata->sum_calculated);
11416c95142eSMartin Matuska 			cfdata->sum_extra_avail = 0;
11426c95142eSMartin Matuska 		}
11436c95142eSMartin Matuska 	}
11446c95142eSMartin Matuska 	if (sumbytes) {
11456c95142eSMartin Matuska 		int odd = sumbytes & 3;
11466c95142eSMartin Matuska 		if (sumbytes - odd > 0)
11476c95142eSMartin Matuska 			cfdata->sum_calculated = cab_checksum_cfdata_4(
11486c95142eSMartin Matuska 			    p, sumbytes - odd, cfdata->sum_calculated);
11496c95142eSMartin Matuska 		if (odd)
11506c95142eSMartin Matuska 			memcpy(cfdata->sum_extra, p + sumbytes - odd, odd);
11516c95142eSMartin Matuska 		cfdata->sum_extra_avail = odd;
11526c95142eSMartin Matuska 	}
11536c95142eSMartin Matuska 	cfdata->sum_ptr = NULL;
11546c95142eSMartin Matuska }
11556c95142eSMartin Matuska 
11566c95142eSMartin Matuska static int
11576c95142eSMartin Matuska cab_checksum_finish(struct archive_read *a)
11586c95142eSMartin Matuska {
11596c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
11606c95142eSMartin Matuska 	struct cfdata *cfdata = cab->entry_cfdata;
11616c95142eSMartin Matuska 	int l;
11626c95142eSMartin Matuska 
11636c95142eSMartin Matuska 	/* Do not need to compute a sum. */
11646c95142eSMartin Matuska 	if (cfdata->sum == 0)
11656c95142eSMartin Matuska 		return (ARCHIVE_OK);
11666c95142eSMartin Matuska 
11676c95142eSMartin Matuska 	/*
11686c95142eSMartin Matuska 	 * Calculate the sum of remaining CFDATA.
11696c95142eSMartin Matuska 	 */
11706c95142eSMartin Matuska 	if (cfdata->sum_extra_avail) {
11716c95142eSMartin Matuska 		cfdata->sum_calculated =
11726c95142eSMartin Matuska 		    cab_checksum_cfdata(cfdata->sum_extra,
11736c95142eSMartin Matuska 		       cfdata->sum_extra_avail, cfdata->sum_calculated);
11746c95142eSMartin Matuska 		cfdata->sum_extra_avail = 0;
11756c95142eSMartin Matuska 	}
11766c95142eSMartin Matuska 
11776c95142eSMartin Matuska 	l = 4;
11786c95142eSMartin Matuska 	if (cab->cfheader.flags & RESERVE_PRESENT)
11796c95142eSMartin Matuska 		l += cab->cfheader.cfdata;
11806c95142eSMartin Matuska 	cfdata->sum_calculated = cab_checksum_cfdata(
11816c95142eSMartin Matuska 	    cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
11826c95142eSMartin Matuska 	if (cfdata->sum_calculated != cfdata->sum) {
11836c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
11846c95142eSMartin Matuska 		    "Checksum error CFDATA[%d] %x:%x in %d bytes",
11856c95142eSMartin Matuska 		    cab->entry_cffolder->cfdata_index -1,
11866c95142eSMartin Matuska 		    cfdata->sum, cfdata->sum_calculated,
11876c95142eSMartin Matuska 		    cfdata->compressed_size);
11886c95142eSMartin Matuska 		return (ARCHIVE_FAILED);
11896c95142eSMartin Matuska 	}
11906c95142eSMartin Matuska 	return (ARCHIVE_OK);
11916c95142eSMartin Matuska }
11926c95142eSMartin Matuska 
11936c95142eSMartin Matuska /*
11946c95142eSMartin Matuska  * Read CFDATA if needed.
11956c95142eSMartin Matuska  */
11966c95142eSMartin Matuska static int
11976c95142eSMartin Matuska cab_next_cfdata(struct archive_read *a)
11986c95142eSMartin Matuska {
11996c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
12006c95142eSMartin Matuska 	struct cfdata *cfdata = cab->entry_cfdata;
12016c95142eSMartin Matuska 
12026c95142eSMartin Matuska 	/* There are remaining bytes in current CFDATA, use it first. */
12036c95142eSMartin Matuska 	if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0)
12046c95142eSMartin Matuska 		return (ARCHIVE_OK);
12056c95142eSMartin Matuska 
12066c95142eSMartin Matuska 	if (cfdata == NULL) {
12076c95142eSMartin Matuska 		int64_t skip;
12086c95142eSMartin Matuska 
12096c95142eSMartin Matuska 		cab->entry_cffolder->cfdata_index = 0;
12106c95142eSMartin Matuska 
12116c95142eSMartin Matuska 		/* Seek read pointer to the offset of CFDATA if needed. */
12126c95142eSMartin Matuska 		skip = cab->entry_cffolder->cfdata_offset_in_cab
12136c95142eSMartin Matuska 			- cab->cab_offset;
12146c95142eSMartin Matuska 		if (skip < 0) {
12156c95142eSMartin Matuska 			int folder_index;
12166c95142eSMartin Matuska 			switch (cab->entry_cffile->folder) {
12176c95142eSMartin Matuska 			case iFoldCONTINUED_FROM_PREV:
12186c95142eSMartin Matuska 			case iFoldCONTINUED_PREV_AND_NEXT:
12196c95142eSMartin Matuska 				folder_index = 0;
12206c95142eSMartin Matuska 				break;
12216c95142eSMartin Matuska 			case iFoldCONTINUED_TO_NEXT:
12226c95142eSMartin Matuska 				folder_index = cab->cfheader.folder_count-1;
12236c95142eSMartin Matuska 				break;
12246c95142eSMartin Matuska 			default:
12256c95142eSMartin Matuska 				folder_index = cab->entry_cffile->folder;
12266c95142eSMartin Matuska 				break;
12276c95142eSMartin Matuska 			}
12286c95142eSMartin Matuska 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
12296c95142eSMartin Matuska 			    "Invalid offset of CFDATA in folder(%d) %jd < %jd",
12306c95142eSMartin Matuska 			    folder_index,
12316c95142eSMartin Matuska 			    (intmax_t)cab->entry_cffolder->cfdata_offset_in_cab,
12326c95142eSMartin Matuska 			    (intmax_t)cab->cab_offset);
12336c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
12346c95142eSMartin Matuska 		}
12356c95142eSMartin Matuska 		if (skip > 0) {
12366c95142eSMartin Matuska 			if (__archive_read_consume(a, skip) < 0)
12376c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
12386c95142eSMartin Matuska 			cab->cab_offset =
12396c95142eSMartin Matuska 			    cab->entry_cffolder->cfdata_offset_in_cab;
12406c95142eSMartin Matuska 		}
12416c95142eSMartin Matuska 	}
12426c95142eSMartin Matuska 
12436c95142eSMartin Matuska 	/*
12446c95142eSMartin Matuska 	 * Read a CFDATA.
12456c95142eSMartin Matuska 	 */
12466c95142eSMartin Matuska 	if (cab->entry_cffolder->cfdata_index <
12476c95142eSMartin Matuska 	    cab->entry_cffolder->cfdata_count) {
12486c95142eSMartin Matuska 		const unsigned char *p;
12496c95142eSMartin Matuska 		int l;
12506c95142eSMartin Matuska 
12516c95142eSMartin Matuska 		cfdata = &(cab->entry_cffolder->cfdata);
12526c95142eSMartin Matuska 		cab->entry_cffolder->cfdata_index++;
12536c95142eSMartin Matuska 		cab->entry_cfdata = cfdata;
12546c95142eSMartin Matuska 		cfdata->sum_calculated = 0;
12556c95142eSMartin Matuska 		cfdata->sum_extra_avail = 0;
12566c95142eSMartin Matuska 		cfdata->sum_ptr = NULL;
12576c95142eSMartin Matuska 		l = 8;
12586c95142eSMartin Matuska 		if (cab->cfheader.flags & RESERVE_PRESENT)
12596c95142eSMartin Matuska 			l += cab->cfheader.cfdata;
12606c95142eSMartin Matuska 		if ((p = __archive_read_ahead(a, l, NULL)) == NULL)
12616c95142eSMartin Matuska 			return (truncated_error(a));
12626c95142eSMartin Matuska 		cfdata->sum = archive_le32dec(p + CFDATA_csum);
12636c95142eSMartin Matuska 		cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData);
12646c95142eSMartin Matuska 		cfdata->compressed_bytes_remaining = cfdata->compressed_size;
12656c95142eSMartin Matuska 		cfdata->uncompressed_size =
12666c95142eSMartin Matuska 		    archive_le16dec(p + CFDATA_cbUncomp);
12676c95142eSMartin Matuska 		cfdata->uncompressed_bytes_remaining =
12686c95142eSMartin Matuska 		    cfdata->uncompressed_size;
12696c95142eSMartin Matuska 		cfdata->uncompressed_avail = 0;
12706c95142eSMartin Matuska 		cfdata->read_offset = 0;
12716c95142eSMartin Matuska 		cfdata->unconsumed = 0;
12726c95142eSMartin Matuska 
12736c95142eSMartin Matuska 		/*
12746c95142eSMartin Matuska 		 * Sanity check if data size is acceptable.
12756c95142eSMartin Matuska 		 */
12766c95142eSMartin Matuska 		if (cfdata->compressed_size == 0 ||
12776c95142eSMartin Matuska 		    cfdata->compressed_size > (0x8000+6144))
12786c95142eSMartin Matuska 			goto invalid;
12796c95142eSMartin Matuska 		if (cfdata->uncompressed_size > 0x8000)
12806c95142eSMartin Matuska 			goto invalid;
12816c95142eSMartin Matuska 		if (cfdata->uncompressed_size == 0) {
12826c95142eSMartin Matuska 			switch (cab->entry_cffile->folder) {
12836c95142eSMartin Matuska 			case iFoldCONTINUED_PREV_AND_NEXT:
12846c95142eSMartin Matuska 			case iFoldCONTINUED_TO_NEXT:
12856c95142eSMartin Matuska 				break;
12866c95142eSMartin Matuska 			case iFoldCONTINUED_FROM_PREV:
12876c95142eSMartin Matuska 			default:
12886c95142eSMartin Matuska 				goto invalid;
12896c95142eSMartin Matuska 			}
12906c95142eSMartin Matuska 		}
12916c95142eSMartin Matuska 		/* If CFDATA is not last in a folder, an uncompressed
12926c95142eSMartin Matuska 		 * size must be 0x8000(32KBi) */
12936c95142eSMartin Matuska 		if ((cab->entry_cffolder->cfdata_index <
12946c95142eSMartin Matuska 		     cab->entry_cffolder->cfdata_count) &&
12956c95142eSMartin Matuska 		       cfdata->uncompressed_size != 0x8000)
12966c95142eSMartin Matuska 			goto invalid;
12976c95142eSMartin Matuska 
12986c95142eSMartin Matuska 		/* A compressed data size and an uncompressed data size must
12996c95142eSMartin Matuska 		 * be the same in no compression mode. */
13006c95142eSMartin Matuska 		if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
13016c95142eSMartin Matuska 		    cfdata->compressed_size != cfdata->uncompressed_size)
13026c95142eSMartin Matuska 			goto invalid;
13036c95142eSMartin Matuska 
13046c95142eSMartin Matuska 		/*
13056c95142eSMartin Matuska 		 * Save CFDATA image for sum check.
13066c95142eSMartin Matuska 		 */
13076c95142eSMartin Matuska 		if (cfdata->memimage_size < (size_t)l) {
13086c95142eSMartin Matuska 			free(cfdata->memimage);
13096c95142eSMartin Matuska 			cfdata->memimage = malloc(l);
13106c95142eSMartin Matuska 			if (cfdata->memimage == NULL) {
13116c95142eSMartin Matuska 				archive_set_error(&a->archive, ENOMEM,
13126c95142eSMartin Matuska 				    "Can't allocate memory for CAB data");
13136c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
13146c95142eSMartin Matuska 			}
13156c95142eSMartin Matuska 			cfdata->memimage_size = l;
13166c95142eSMartin Matuska 		}
13176c95142eSMartin Matuska 		memcpy(cfdata->memimage, p, l);
13186c95142eSMartin Matuska 
13196c95142eSMartin Matuska 		/* Consume bytes as much as we used. */
13206c95142eSMartin Matuska 		__archive_read_consume(a, l);
13216c95142eSMartin Matuska 		cab->cab_offset += l;
13226c95142eSMartin Matuska 	} else if (cab->entry_cffolder->cfdata_count > 0) {
13236c95142eSMartin Matuska 		/* Run out of all CFDATA in a folder. */
13246c95142eSMartin Matuska 		cfdata->compressed_size = 0;
13256c95142eSMartin Matuska 		cfdata->uncompressed_size = 0;
13266c95142eSMartin Matuska 		cfdata->compressed_bytes_remaining = 0;
13276c95142eSMartin Matuska 		cfdata->uncompressed_bytes_remaining = 0;
13286c95142eSMartin Matuska 	} else {
13296c95142eSMartin Matuska 		/* Current folder does not have any CFDATA. */
13306c95142eSMartin Matuska 		cfdata = &(cab->entry_cffolder->cfdata);
13316c95142eSMartin Matuska 		cab->entry_cfdata = cfdata;
13326c95142eSMartin Matuska 		memset(cfdata, 0, sizeof(*cfdata));
13336c95142eSMartin Matuska 	}
13346c95142eSMartin Matuska 	return (ARCHIVE_OK);
13356c95142eSMartin Matuska invalid:
13366c95142eSMartin Matuska 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
13376c95142eSMartin Matuska 	    "Invalid CFDATA");
13386c95142eSMartin Matuska 	return (ARCHIVE_FATAL);
13396c95142eSMartin Matuska }
13406c95142eSMartin Matuska 
13416c95142eSMartin Matuska /*
13426c95142eSMartin Matuska  * Read ahead CFDATA.
13436c95142eSMartin Matuska  */
13446c95142eSMartin Matuska static const void *
13456c95142eSMartin Matuska cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail)
13466c95142eSMartin Matuska {
13476c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
13486c95142eSMartin Matuska 	int err;
13496c95142eSMartin Matuska 
13506c95142eSMartin Matuska 	err = cab_next_cfdata(a);
13516c95142eSMartin Matuska 	if (err < ARCHIVE_OK) {
13526c95142eSMartin Matuska 		*avail = err;
13536c95142eSMartin Matuska 		return (NULL);
13546c95142eSMartin Matuska 	}
13556c95142eSMartin Matuska 
13566c95142eSMartin Matuska 	switch (cab->entry_cffolder->comptype) {
13576c95142eSMartin Matuska 	case COMPTYPE_NONE:
13586c95142eSMartin Matuska 		return (cab_read_ahead_cfdata_none(a, avail));
13596c95142eSMartin Matuska 	case COMPTYPE_MSZIP:
13606c95142eSMartin Matuska 		return (cab_read_ahead_cfdata_deflate(a, avail));
13616c95142eSMartin Matuska 	case COMPTYPE_LZX:
13626c95142eSMartin Matuska 		return (cab_read_ahead_cfdata_lzx(a, avail));
13636c95142eSMartin Matuska 	default: /* Unsupported compression. */
13646c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
13656c95142eSMartin Matuska 		    "Unsupported CAB compression : %s",
13666c95142eSMartin Matuska 		    cab->entry_cffolder->compname);
13676c95142eSMartin Matuska 		*avail = ARCHIVE_FAILED;
13686c95142eSMartin Matuska 		return (NULL);
13696c95142eSMartin Matuska 	}
13706c95142eSMartin Matuska }
13716c95142eSMartin Matuska 
13726c95142eSMartin Matuska /*
13736c95142eSMartin Matuska  * Read ahead CFDATA as uncompressed data.
13746c95142eSMartin Matuska  */
13756c95142eSMartin Matuska static const void *
13766c95142eSMartin Matuska cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
13776c95142eSMartin Matuska {
13786c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
13796c95142eSMartin Matuska 	struct cfdata *cfdata;
13806c95142eSMartin Matuska 	const void *d;
13816c95142eSMartin Matuska 
13826c95142eSMartin Matuska 	cfdata = cab->entry_cfdata;
13836c95142eSMartin Matuska 
13846c95142eSMartin Matuska 	/*
13856c95142eSMartin Matuska 	 * Note: '1' here is a performance optimization.
13866c95142eSMartin Matuska 	 * Recall that the decompression layer returns a count of
13876c95142eSMartin Matuska 	 * available bytes; asking for more than that forces the
13886c95142eSMartin Matuska 	 * decompressor to combine reads by copying data.
13896c95142eSMartin Matuska 	 */
13906c95142eSMartin Matuska 	d = __archive_read_ahead(a, 1, avail);
13916c95142eSMartin Matuska 	if (*avail <= 0) {
13926c95142eSMartin Matuska 		*avail = truncated_error(a);
13936c95142eSMartin Matuska 		return (NULL);
13946c95142eSMartin Matuska 	}
13956c95142eSMartin Matuska 	if (*avail > cfdata->uncompressed_bytes_remaining)
13966c95142eSMartin Matuska 		*avail = cfdata->uncompressed_bytes_remaining;
13976c95142eSMartin Matuska 	cfdata->uncompressed_avail = cfdata->uncompressed_size;
13986c95142eSMartin Matuska 	cfdata->unconsumed = *avail;
13996c95142eSMartin Matuska 	cfdata->sum_ptr = d;
14006c95142eSMartin Matuska 	return (d);
14016c95142eSMartin Matuska }
14026c95142eSMartin Matuska 
14036c95142eSMartin Matuska /*
14046c95142eSMartin Matuska  * Read ahead CFDATA as deflate data.
14056c95142eSMartin Matuska  */
14066c95142eSMartin Matuska #ifdef HAVE_ZLIB_H
14076c95142eSMartin Matuska static const void *
14086c95142eSMartin Matuska cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
14096c95142eSMartin Matuska {
14106c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
14116c95142eSMartin Matuska 	struct cfdata *cfdata;
14126c95142eSMartin Matuska 	const void *d;
14136c95142eSMartin Matuska 	int r, mszip;
14146c95142eSMartin Matuska 	uint16_t uavail;
14156c95142eSMartin Matuska 	char eod = 0;
14166c95142eSMartin Matuska 
14176c95142eSMartin Matuska 	cfdata = cab->entry_cfdata;
14186c95142eSMartin Matuska 	/* If the buffer hasn't been allocated, allocate it now. */
14196c95142eSMartin Matuska 	if (cab->uncompressed_buffer == NULL) {
14206c95142eSMartin Matuska 		cab->uncompressed_buffer_size = 0x8000;
14216c95142eSMartin Matuska 		cab->uncompressed_buffer
14226c95142eSMartin Matuska 		    = (unsigned char *)malloc(cab->uncompressed_buffer_size);
14236c95142eSMartin Matuska 		if (cab->uncompressed_buffer == NULL) {
14246c95142eSMartin Matuska 			archive_set_error(&a->archive, ENOMEM,
14256c95142eSMartin Matuska 			    "No memory for CAB reader");
14266c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
14276c95142eSMartin Matuska 			return (NULL);
14286c95142eSMartin Matuska 		}
14296c95142eSMartin Matuska 	}
14306c95142eSMartin Matuska 
14316c95142eSMartin Matuska 	uavail = cfdata->uncompressed_avail;
14326c95142eSMartin Matuska 	if (uavail == cfdata->uncompressed_size) {
14336c95142eSMartin Matuska 		d = cab->uncompressed_buffer + cfdata->read_offset;
14346c95142eSMartin Matuska 		*avail = uavail - cfdata->read_offset;
14356c95142eSMartin Matuska 		return (d);
14366c95142eSMartin Matuska 	}
14376c95142eSMartin Matuska 
14386c95142eSMartin Matuska 	if (!cab->entry_cffolder->decompress_init) {
14396c95142eSMartin Matuska 		cab->stream.next_in = NULL;
14406c95142eSMartin Matuska 		cab->stream.avail_in = 0;
14416c95142eSMartin Matuska 		cab->stream.total_in = 0;
14426c95142eSMartin Matuska 		cab->stream.next_out = NULL;
14436c95142eSMartin Matuska 		cab->stream.avail_out = 0;
14446c95142eSMartin Matuska 		cab->stream.total_out = 0;
14456c95142eSMartin Matuska 		if (cab->stream_valid)
14466c95142eSMartin Matuska 			r = inflateReset(&cab->stream);
14476c95142eSMartin Matuska 		else
14486c95142eSMartin Matuska 			r = inflateInit2(&cab->stream,
14496c95142eSMartin Matuska 			    -15 /* Don't check for zlib header */);
14506c95142eSMartin Matuska 		if (r != Z_OK) {
14516c95142eSMartin Matuska 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
14526c95142eSMartin Matuska 			    "Can't initialize deflate decompression.");
14536c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
14546c95142eSMartin Matuska 			return (NULL);
14556c95142eSMartin Matuska 		}
14566c95142eSMartin Matuska 		/* Stream structure has been set up. */
14576c95142eSMartin Matuska 		cab->stream_valid = 1;
14586c95142eSMartin Matuska 		/* We've initialized decompression for this stream. */
14596c95142eSMartin Matuska 		cab->entry_cffolder->decompress_init = 1;
14606c95142eSMartin Matuska 	}
14616c95142eSMartin Matuska 
14626c95142eSMartin Matuska 	if (cfdata->compressed_bytes_remaining == cfdata->compressed_size)
14636c95142eSMartin Matuska 		mszip = 2;
14646c95142eSMartin Matuska 	else
14656c95142eSMartin Matuska 		mszip = 0;
14666c95142eSMartin Matuska 	eod = 0;
14676c95142eSMartin Matuska 	cab->stream.total_out = uavail;
14686c95142eSMartin Matuska 	/*
14696c95142eSMartin Matuska 	 * We always uncompress all data in current CFDATA.
14706c95142eSMartin Matuska 	 */
14716c95142eSMartin Matuska 	while (!eod && cab->stream.total_out < cfdata->uncompressed_size) {
14726c95142eSMartin Matuska 		ssize_t bytes_avail;
14736c95142eSMartin Matuska 
14746c95142eSMartin Matuska 		cab->stream.next_out =
14756c95142eSMartin Matuska 		    cab->uncompressed_buffer + cab->stream.total_out;
14766c95142eSMartin Matuska 		cab->stream.avail_out =
14776c95142eSMartin Matuska 		    cfdata->uncompressed_size - cab->stream.total_out;
14786c95142eSMartin Matuska 
14796c95142eSMartin Matuska 		d = __archive_read_ahead(a, 1, &bytes_avail);
14806c95142eSMartin Matuska 		if (bytes_avail <= 0) {
14816c95142eSMartin Matuska 			*avail = truncated_error(a);
14826c95142eSMartin Matuska 			return (NULL);
14836c95142eSMartin Matuska 		}
14846c95142eSMartin Matuska 		if (bytes_avail > cfdata->compressed_bytes_remaining)
14856c95142eSMartin Matuska 			bytes_avail = cfdata->compressed_bytes_remaining;
14866c95142eSMartin Matuska 		/*
14876c95142eSMartin Matuska 		 * A bug in zlib.h: stream.next_in should be marked 'const'
14886c95142eSMartin Matuska 		 * but isn't (the library never alters data through the
14896c95142eSMartin Matuska 		 * next_in pointer, only reads it).  The result: this ugly
14906c95142eSMartin Matuska 		 * cast to remove 'const'.
14916c95142eSMartin Matuska 		 */
14926c95142eSMartin Matuska 		cab->stream.next_in = (Bytef *)(uintptr_t)d;
1493acc60b03SMartin Matuska 		cab->stream.avail_in = (uInt)bytes_avail;
14946c95142eSMartin Matuska 		cab->stream.total_in = 0;
14956c95142eSMartin Matuska 
14966c95142eSMartin Matuska 		/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
14976c95142eSMartin Matuska 		if (mszip > 0) {
14989f3de9e2SMartin Matuska 			if (bytes_avail <= 0)
14999f3de9e2SMartin Matuska 				goto nomszip;
15006c95142eSMartin Matuska 			if (bytes_avail <= mszip) {
15016c95142eSMartin Matuska 				if (mszip == 2) {
15026c95142eSMartin Matuska 					if (cab->stream.next_in[0] != 0x43)
15036c95142eSMartin Matuska 						goto nomszip;
15046c95142eSMartin Matuska 					if (bytes_avail > 1 &&
15056c95142eSMartin Matuska 					    cab->stream.next_in[1] != 0x4b)
15066c95142eSMartin Matuska 						goto nomszip;
15076c95142eSMartin Matuska 				} else if (cab->stream.next_in[0] != 0x4b)
15086c95142eSMartin Matuska 					goto nomszip;
15096c95142eSMartin Matuska 				cfdata->unconsumed = bytes_avail;
15106c95142eSMartin Matuska 				cfdata->sum_ptr = d;
15116c95142eSMartin Matuska 				if (cab_minimum_consume_cfdata(
15126c95142eSMartin Matuska 				    a, cfdata->unconsumed) < 0) {
15136c95142eSMartin Matuska 					*avail = ARCHIVE_FATAL;
15146c95142eSMartin Matuska 					return (NULL);
15156c95142eSMartin Matuska 				}
1516acc60b03SMartin Matuska 				mszip -= (int)bytes_avail;
15176c95142eSMartin Matuska 				continue;
15186c95142eSMartin Matuska 			}
15196c95142eSMartin Matuska 			if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
15206c95142eSMartin Matuska 				goto nomszip;
15216c95142eSMartin Matuska 			else if (cab->stream.next_in[0] != 0x43 ||
15226c95142eSMartin Matuska 			    cab->stream.next_in[1] != 0x4b)
15236c95142eSMartin Matuska 				goto nomszip;
15246c95142eSMartin Matuska 			cab->stream.next_in += mszip;
15256c95142eSMartin Matuska 			cab->stream.avail_in -= mszip;
15266c95142eSMartin Matuska 			cab->stream.total_in += mszip;
15276c95142eSMartin Matuska 			mszip = 0;
15286c95142eSMartin Matuska 		}
15296c95142eSMartin Matuska 
15306c95142eSMartin Matuska 		r = inflate(&cab->stream, 0);
15316c95142eSMartin Matuska 		switch (r) {
15326c95142eSMartin Matuska 		case Z_OK:
15336c95142eSMartin Matuska 			break;
15346c95142eSMartin Matuska 		case Z_STREAM_END:
15356c95142eSMartin Matuska 			eod = 1;
15366c95142eSMartin Matuska 			break;
15376c95142eSMartin Matuska 		default:
15386c95142eSMartin Matuska 			goto zlibfailed;
15396c95142eSMartin Matuska 		}
15406c95142eSMartin Matuska 		cfdata->unconsumed = cab->stream.total_in;
15416c95142eSMartin Matuska 		cfdata->sum_ptr = d;
15426c95142eSMartin Matuska 		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
15436c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
15446c95142eSMartin Matuska 			return (NULL);
15456c95142eSMartin Matuska 		}
15466c95142eSMartin Matuska 	}
1547fd082e96SMartin Matuska 	uavail = (uint16_t)cab->stream.total_out;
15486c95142eSMartin Matuska 
15496c95142eSMartin Matuska 	if (uavail < cfdata->uncompressed_size) {
15506c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
15516c95142eSMartin Matuska 		    "Invalid uncompressed size (%d < %d)",
15526c95142eSMartin Matuska 		    uavail, cfdata->uncompressed_size);
15536c95142eSMartin Matuska 		*avail = ARCHIVE_FATAL;
15546c95142eSMartin Matuska 		return (NULL);
15556c95142eSMartin Matuska 	}
15566c95142eSMartin Matuska 
15576c95142eSMartin Matuska 	/*
15586c95142eSMartin Matuska 	 * Note: I suspect there is a bug in makecab.exe because, in rare
15596c95142eSMartin Matuska 	 * case, compressed bytes are still remaining regardless we have
1560a2e802b7SMartin Matuska 	 * gotten all uncompressed bytes, which size is recorded in CFDATA,
15616c95142eSMartin Matuska 	 * as much as we need, and we have to use the garbage so as to
15626c95142eSMartin Matuska 	 * correctly compute the sum of CFDATA accordingly.
15636c95142eSMartin Matuska 	 */
15646c95142eSMartin Matuska 	if (cfdata->compressed_bytes_remaining > 0) {
15656c95142eSMartin Matuska 		ssize_t bytes_avail;
15666c95142eSMartin Matuska 
15676c95142eSMartin Matuska 		d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
15686c95142eSMartin Matuska 		    &bytes_avail);
15696c95142eSMartin Matuska 		if (bytes_avail <= 0) {
15706c95142eSMartin Matuska 			*avail = truncated_error(a);
15716c95142eSMartin Matuska 			return (NULL);
15726c95142eSMartin Matuska 		}
15736c95142eSMartin Matuska 		cfdata->unconsumed = cfdata->compressed_bytes_remaining;
15746c95142eSMartin Matuska 		cfdata->sum_ptr = d;
15756c95142eSMartin Matuska 		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
15766c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
15776c95142eSMartin Matuska 			return (NULL);
15786c95142eSMartin Matuska 		}
15796c95142eSMartin Matuska 	}
15806c95142eSMartin Matuska 
15816c95142eSMartin Matuska 	/*
15826c95142eSMartin Matuska 	 * Set dictionary data for decompressing of next CFDATA, which
15836c95142eSMartin Matuska 	 * in the same folder. This is why we always do decompress CFDATA
15846c95142eSMartin Matuska 	 * even if beginning CFDATA or some of CFDATA are not used in
15856c95142eSMartin Matuska 	 * skipping file data.
15866c95142eSMartin Matuska 	 */
15876c95142eSMartin Matuska 	if (cab->entry_cffolder->cfdata_index <
15886c95142eSMartin Matuska 	    cab->entry_cffolder->cfdata_count) {
15896c95142eSMartin Matuska 		r = inflateReset(&cab->stream);
15906c95142eSMartin Matuska 		if (r != Z_OK)
15916c95142eSMartin Matuska 			goto zlibfailed;
15926c95142eSMartin Matuska 		r = inflateSetDictionary(&cab->stream,
15936c95142eSMartin Matuska 		    cab->uncompressed_buffer, cfdata->uncompressed_size);
15946c95142eSMartin Matuska 		if (r != Z_OK)
15956c95142eSMartin Matuska 			goto zlibfailed;
15966c95142eSMartin Matuska 	}
15976c95142eSMartin Matuska 
15986c95142eSMartin Matuska 	d = cab->uncompressed_buffer + cfdata->read_offset;
15996c95142eSMartin Matuska 	*avail = uavail - cfdata->read_offset;
16006c95142eSMartin Matuska 	cfdata->uncompressed_avail = uavail;
16016c95142eSMartin Matuska 
16026c95142eSMartin Matuska 	return (d);
16036c95142eSMartin Matuska 
16046c95142eSMartin Matuska zlibfailed:
16056c95142eSMartin Matuska 	switch (r) {
16066c95142eSMartin Matuska 	case Z_MEM_ERROR:
16076c95142eSMartin Matuska 		archive_set_error(&a->archive, ENOMEM,
16086c95142eSMartin Matuska 		    "Out of memory for deflate decompression");
16096c95142eSMartin Matuska 		break;
16106c95142eSMartin Matuska 	default:
16116c95142eSMartin Matuska 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
16126c95142eSMartin Matuska 		    "Deflate decompression failed (%d)", r);
16136c95142eSMartin Matuska 		break;
16146c95142eSMartin Matuska 	}
16156c95142eSMartin Matuska 	*avail = ARCHIVE_FATAL;
16166c95142eSMartin Matuska 	return (NULL);
16176c95142eSMartin Matuska nomszip:
16186c95142eSMartin Matuska 	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
16196c95142eSMartin Matuska 	    "CFDATA incorrect(no MSZIP signature)");
16206c95142eSMartin Matuska 	*avail = ARCHIVE_FATAL;
16216c95142eSMartin Matuska 	return (NULL);
16226c95142eSMartin Matuska }
16236c95142eSMartin Matuska 
16246c95142eSMartin Matuska #else /* HAVE_ZLIB_H */
16256c95142eSMartin Matuska 
16266c95142eSMartin Matuska static const void *
16276c95142eSMartin Matuska cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
16286c95142eSMartin Matuska {
16296c95142eSMartin Matuska 	*avail = ARCHIVE_FATAL;
16306c95142eSMartin Matuska 	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
16316c95142eSMartin Matuska 	    "libarchive compiled without deflate support (no libz)");
16326c95142eSMartin Matuska 	return (NULL);
16336c95142eSMartin Matuska }
16346c95142eSMartin Matuska 
16356c95142eSMartin Matuska #endif /* HAVE_ZLIB_H */
16366c95142eSMartin Matuska 
16376c95142eSMartin Matuska static const void *
16386c95142eSMartin Matuska cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
16396c95142eSMartin Matuska {
16406c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
16416c95142eSMartin Matuska 	struct cfdata *cfdata;
16426c95142eSMartin Matuska 	const void *d;
16436c95142eSMartin Matuska 	int r;
16446c95142eSMartin Matuska 	uint16_t uavail;
16456c95142eSMartin Matuska 
16466c95142eSMartin Matuska 	cfdata = cab->entry_cfdata;
16476c95142eSMartin Matuska 	/* If the buffer hasn't been allocated, allocate it now. */
16486c95142eSMartin Matuska 	if (cab->uncompressed_buffer == NULL) {
16496c95142eSMartin Matuska 		cab->uncompressed_buffer_size = 0x8000;
16506c95142eSMartin Matuska 		cab->uncompressed_buffer
16516c95142eSMartin Matuska 		    = (unsigned char *)malloc(cab->uncompressed_buffer_size);
16526c95142eSMartin Matuska 		if (cab->uncompressed_buffer == NULL) {
16536c95142eSMartin Matuska 			archive_set_error(&a->archive, ENOMEM,
16546c95142eSMartin Matuska 			    "No memory for CAB reader");
16556c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
16566c95142eSMartin Matuska 			return (NULL);
16576c95142eSMartin Matuska 		}
16586c95142eSMartin Matuska 	}
16596c95142eSMartin Matuska 
16606c95142eSMartin Matuska 	uavail = cfdata->uncompressed_avail;
16616c95142eSMartin Matuska 	if (uavail == cfdata->uncompressed_size) {
16626c95142eSMartin Matuska 		d = cab->uncompressed_buffer + cfdata->read_offset;
16636c95142eSMartin Matuska 		*avail = uavail - cfdata->read_offset;
16646c95142eSMartin Matuska 		return (d);
16656c95142eSMartin Matuska 	}
16666c95142eSMartin Matuska 
16676c95142eSMartin Matuska 	if (!cab->entry_cffolder->decompress_init) {
16686c95142eSMartin Matuska 		r = lzx_decode_init(&cab->xstrm,
16696c95142eSMartin Matuska 		    cab->entry_cffolder->compdata);
16706c95142eSMartin Matuska 		if (r != ARCHIVE_OK) {
16716c95142eSMartin Matuska 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
16726c95142eSMartin Matuska 			    "Can't initialize LZX decompression.");
16736c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
16746c95142eSMartin Matuska 			return (NULL);
16756c95142eSMartin Matuska 		}
16766c95142eSMartin Matuska 		/* We've initialized decompression for this stream. */
16776c95142eSMartin Matuska 		cab->entry_cffolder->decompress_init = 1;
16786c95142eSMartin Matuska 	}
16796c95142eSMartin Matuska 
16806c95142eSMartin Matuska 	/* Clean up remaining bits of previous CFDATA. */
16816c95142eSMartin Matuska 	lzx_cleanup_bitstream(&cab->xstrm);
16826c95142eSMartin Matuska 	cab->xstrm.total_out = uavail;
16836c95142eSMartin Matuska 	while (cab->xstrm.total_out < cfdata->uncompressed_size) {
16846c95142eSMartin Matuska 		ssize_t bytes_avail;
16856c95142eSMartin Matuska 
16866c95142eSMartin Matuska 		cab->xstrm.next_out =
16876c95142eSMartin Matuska 		    cab->uncompressed_buffer + cab->xstrm.total_out;
16886c95142eSMartin Matuska 		cab->xstrm.avail_out =
16896c95142eSMartin Matuska 		    cfdata->uncompressed_size - cab->xstrm.total_out;
16906c95142eSMartin Matuska 
16916c95142eSMartin Matuska 		d = __archive_read_ahead(a, 1, &bytes_avail);
16926c95142eSMartin Matuska 		if (bytes_avail <= 0) {
16936c95142eSMartin Matuska 			archive_set_error(&a->archive,
16946c95142eSMartin Matuska 			    ARCHIVE_ERRNO_FILE_FORMAT,
16956c95142eSMartin Matuska 			    "Truncated CAB file data");
16966c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
16976c95142eSMartin Matuska 			return (NULL);
16986c95142eSMartin Matuska 		}
16996c95142eSMartin Matuska 		if (bytes_avail > cfdata->compressed_bytes_remaining)
17006c95142eSMartin Matuska 			bytes_avail = cfdata->compressed_bytes_remaining;
17016c95142eSMartin Matuska 
17026c95142eSMartin Matuska 		cab->xstrm.next_in = d;
17036c95142eSMartin Matuska 		cab->xstrm.avail_in = bytes_avail;
17046c95142eSMartin Matuska 		cab->xstrm.total_in = 0;
17056c95142eSMartin Matuska 		r = lzx_decode(&cab->xstrm,
17066c95142eSMartin Matuska 		    cfdata->compressed_bytes_remaining == bytes_avail);
17076c95142eSMartin Matuska 		switch (r) {
17086c95142eSMartin Matuska 		case ARCHIVE_OK:
17096c95142eSMartin Matuska 		case ARCHIVE_EOF:
17106c95142eSMartin Matuska 			break;
17116c95142eSMartin Matuska 		default:
17126c95142eSMartin Matuska 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
17136c95142eSMartin Matuska 			    "LZX decompression failed (%d)", r);
17146c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
17156c95142eSMartin Matuska 			return (NULL);
17166c95142eSMartin Matuska 		}
17176c95142eSMartin Matuska 		cfdata->unconsumed = cab->xstrm.total_in;
17186c95142eSMartin Matuska 		cfdata->sum_ptr = d;
17196c95142eSMartin Matuska 		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
17206c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
17216c95142eSMartin Matuska 			return (NULL);
17226c95142eSMartin Matuska 		}
17236c95142eSMartin Matuska 	}
17246c95142eSMartin Matuska 
1725fd082e96SMartin Matuska 	uavail = (uint16_t)cab->xstrm.total_out;
17266c95142eSMartin Matuska 	/*
17276c95142eSMartin Matuska 	 * Make sure a read pointer advances to next CFDATA.
17286c95142eSMartin Matuska 	 */
17296c95142eSMartin Matuska 	if (cfdata->compressed_bytes_remaining > 0) {
17306c95142eSMartin Matuska 		ssize_t bytes_avail;
17316c95142eSMartin Matuska 
17326c95142eSMartin Matuska 		d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
17336c95142eSMartin Matuska 		    &bytes_avail);
17346c95142eSMartin Matuska 		if (bytes_avail <= 0) {
17356c95142eSMartin Matuska 			*avail = truncated_error(a);
17366c95142eSMartin Matuska 			return (NULL);
17376c95142eSMartin Matuska 		}
17386c95142eSMartin Matuska 		cfdata->unconsumed = cfdata->compressed_bytes_remaining;
17396c95142eSMartin Matuska 		cfdata->sum_ptr = d;
17406c95142eSMartin Matuska 		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
17416c95142eSMartin Matuska 			*avail = ARCHIVE_FATAL;
17426c95142eSMartin Matuska 			return (NULL);
17436c95142eSMartin Matuska 		}
17446c95142eSMartin Matuska 	}
17456c95142eSMartin Matuska 
17466c95142eSMartin Matuska 	/*
1747a2e802b7SMartin Matuska 	 * Translation reversal of x86 processor CALL byte sequence(E8).
17486c95142eSMartin Matuska 	 */
17496c95142eSMartin Matuska 	lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
17506c95142eSMartin Matuska 	    cfdata->uncompressed_size,
17516c95142eSMartin Matuska 	    (cab->entry_cffolder->cfdata_index-1) * 0x8000);
17526c95142eSMartin Matuska 
17536c95142eSMartin Matuska 	d = cab->uncompressed_buffer + cfdata->read_offset;
17546c95142eSMartin Matuska 	*avail = uavail - cfdata->read_offset;
17556c95142eSMartin Matuska 	cfdata->uncompressed_avail = uavail;
17566c95142eSMartin Matuska 
17576c95142eSMartin Matuska 	return (d);
17586c95142eSMartin Matuska }
17596c95142eSMartin Matuska 
17606c95142eSMartin Matuska /*
17616c95142eSMartin Matuska  * Consume CFDATA.
17626c95142eSMartin Matuska  * We always decompress CFDATA to consume CFDATA as much as we need
17636c95142eSMartin Matuska  * in uncompressed bytes because all CFDATA in a folder are related
17646c95142eSMartin Matuska  * so we do not skip any CFDATA without decompressing.
17656c95142eSMartin Matuska  * Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or
17666c95142eSMartin Matuska  * iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for
17676c95142eSMartin Matuska  * the CFFILE is remaining bytes of previous Multivolume CAB file.
17686c95142eSMartin Matuska  */
17696c95142eSMartin Matuska static int64_t
17706c95142eSMartin Matuska cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
17716c95142eSMartin Matuska {
17726c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
17736c95142eSMartin Matuska 	struct cfdata *cfdata;
17746c95142eSMartin Matuska 	int64_t cbytes, rbytes;
17756c95142eSMartin Matuska 	int err;
17766c95142eSMartin Matuska 
17776c95142eSMartin Matuska 	rbytes = cab_minimum_consume_cfdata(a, consumed_bytes);
17786c95142eSMartin Matuska 	if (rbytes < 0)
17796c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
17806c95142eSMartin Matuska 
17816c95142eSMartin Matuska 	cfdata = cab->entry_cfdata;
17826c95142eSMartin Matuska 	while (rbytes > 0) {
17836c95142eSMartin Matuska 		ssize_t avail;
17846c95142eSMartin Matuska 
17856c95142eSMartin Matuska 		if (cfdata->compressed_size == 0) {
17866c95142eSMartin Matuska 			archive_set_error(&a->archive,
17876c95142eSMartin Matuska 			    ARCHIVE_ERRNO_FILE_FORMAT,
17886c95142eSMartin Matuska 			    "Invalid CFDATA");
17896c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
17906c95142eSMartin Matuska 		}
17916c95142eSMartin Matuska 		cbytes = cfdata->uncompressed_bytes_remaining;
17926c95142eSMartin Matuska 		if (cbytes > rbytes)
17936c95142eSMartin Matuska 			cbytes = rbytes;
17946c95142eSMartin Matuska 		rbytes -= cbytes;
17956c95142eSMartin Matuska 
17966c95142eSMartin Matuska 		if (cfdata->uncompressed_avail == 0 &&
1797fd082e96SMartin Matuska 		   (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
17986c95142eSMartin Matuska 		    cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
17996c95142eSMartin Matuska 			/* We have not read any data yet. */
18006c95142eSMartin Matuska 			if (cbytes == cfdata->uncompressed_bytes_remaining) {
18016c95142eSMartin Matuska 				/* Skip whole current CFDATA. */
18026c95142eSMartin Matuska 				__archive_read_consume(a,
18036c95142eSMartin Matuska 				    cfdata->compressed_size);
18046c95142eSMartin Matuska 				cab->cab_offset += cfdata->compressed_size;
18056c95142eSMartin Matuska 				cfdata->compressed_bytes_remaining = 0;
18066c95142eSMartin Matuska 				cfdata->uncompressed_bytes_remaining = 0;
18076c95142eSMartin Matuska 				err = cab_next_cfdata(a);
18086c95142eSMartin Matuska 				if (err < 0)
18096c95142eSMartin Matuska 					return (err);
18106c95142eSMartin Matuska 				cfdata = cab->entry_cfdata;
18116c95142eSMartin Matuska 				if (cfdata->uncompressed_size == 0) {
18126c95142eSMartin Matuska 					switch (cab->entry_cffile->folder) {
18136c95142eSMartin Matuska 					case iFoldCONTINUED_PREV_AND_NEXT:
18146c95142eSMartin Matuska 					case iFoldCONTINUED_TO_NEXT:
18156c95142eSMartin Matuska 					case iFoldCONTINUED_FROM_PREV:
18166c95142eSMartin Matuska 						rbytes = 0;
18176c95142eSMartin Matuska 						break;
18186c95142eSMartin Matuska 					default:
18196c95142eSMartin Matuska 						break;
18206c95142eSMartin Matuska 					}
18216c95142eSMartin Matuska 				}
18226c95142eSMartin Matuska 				continue;
18236c95142eSMartin Matuska 			}
1824fd082e96SMartin Matuska 			cfdata->read_offset += (uint16_t)cbytes;
1825fd082e96SMartin Matuska 			cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
18266c95142eSMartin Matuska 			break;
18276c95142eSMartin Matuska 		} else if (cbytes == 0) {
18286c95142eSMartin Matuska 			err = cab_next_cfdata(a);
18296c95142eSMartin Matuska 			if (err < 0)
18306c95142eSMartin Matuska 				return (err);
18316c95142eSMartin Matuska 			cfdata = cab->entry_cfdata;
18326c95142eSMartin Matuska 			if (cfdata->uncompressed_size == 0) {
18336c95142eSMartin Matuska 				switch (cab->entry_cffile->folder) {
18346c95142eSMartin Matuska 				case iFoldCONTINUED_PREV_AND_NEXT:
18356c95142eSMartin Matuska 				case iFoldCONTINUED_TO_NEXT:
18366c95142eSMartin Matuska 				case iFoldCONTINUED_FROM_PREV:
18376c95142eSMartin Matuska 					return (ARCHIVE_FATAL);
18386c95142eSMartin Matuska 				default:
18396c95142eSMartin Matuska 					break;
18406c95142eSMartin Matuska 				}
18416c95142eSMartin Matuska 			}
18426c95142eSMartin Matuska 			continue;
18436c95142eSMartin Matuska 		}
18446c95142eSMartin Matuska 		while (cbytes > 0) {
18456c95142eSMartin Matuska 			(void)cab_read_ahead_cfdata(a, &avail);
18466c95142eSMartin Matuska 			if (avail <= 0)
18476c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
18486c95142eSMartin Matuska 			if (avail > cbytes)
1849fd082e96SMartin Matuska 				avail = (ssize_t)cbytes;
18506c95142eSMartin Matuska 			if (cab_minimum_consume_cfdata(a, avail) < 0)
18516c95142eSMartin Matuska 				return (ARCHIVE_FATAL);
18526c95142eSMartin Matuska 			cbytes -= avail;
18536c95142eSMartin Matuska 		}
18546c95142eSMartin Matuska 	}
18556c95142eSMartin Matuska 	return (consumed_bytes);
18566c95142eSMartin Matuska }
18576c95142eSMartin Matuska 
18586c95142eSMartin Matuska /*
18596c95142eSMartin Matuska  * Consume CFDATA as much as we have already gotten and
18606c95142eSMartin Matuska  * compute the sum of CFDATA.
18616c95142eSMartin Matuska  */
18626c95142eSMartin Matuska static int64_t
18636c95142eSMartin Matuska cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
18646c95142eSMartin Matuska {
18656c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
18666c95142eSMartin Matuska 	struct cfdata *cfdata;
18676c95142eSMartin Matuska 	int64_t cbytes, rbytes;
18686c95142eSMartin Matuska 	int err;
18696c95142eSMartin Matuska 
18706c95142eSMartin Matuska 	cfdata = cab->entry_cfdata;
18716c95142eSMartin Matuska 	rbytes = consumed_bytes;
18726c95142eSMartin Matuska 	if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
18736c95142eSMartin Matuska 		if (consumed_bytes < cfdata->unconsumed)
18746c95142eSMartin Matuska 			cbytes = consumed_bytes;
18756c95142eSMartin Matuska 		else
18766c95142eSMartin Matuska 			cbytes = cfdata->unconsumed;
18776c95142eSMartin Matuska 		rbytes -= cbytes;
1878fd082e96SMartin Matuska 		cfdata->read_offset += (uint16_t)cbytes;
1879fd082e96SMartin Matuska 		cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
18806c95142eSMartin Matuska 		cfdata->unconsumed -= cbytes;
18816c95142eSMartin Matuska 	} else {
18826c95142eSMartin Matuska 		cbytes = cfdata->uncompressed_avail - cfdata->read_offset;
18836c95142eSMartin Matuska 		if (cbytes > 0) {
18846c95142eSMartin Matuska 			if (consumed_bytes < cbytes)
18856c95142eSMartin Matuska 				cbytes = consumed_bytes;
18866c95142eSMartin Matuska 			rbytes -= cbytes;
1887fd082e96SMartin Matuska 			cfdata->read_offset += (uint16_t)cbytes;
1888fd082e96SMartin Matuska 			cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
18896c95142eSMartin Matuska 		}
18906c95142eSMartin Matuska 
18916c95142eSMartin Matuska 		if (cfdata->unconsumed) {
18926c95142eSMartin Matuska 			cbytes = cfdata->unconsumed;
18936c95142eSMartin Matuska 			cfdata->unconsumed = 0;
18946c95142eSMartin Matuska 		} else
18956c95142eSMartin Matuska 			cbytes = 0;
18966c95142eSMartin Matuska 	}
18976c95142eSMartin Matuska 	if (cbytes) {
18986c95142eSMartin Matuska 		/* Compute the sum. */
1899fd082e96SMartin Matuska 		cab_checksum_update(a, (size_t)cbytes);
19006c95142eSMartin Matuska 
19016c95142eSMartin Matuska 		/* Consume as much as the compressor actually used. */
19026c95142eSMartin Matuska 		__archive_read_consume(a, cbytes);
19036c95142eSMartin Matuska 		cab->cab_offset += cbytes;
1904fd082e96SMartin Matuska 		cfdata->compressed_bytes_remaining -= (uint16_t)cbytes;
19056c95142eSMartin Matuska 		if (cfdata->compressed_bytes_remaining == 0) {
19066c95142eSMartin Matuska 			err = cab_checksum_finish(a);
19076c95142eSMartin Matuska 			if (err < 0)
19086c95142eSMartin Matuska 				return (err);
19096c95142eSMartin Matuska 		}
19106c95142eSMartin Matuska 	}
19116c95142eSMartin Matuska 	return (rbytes);
19126c95142eSMartin Matuska }
19136c95142eSMartin Matuska 
19146c95142eSMartin Matuska /*
19156c95142eSMartin Matuska  * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
19166c95142eSMartin Matuska  * cab->end_of_entry if it consumes all of the data.
19176c95142eSMartin Matuska  */
19186c95142eSMartin Matuska static int
19196c95142eSMartin Matuska cab_read_data(struct archive_read *a, const void **buff,
19206c95142eSMartin Matuska     size_t *size, int64_t *offset)
19216c95142eSMartin Matuska {
19226c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
19236c95142eSMartin Matuska 	ssize_t bytes_avail;
19246c95142eSMartin Matuska 
19256c95142eSMartin Matuska 	if (cab->entry_bytes_remaining == 0) {
19266c95142eSMartin Matuska 		*buff = NULL;
19276c95142eSMartin Matuska 		*size = 0;
19286c95142eSMartin Matuska 		*offset = cab->entry_offset;
19296c95142eSMartin Matuska 		cab->end_of_entry = 1;
19306c95142eSMartin Matuska 		return (ARCHIVE_OK);
19316c95142eSMartin Matuska 	}
19326c95142eSMartin Matuska 
19336c95142eSMartin Matuska 	*buff = cab_read_ahead_cfdata(a, &bytes_avail);
19346c95142eSMartin Matuska 	if (bytes_avail <= 0) {
19356c95142eSMartin Matuska 		*buff = NULL;
19366c95142eSMartin Matuska 		*size = 0;
19376c95142eSMartin Matuska 		*offset = 0;
19386c95142eSMartin Matuska 		if (bytes_avail == 0 &&
19396c95142eSMartin Matuska 		    cab->entry_cfdata->uncompressed_size == 0) {
19406c95142eSMartin Matuska 			/* All of CFDATA in a folder has been handled. */
19416c95142eSMartin Matuska 			archive_set_error(&a->archive,
19426c95142eSMartin Matuska 			    ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
19436c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
19446c95142eSMartin Matuska 		} else
1945acc60b03SMartin Matuska 			return ((int)bytes_avail);
19466c95142eSMartin Matuska 	}
19476c95142eSMartin Matuska 	if (bytes_avail > cab->entry_bytes_remaining)
1948fd082e96SMartin Matuska 		bytes_avail = (ssize_t)cab->entry_bytes_remaining;
19496c95142eSMartin Matuska 
19506c95142eSMartin Matuska 	*size = bytes_avail;
19516c95142eSMartin Matuska 	*offset = cab->entry_offset;
19526c95142eSMartin Matuska 	cab->entry_offset += bytes_avail;
19536c95142eSMartin Matuska 	cab->entry_bytes_remaining -= bytes_avail;
19546c95142eSMartin Matuska 	if (cab->entry_bytes_remaining == 0)
19556c95142eSMartin Matuska 		cab->end_of_entry = 1;
19566c95142eSMartin Matuska 	cab->entry_unconsumed = bytes_avail;
1957fd082e96SMartin Matuska 	if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
1958fd082e96SMartin Matuska 		/* Don't consume more than current entry used. */
1959fd082e96SMartin Matuska 		if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed)
1960fd082e96SMartin Matuska 			cab->entry_cfdata->unconsumed = cab->entry_unconsumed;
1961fd082e96SMartin Matuska 	}
19626c95142eSMartin Matuska 	return (ARCHIVE_OK);
19636c95142eSMartin Matuska }
19646c95142eSMartin Matuska 
19656c95142eSMartin Matuska static int
19666c95142eSMartin Matuska archive_read_format_cab_read_data_skip(struct archive_read *a)
19676c95142eSMartin Matuska {
19686c95142eSMartin Matuska 	struct cab *cab;
19696c95142eSMartin Matuska 	int64_t bytes_skipped;
19706c95142eSMartin Matuska 	int r;
19716c95142eSMartin Matuska 
19726c95142eSMartin Matuska 	cab = (struct cab *)(a->format->data);
19736c95142eSMartin Matuska 
19746c95142eSMartin Matuska 	if (cab->end_of_archive)
19756c95142eSMartin Matuska 		return (ARCHIVE_EOF);
19766c95142eSMartin Matuska 
1977fd082e96SMartin Matuska 	if (!cab->read_data_invoked) {
1978fd082e96SMartin Matuska 		cab->bytes_skipped += cab->entry_bytes_remaining;
1979fd082e96SMartin Matuska 		cab->entry_bytes_remaining = 0;
1980fd082e96SMartin Matuska 		/* This entry is finished and done. */
1981fd082e96SMartin Matuska 		cab->end_of_entry_cleanup = cab->end_of_entry = 1;
1982fd082e96SMartin Matuska 		return (ARCHIVE_OK);
1983fd082e96SMartin Matuska 	}
1984fd082e96SMartin Matuska 
19856c95142eSMartin Matuska 	if (cab->entry_unconsumed) {
19866c95142eSMartin Matuska 		/* Consume as much as the compressor actually used. */
1987fd082e96SMartin Matuska 		r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
19886c95142eSMartin Matuska 		cab->entry_unconsumed = 0;
19896c95142eSMartin Matuska 		if (r < 0)
19906c95142eSMartin Matuska 			return (r);
19916c95142eSMartin Matuska 	} else if (cab->entry_cfdata == NULL) {
19926c95142eSMartin Matuska 		r = cab_next_cfdata(a);
19936c95142eSMartin Matuska 		if (r < 0)
19946c95142eSMartin Matuska 			return (r);
19956c95142eSMartin Matuska 	}
19966c95142eSMartin Matuska 
19976c95142eSMartin Matuska 	/* if we've already read to end of data, we're done. */
19986c95142eSMartin Matuska 	if (cab->end_of_entry_cleanup)
19996c95142eSMartin Matuska 		return (ARCHIVE_OK);
20006c95142eSMartin Matuska 
20016c95142eSMartin Matuska 	/*
20026c95142eSMartin Matuska 	 * If the length is at the beginning, we can skip the
20036c95142eSMartin Matuska 	 * compressed data much more quickly.
20046c95142eSMartin Matuska 	 */
20056c95142eSMartin Matuska 	bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining);
20066c95142eSMartin Matuska 	if (bytes_skipped < 0)
20076c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
20086c95142eSMartin Matuska 
2009fd082e96SMartin Matuska 	/* If the compression type is none(uncompressed), we've already
2010fd082e96SMartin Matuska 	 * consumed data as much as the current entry size. */
2011acc60b03SMartin Matuska 	if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
2012acc60b03SMartin Matuska 	    cab->entry_cfdata != NULL)
2013fd082e96SMartin Matuska 		cab->entry_cfdata->unconsumed = 0;
2014fd082e96SMartin Matuska 
20156c95142eSMartin Matuska 	/* This entry is finished and done. */
20166c95142eSMartin Matuska 	cab->end_of_entry_cleanup = cab->end_of_entry = 1;
20176c95142eSMartin Matuska 	return (ARCHIVE_OK);
20186c95142eSMartin Matuska }
20196c95142eSMartin Matuska 
20206c95142eSMartin Matuska static int
20216c95142eSMartin Matuska archive_read_format_cab_cleanup(struct archive_read *a)
20226c95142eSMartin Matuska {
20236c95142eSMartin Matuska 	struct cab *cab = (struct cab *)(a->format->data);
20246c95142eSMartin Matuska 	struct cfheader *hd = &cab->cfheader;
20256c95142eSMartin Matuska 	int i;
20266c95142eSMartin Matuska 
20276c95142eSMartin Matuska 	if (hd->folder_array != NULL) {
20286c95142eSMartin Matuska 		for (i = 0; i < hd->folder_count; i++)
20296c95142eSMartin Matuska 			free(hd->folder_array[i].cfdata.memimage);
20306c95142eSMartin Matuska 		free(hd->folder_array);
20316c95142eSMartin Matuska 	}
20326c95142eSMartin Matuska 	if (hd->file_array != NULL) {
20336c95142eSMartin Matuska 		for (i = 0; i < cab->cfheader.file_count; i++)
20346c95142eSMartin Matuska 			archive_string_free(&(hd->file_array[i].pathname));
20356c95142eSMartin Matuska 		free(hd->file_array);
20366c95142eSMartin Matuska 	}
20376c95142eSMartin Matuska #ifdef HAVE_ZLIB_H
20386c95142eSMartin Matuska 	if (cab->stream_valid)
20396c95142eSMartin Matuska 		inflateEnd(&cab->stream);
20406c95142eSMartin Matuska #endif
20416c95142eSMartin Matuska 	lzx_decode_free(&cab->xstrm);
20426c95142eSMartin Matuska 	archive_wstring_free(&cab->ws);
20436c95142eSMartin Matuska 	free(cab->uncompressed_buffer);
20446c95142eSMartin Matuska 	free(cab);
20456c95142eSMartin Matuska 	(a->format->data) = NULL;
20466c95142eSMartin Matuska 	return (ARCHIVE_OK);
20476c95142eSMartin Matuska }
20486c95142eSMartin Matuska 
20496c95142eSMartin Matuska /* Convert an MSDOS-style date/time into Unix-style time. */
20506c95142eSMartin Matuska static time_t
20516c95142eSMartin Matuska cab_dos_time(const unsigned char *p)
20526c95142eSMartin Matuska {
20536c95142eSMartin Matuska 	int msTime, msDate;
20546c95142eSMartin Matuska 	struct tm ts;
20556c95142eSMartin Matuska 
20566c95142eSMartin Matuska 	msDate = archive_le16dec(p);
20576c95142eSMartin Matuska 	msTime = archive_le16dec(p+2);
20586c95142eSMartin Matuska 
20596c95142eSMartin Matuska 	memset(&ts, 0, sizeof(ts));
20606c95142eSMartin Matuska 	ts.tm_year = ((msDate >> 9) & 0x7f) + 80;   /* Years since 1900. */
20616c95142eSMartin Matuska 	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1;     /* Month number.     */
20626c95142eSMartin Matuska 	ts.tm_mday = msDate & 0x1f;		    /* Day of month.     */
20636c95142eSMartin Matuska 	ts.tm_hour = (msTime >> 11) & 0x1f;
20646c95142eSMartin Matuska 	ts.tm_min = (msTime >> 5) & 0x3f;
20656c95142eSMartin Matuska 	ts.tm_sec = (msTime << 1) & 0x3e;
20666c95142eSMartin Matuska 	ts.tm_isdst = -1;
20676c95142eSMartin Matuska 	return (mktime(&ts));
20686c95142eSMartin Matuska }
20696c95142eSMartin Matuska 
20706c95142eSMartin Matuska /*****************************************************************
20716c95142eSMartin Matuska  *
20726c95142eSMartin Matuska  * LZX decompression code.
20736c95142eSMartin Matuska  *
20746c95142eSMartin Matuska  *****************************************************************/
20756c95142eSMartin Matuska 
20766c95142eSMartin Matuska /*
20776c95142eSMartin Matuska  * Initialize LZX decoder.
20786c95142eSMartin Matuska  *
20796c95142eSMartin Matuska  * Returns ARCHIVE_OK if initialization was successful.
20806c95142eSMartin Matuska  * Returns ARCHIVE_FAILED if w_bits has unsupported value.
20816c95142eSMartin Matuska  * Returns ARCHIVE_FATAL if initialization failed; memory allocation
20826c95142eSMartin Matuska  * error occurred.
20836c95142eSMartin Matuska  */
20846c95142eSMartin Matuska static int
20856c95142eSMartin Matuska lzx_decode_init(struct lzx_stream *strm, int w_bits)
20866c95142eSMartin Matuska {
20876c95142eSMartin Matuska 	struct lzx_dec *ds;
20886c95142eSMartin Matuska 	int slot, w_size, w_slot;
20896c95142eSMartin Matuska 	int base, footer;
20906c95142eSMartin Matuska 	int base_inc[18];
20916c95142eSMartin Matuska 
20926c95142eSMartin Matuska 	if (strm->ds == NULL) {
20936c95142eSMartin Matuska 		strm->ds = calloc(1, sizeof(*strm->ds));
20946c95142eSMartin Matuska 		if (strm->ds == NULL)
20956c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
20966c95142eSMartin Matuska 	}
20976c95142eSMartin Matuska 	ds = strm->ds;
20986c95142eSMartin Matuska 	ds->error = ARCHIVE_FAILED;
20996c95142eSMartin Matuska 
21006c95142eSMartin Matuska 	/* Allow bits from 15(32KBi) up to 21(2MBi) */
21016c95142eSMartin Matuska 	if (w_bits < SLOT_BASE || w_bits > SLOT_MAX)
21026c95142eSMartin Matuska 		return (ARCHIVE_FAILED);
21036c95142eSMartin Matuska 
21046c95142eSMartin Matuska 	ds->error = ARCHIVE_FATAL;
21056c95142eSMartin Matuska 
21066c95142eSMartin Matuska 	/*
21076c95142eSMartin Matuska 	 * Alloc window
21086c95142eSMartin Matuska 	 */
21096c95142eSMartin Matuska 	w_size = ds->w_size;
21106c95142eSMartin Matuska 	w_slot = slots[w_bits - SLOT_BASE];
21116c95142eSMartin Matuska 	ds->w_size = 1U << w_bits;
21126c95142eSMartin Matuska 	ds->w_mask = ds->w_size -1;
21136c95142eSMartin Matuska 	if (ds->w_buff == NULL || w_size != ds->w_size) {
21146c95142eSMartin Matuska 		free(ds->w_buff);
21156c95142eSMartin Matuska 		ds->w_buff = malloc(ds->w_size);
21166c95142eSMartin Matuska 		if (ds->w_buff == NULL)
21176c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
21186c95142eSMartin Matuska 		free(ds->pos_tbl);
21196c95142eSMartin Matuska 		ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
21206c95142eSMartin Matuska 		if (ds->pos_tbl == NULL)
21216c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
21226c95142eSMartin Matuska 		lzx_huffman_free(&(ds->mt));
21236c95142eSMartin Matuska 	}
21246c95142eSMartin Matuska 
21256c95142eSMartin Matuska 	for (footer = 0; footer < 18; footer++)
21266c95142eSMartin Matuska 		base_inc[footer] = 1 << footer;
21276c95142eSMartin Matuska 	base = footer = 0;
21286c95142eSMartin Matuska 	for (slot = 0; slot < w_slot; slot++) {
21296c95142eSMartin Matuska 		int n;
21306c95142eSMartin Matuska 		if (footer == 0)
21316c95142eSMartin Matuska 			base = slot;
21326c95142eSMartin Matuska 		else
21336c95142eSMartin Matuska 			base += base_inc[footer];
21346c95142eSMartin Matuska 		if (footer < 17) {
21356c95142eSMartin Matuska 			footer = -2;
21366c95142eSMartin Matuska 			for (n = base; n; n >>= 1)
21376c95142eSMartin Matuska 				footer++;
21386c95142eSMartin Matuska 			if (footer <= 0)
21396c95142eSMartin Matuska 				footer = 0;
21406c95142eSMartin Matuska 		}
21416c95142eSMartin Matuska 		ds->pos_tbl[slot].base = base;
21426c95142eSMartin Matuska 		ds->pos_tbl[slot].footer_bits = footer;
21436c95142eSMartin Matuska 	}
21446c95142eSMartin Matuska 
21456c95142eSMartin Matuska 	ds->w_pos = 0;
21466c95142eSMartin Matuska 	ds->state = 0;
21476c95142eSMartin Matuska 	ds->br.cache_buffer = 0;
21486c95142eSMartin Matuska 	ds->br.cache_avail = 0;
21496c95142eSMartin Matuska 	ds->r0 = ds->r1 = ds->r2 = 1;
21506c95142eSMartin Matuska 
21516c95142eSMartin Matuska 	/* Initialize aligned offset tree. */
21526c95142eSMartin Matuska 	if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK)
21536c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
21546c95142eSMartin Matuska 
21556c95142eSMartin Matuska 	/* Initialize pre-tree. */
21566c95142eSMartin Matuska 	if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK)
21576c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
21586c95142eSMartin Matuska 
21596c95142eSMartin Matuska 	/* Initialize Main tree. */
21606c95142eSMartin Matuska 	if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16)
21616c95142eSMartin Matuska 	    != ARCHIVE_OK)
21626c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
21636c95142eSMartin Matuska 
21646c95142eSMartin Matuska 	/* Initialize Length tree. */
21656c95142eSMartin Matuska 	if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK)
21666c95142eSMartin Matuska 		return (ARCHIVE_FATAL);
21676c95142eSMartin Matuska 
21686c95142eSMartin Matuska 	ds->error = 0;
21696c95142eSMartin Matuska 
21706c95142eSMartin Matuska 	return (ARCHIVE_OK);
21716c95142eSMartin Matuska }
21726c95142eSMartin Matuska 
21736c95142eSMartin Matuska /*
21746c95142eSMartin Matuska  * Release LZX decoder.
21756c95142eSMartin Matuska  */
21766c95142eSMartin Matuska static void
21776c95142eSMartin Matuska lzx_decode_free(struct lzx_stream *strm)
21786c95142eSMartin Matuska {
21796c95142eSMartin Matuska 
21806c95142eSMartin Matuska 	if (strm->ds == NULL)
21816c95142eSMartin Matuska 		return;
21826c95142eSMartin Matuska 	free(strm->ds->w_buff);
21836c95142eSMartin Matuska 	free(strm->ds->pos_tbl);
21846c95142eSMartin Matuska 	lzx_huffman_free(&(strm->ds->at));
21856c95142eSMartin Matuska 	lzx_huffman_free(&(strm->ds->pt));
21866c95142eSMartin Matuska 	lzx_huffman_free(&(strm->ds->mt));
21876c95142eSMartin Matuska 	lzx_huffman_free(&(strm->ds->lt));
21886c95142eSMartin Matuska 	free(strm->ds);
21896c95142eSMartin Matuska 	strm->ds = NULL;
21906c95142eSMartin Matuska }
21916c95142eSMartin Matuska 
21926c95142eSMartin Matuska /*
21936c95142eSMartin Matuska  * E8 Call Translation reversal.
21946c95142eSMartin Matuska  */
21956c95142eSMartin Matuska static void
21966c95142eSMartin Matuska lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
21976c95142eSMartin Matuska {
21986c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
21996c95142eSMartin Matuska 	unsigned char *b, *end;
22006c95142eSMartin Matuska 
22016c95142eSMartin Matuska 	if (!ds->translation || size <= 10)
22026c95142eSMartin Matuska 		return;
22036c95142eSMartin Matuska 	b = p;
22046c95142eSMartin Matuska 	end = b + size - 10;
22056c95142eSMartin Matuska 	while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) {
22066c95142eSMartin Matuska 		size_t i = b - (unsigned char *)p;
22076c95142eSMartin Matuska 		int32_t cp, displacement, value;
22086c95142eSMartin Matuska 
2209acc60b03SMartin Matuska 		cp = (int32_t)(offset + (uint32_t)i);
22106c95142eSMartin Matuska 		value = archive_le32dec(&b[1]);
22116c95142eSMartin Matuska 		if (value >= -cp && value < (int32_t)ds->translation_size) {
22126c95142eSMartin Matuska 			if (value >= 0)
22136c95142eSMartin Matuska 				displacement = value - cp;
22146c95142eSMartin Matuska 			else
22156c95142eSMartin Matuska 				displacement = value + ds->translation_size;
22166c95142eSMartin Matuska 			archive_le32enc(&b[1], (uint32_t)displacement);
22176c95142eSMartin Matuska 		}
22186c95142eSMartin Matuska 		b += 5;
22196c95142eSMartin Matuska 	}
22206c95142eSMartin Matuska }
22216c95142eSMartin Matuska 
22226c95142eSMartin Matuska /*
22236c95142eSMartin Matuska  * Bit stream reader.
22246c95142eSMartin Matuska  */
22256c95142eSMartin Matuska /* Check that the cache buffer has enough bits. */
22266c95142eSMartin Matuska #define lzx_br_has(br, n)	((br)->cache_avail >= n)
22276c95142eSMartin Matuska /* Get compressed data by bit. */
22286c95142eSMartin Matuska #define lzx_br_bits(br, n)				\
22296c95142eSMartin Matuska 	(((uint32_t)((br)->cache_buffer >>		\
22306c95142eSMartin Matuska 		((br)->cache_avail - (n)))) & cache_masks[n])
22316c95142eSMartin Matuska #define lzx_br_bits_forced(br, n)			\
22326c95142eSMartin Matuska 	(((uint32_t)((br)->cache_buffer <<		\
22336c95142eSMartin Matuska 		((n) - (br)->cache_avail))) & cache_masks[n])
22346c95142eSMartin Matuska /* Read ahead to make sure the cache buffer has enough compressed data we
22356c95142eSMartin Matuska  * will use.
22366c95142eSMartin Matuska  *  True  : completed, there is enough data in the cache buffer.
22376c95142eSMartin Matuska  *  False : we met that strm->next_in is empty, we have to get following
22386c95142eSMartin Matuska  *          bytes. */
22396c95142eSMartin Matuska #define lzx_br_read_ahead_0(strm, br, n)	\
22406c95142eSMartin Matuska 	(lzx_br_has((br), (n)) || lzx_br_fillup(strm, br))
22416c95142eSMartin Matuska /*  True  : the cache buffer has some bits as much as we need.
22426c95142eSMartin Matuska  *  False : there are no enough bits in the cache buffer to be used,
22436c95142eSMartin Matuska  *          we have to get following bytes if we could. */
22446c95142eSMartin Matuska #define lzx_br_read_ahead(strm, br, n)	\
22456c95142eSMartin Matuska 	(lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n)))
22466c95142eSMartin Matuska 
22476c95142eSMartin Matuska /* Notify how many bits we consumed. */
22486c95142eSMartin Matuska #define lzx_br_consume(br, n)	((br)->cache_avail -= (n))
2249fd082e96SMartin Matuska #define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f)
2250fd082e96SMartin Matuska 
2251fd082e96SMartin Matuska #define lzx_br_is_unaligned(br)	((br)->cache_avail & 0x0f)
22526c95142eSMartin Matuska 
22536c95142eSMartin Matuska static const uint32_t cache_masks[] = {
22546c95142eSMartin Matuska 	0x00000000, 0x00000001, 0x00000003, 0x00000007,
22556c95142eSMartin Matuska 	0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
22566c95142eSMartin Matuska 	0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
22576c95142eSMartin Matuska 	0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
22586c95142eSMartin Matuska 	0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
22596c95142eSMartin Matuska 	0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
22606c95142eSMartin Matuska 	0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
22616c95142eSMartin Matuska 	0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
22626c95142eSMartin Matuska 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
22636c95142eSMartin Matuska };
22646c95142eSMartin Matuska 
22656c95142eSMartin Matuska /*
22666c95142eSMartin Matuska  * Shift away used bits in the cache data and fill it up with following bits.
22676c95142eSMartin Matuska  * Call this when cache buffer does not have enough bits you need.
22686c95142eSMartin Matuska  *
22696c95142eSMartin Matuska  * Returns 1 if the cache buffer is full.
22706c95142eSMartin Matuska  * Returns 0 if the cache buffer is not full; input buffer is empty.
22716c95142eSMartin Matuska  */
22726c95142eSMartin Matuska static int
22736c95142eSMartin Matuska lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
22746c95142eSMartin Matuska {
22756c95142eSMartin Matuska /*
2276a2e802b7SMartin Matuska  * x86 processor family can read misaligned data without an access error.
22776c95142eSMartin Matuska  */
22786c95142eSMartin Matuska 	int n = CACHE_BITS - br->cache_avail;
22796c95142eSMartin Matuska 
22806c95142eSMartin Matuska 	for (;;) {
22816c95142eSMartin Matuska 		switch (n >> 4) {
22826c95142eSMartin Matuska 		case 4:
22836c95142eSMartin Matuska 			if (strm->avail_in >= 8) {
22846c95142eSMartin Matuska 				br->cache_buffer =
22856c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[1]) << 56 |
22866c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[0]) << 48 |
22876c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[3]) << 40 |
22886c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[2]) << 32 |
22896c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[5]) << 24 |
22906c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[4]) << 16 |
22916c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[7]) << 8 |
22926c95142eSMartin Matuska 				     (uint32_t)strm->next_in[6];
22936c95142eSMartin Matuska 				strm->next_in += 8;
22946c95142eSMartin Matuska 				strm->avail_in -= 8;
22956c95142eSMartin Matuska 				br->cache_avail += 8 * 8;
22966c95142eSMartin Matuska 				return (1);
22976c95142eSMartin Matuska 			}
22986c95142eSMartin Matuska 			break;
22996c95142eSMartin Matuska 		case 3:
23006c95142eSMartin Matuska 			if (strm->avail_in >= 6) {
23016c95142eSMartin Matuska 				br->cache_buffer =
23026c95142eSMartin Matuska 		 		   (br->cache_buffer << 48) |
23036c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[1]) << 40 |
23046c95142eSMartin Matuska 				    ((uint64_t)strm->next_in[0]) << 32 |
23056c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[3]) << 24 |
23066c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[2]) << 16 |
23076c95142eSMartin Matuska 				    ((uint32_t)strm->next_in[5]) << 8 |
23086c95142eSMartin Matuska 				     (uint32_t)strm->next_in[4];
23096c95142eSMartin Matuska 				strm->next_in += 6;
23106c95142eSMartin Matuska 				strm->avail_in -= 6;
23116c95142eSMartin Matuska 				br->cache_avail += 6 * 8;
23126c95142eSMartin Matuska 				return (1);
23136c95142eSMartin Matuska 			}
23146c95142eSMartin Matuska 			break;
23156c95142eSMartin Matuska 		case 0:
23166c95142eSMartin Matuska 			/* We have enough compressed data in
23176c95142eSMartin Matuska 			 * the cache buffer.*/
23186c95142eSMartin Matuska 			return (1);
23196c95142eSMartin Matuska 		default:
23206c95142eSMartin Matuska 			break;
23216c95142eSMartin Matuska 		}
23226c95142eSMartin Matuska 		if (strm->avail_in < 2) {
23236c95142eSMartin Matuska 			/* There is not enough compressed data to
23246c95142eSMartin Matuska 			 * fill up the cache buffer. */
23256c95142eSMartin Matuska 			if (strm->avail_in == 1) {
23266c95142eSMartin Matuska 				br->odd = *strm->next_in++;
23276c95142eSMartin Matuska 				strm->avail_in--;
23286c95142eSMartin Matuska 				br->have_odd = 1;
23296c95142eSMartin Matuska 			}
23306c95142eSMartin Matuska 			return (0);
23316c95142eSMartin Matuska 		}
23326c95142eSMartin Matuska 		br->cache_buffer =
23336c95142eSMartin Matuska 		   (br->cache_buffer << 16) |
23346c95142eSMartin Matuska 		    archive_le16dec(strm->next_in);
23356c95142eSMartin Matuska 		strm->next_in += 2;
23366c95142eSMartin Matuska 		strm->avail_in -= 2;
23376c95142eSMartin Matuska 		br->cache_avail += 16;
23386c95142eSMartin Matuska 		n -= 16;
23396c95142eSMartin Matuska 	}
23406c95142eSMartin Matuska }
23416c95142eSMartin Matuska 
23426c95142eSMartin Matuska static void
23436c95142eSMartin Matuska lzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br)
23446c95142eSMartin Matuska {
23456c95142eSMartin Matuska 	int n = CACHE_BITS - br->cache_avail;
23466c95142eSMartin Matuska 
23476c95142eSMartin Matuska 	if (br->have_odd && n >= 16 && strm->avail_in > 0) {
23486c95142eSMartin Matuska 		br->cache_buffer =
23496c95142eSMartin Matuska 		   (br->cache_buffer << 16) |
23506c95142eSMartin Matuska 		   ((uint16_t)(*strm->next_in)) << 8 | br->odd;
23516c95142eSMartin Matuska 		strm->next_in++;
23526c95142eSMartin Matuska 		strm->avail_in--;
23536c95142eSMartin Matuska 		br->cache_avail += 16;
23546c95142eSMartin Matuska 		br->have_odd = 0;
23556c95142eSMartin Matuska 	}
23566c95142eSMartin Matuska }
23576c95142eSMartin Matuska 
23586c95142eSMartin Matuska static void
23596c95142eSMartin Matuska lzx_cleanup_bitstream(struct lzx_stream *strm)
23606c95142eSMartin Matuska {
23616c95142eSMartin Matuska 	strm->ds->br.cache_avail = 0;
23626c95142eSMartin Matuska 	strm->ds->br.have_odd = 0;
23636c95142eSMartin Matuska }
23646c95142eSMartin Matuska 
23656c95142eSMartin Matuska /*
23666c95142eSMartin Matuska  * Decode LZX.
23676c95142eSMartin Matuska  *
23686c95142eSMartin Matuska  * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty.
23696c95142eSMartin Matuska  *    Please set available buffer and call this function again.
23706c95142eSMartin Matuska  * 2. Returns ARCHIVE_EOF if decompression has been completed.
23716c95142eSMartin Matuska  * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data
23726c95142eSMartin Matuska  *    is broken or you do not set 'last' flag properly.
23736c95142eSMartin Matuska  */
23746c95142eSMartin Matuska #define ST_RD_TRANSLATION	0
23756c95142eSMartin Matuska #define ST_RD_TRANSLATION_SIZE	1
23766c95142eSMartin Matuska #define ST_RD_BLOCK_TYPE	2
23776c95142eSMartin Matuska #define ST_RD_BLOCK_SIZE	3
2378fd082e96SMartin Matuska #define ST_RD_ALIGNMENT		4
2379fd082e96SMartin Matuska #define ST_RD_R0		5
2380fd082e96SMartin Matuska #define ST_RD_R1		6
2381fd082e96SMartin Matuska #define ST_RD_R2		7
2382fd082e96SMartin Matuska #define ST_COPY_UNCOMP1		8
2383fd082e96SMartin Matuska #define ST_COPY_UNCOMP2		9
2384fd082e96SMartin Matuska #define ST_RD_ALIGNED_OFFSET	10
2385fd082e96SMartin Matuska #define ST_RD_VERBATIM		11
2386fd082e96SMartin Matuska #define ST_RD_PRE_MAIN_TREE_256	12
2387fd082e96SMartin Matuska #define ST_MAIN_TREE_256	13
2388fd082e96SMartin Matuska #define ST_RD_PRE_MAIN_TREE_REM	14
2389fd082e96SMartin Matuska #define ST_MAIN_TREE_REM	15
2390fd082e96SMartin Matuska #define ST_RD_PRE_LENGTH_TREE	16
2391fd082e96SMartin Matuska #define ST_LENGTH_TREE		17
2392fd082e96SMartin Matuska #define ST_MAIN			18
2393fd082e96SMartin Matuska #define ST_LENGTH		19
2394fd082e96SMartin Matuska #define ST_OFFSET		20
2395fd082e96SMartin Matuska #define ST_REAL_POS		21
2396fd082e96SMartin Matuska #define ST_COPY			22
23976c95142eSMartin Matuska 
23986c95142eSMartin Matuska static int
23996c95142eSMartin Matuska lzx_decode(struct lzx_stream *strm, int last)
24006c95142eSMartin Matuska {
24016c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
24026c95142eSMartin Matuska 	int64_t avail_in;
24036c95142eSMartin Matuska 	int r;
24046c95142eSMartin Matuska 
24056c95142eSMartin Matuska 	if (ds->error)
24066c95142eSMartin Matuska 		return (ds->error);
24076c95142eSMartin Matuska 
24086c95142eSMartin Matuska 	avail_in = strm->avail_in;
24096c95142eSMartin Matuska 	lzx_br_fixup(strm, &(ds->br));
24106c95142eSMartin Matuska 	do {
24116c95142eSMartin Matuska 		if (ds->state < ST_MAIN)
24126c95142eSMartin Matuska 			r = lzx_read_blocks(strm, last);
24136c95142eSMartin Matuska 		else {
24146c95142eSMartin Matuska 			int64_t bytes_written = strm->avail_out;
24156c95142eSMartin Matuska 			r = lzx_decode_blocks(strm, last);
24166c95142eSMartin Matuska 			bytes_written -= strm->avail_out;
24176c95142eSMartin Matuska 			strm->next_out += bytes_written;
24186c95142eSMartin Matuska 			strm->total_out += bytes_written;
24196c95142eSMartin Matuska 		}
24206c95142eSMartin Matuska 	} while (r == 100);
24216c95142eSMartin Matuska 	strm->total_in += avail_in - strm->avail_in;
24226c95142eSMartin Matuska 	return (r);
24236c95142eSMartin Matuska }
24246c95142eSMartin Matuska 
24256c95142eSMartin Matuska static int
24266c95142eSMartin Matuska lzx_read_blocks(struct lzx_stream *strm, int last)
24276c95142eSMartin Matuska {
24286c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
24296c95142eSMartin Matuska 	struct lzx_br *br = &(ds->br);
24306c95142eSMartin Matuska 	int i, r;
24316c95142eSMartin Matuska 
24326c95142eSMartin Matuska 	for (;;) {
24336c95142eSMartin Matuska 		switch (ds->state) {
24346c95142eSMartin Matuska 		case ST_RD_TRANSLATION:
24356c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, 1)) {
24366c95142eSMartin Matuska 				ds->state = ST_RD_TRANSLATION;
24376c95142eSMartin Matuska 				if (last)
24386c95142eSMartin Matuska 					goto failed;
24396c95142eSMartin Matuska 				return (ARCHIVE_OK);
24406c95142eSMartin Matuska 			}
24416c95142eSMartin Matuska 			ds->translation = lzx_br_bits(br, 1);
24426c95142eSMartin Matuska 			lzx_br_consume(br, 1);
24436c95142eSMartin Matuska 			/* FALL THROUGH */
24446c95142eSMartin Matuska 		case ST_RD_TRANSLATION_SIZE:
24456c95142eSMartin Matuska 			if (ds->translation) {
24466c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, br, 32)) {
24476c95142eSMartin Matuska 					ds->state = ST_RD_TRANSLATION_SIZE;
24486c95142eSMartin Matuska 					if (last)
24496c95142eSMartin Matuska 						goto failed;
24506c95142eSMartin Matuska 					return (ARCHIVE_OK);
24516c95142eSMartin Matuska 				}
24526c95142eSMartin Matuska 				ds->translation_size = lzx_br_bits(br, 16);
24536c95142eSMartin Matuska 				lzx_br_consume(br, 16);
24546c95142eSMartin Matuska 				ds->translation_size <<= 16;
24556c95142eSMartin Matuska 				ds->translation_size |= lzx_br_bits(br, 16);
24566c95142eSMartin Matuska 				lzx_br_consume(br, 16);
24576c95142eSMartin Matuska 			}
24586c95142eSMartin Matuska 			/* FALL THROUGH */
24596c95142eSMartin Matuska 		case ST_RD_BLOCK_TYPE:
24606c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, 3)) {
24616c95142eSMartin Matuska 				ds->state = ST_RD_BLOCK_TYPE;
24626c95142eSMartin Matuska 				if (last)
24636c95142eSMartin Matuska 					goto failed;
24646c95142eSMartin Matuska 				return (ARCHIVE_OK);
24656c95142eSMartin Matuska 			}
24666c95142eSMartin Matuska 			ds->block_type = lzx_br_bits(br, 3);
24676c95142eSMartin Matuska 			lzx_br_consume(br, 3);
24686c95142eSMartin Matuska 			/* Check a block type. */
24696c95142eSMartin Matuska 			switch (ds->block_type) {
24706c95142eSMartin Matuska 			case VERBATIM_BLOCK:
24716c95142eSMartin Matuska 			case ALIGNED_OFFSET_BLOCK:
24726c95142eSMartin Matuska 			case UNCOMPRESSED_BLOCK:
24736c95142eSMartin Matuska 				break;
24746c95142eSMartin Matuska 			default:
24756c95142eSMartin Matuska 				goto failed;/* Invalid */
24766c95142eSMartin Matuska 			}
24776c95142eSMartin Matuska 			/* FALL THROUGH */
24786c95142eSMartin Matuska 		case ST_RD_BLOCK_SIZE:
24796c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, 24)) {
24806c95142eSMartin Matuska 				ds->state = ST_RD_BLOCK_SIZE;
24816c95142eSMartin Matuska 				if (last)
24826c95142eSMartin Matuska 					goto failed;
24836c95142eSMartin Matuska 				return (ARCHIVE_OK);
24846c95142eSMartin Matuska 			}
24856c95142eSMartin Matuska 			ds->block_size = lzx_br_bits(br, 8);
24866c95142eSMartin Matuska 			lzx_br_consume(br, 8);
24876c95142eSMartin Matuska 			ds->block_size <<= 16;
24886c95142eSMartin Matuska 			ds->block_size |= lzx_br_bits(br, 16);
24896c95142eSMartin Matuska 			lzx_br_consume(br, 16);
24906c95142eSMartin Matuska 			if (ds->block_size == 0)
24916c95142eSMartin Matuska 				goto failed;
24926c95142eSMartin Matuska 			ds->block_bytes_avail = ds->block_size;
24936c95142eSMartin Matuska 			if (ds->block_type != UNCOMPRESSED_BLOCK) {
24946c95142eSMartin Matuska 				if (ds->block_type == VERBATIM_BLOCK)
24956c95142eSMartin Matuska 					ds->state = ST_RD_VERBATIM;
24966c95142eSMartin Matuska 				else
24976c95142eSMartin Matuska 					ds->state = ST_RD_ALIGNED_OFFSET;
24986c95142eSMartin Matuska 				break;
24996c95142eSMartin Matuska 			}
2500fd082e96SMartin Matuska 			/* FALL THROUGH */
2501fd082e96SMartin Matuska 		case ST_RD_ALIGNMENT:
25026c95142eSMartin Matuska 			/*
25036c95142eSMartin Matuska 			 * Handle an Uncompressed Block.
25046c95142eSMartin Matuska 			 */
25056c95142eSMartin Matuska 			/* Skip padding to align following field on
25066c95142eSMartin Matuska 			 * 16-bit boundary. */
2507fd082e96SMartin Matuska 			if (lzx_br_is_unaligned(br))
2508fd082e96SMartin Matuska 				lzx_br_consume_unaligned_bits(br);
2509fd082e96SMartin Matuska 			else {
2510fd082e96SMartin Matuska 				if (lzx_br_read_ahead(strm, br, 16))
25116c95142eSMartin Matuska 					lzx_br_consume(br, 16);
2512fd082e96SMartin Matuska 				else {
2513fd082e96SMartin Matuska 					ds->state = ST_RD_ALIGNMENT;
2514fd082e96SMartin Matuska 					if (last)
2515fd082e96SMartin Matuska 						goto failed;
2516fd082e96SMartin Matuska 					return (ARCHIVE_OK);
2517fd082e96SMartin Matuska 				}
2518fd082e96SMartin Matuska 			}
25196c95142eSMartin Matuska 			/* Preparation to read repeated offsets R0,R1 and R2. */
25206c95142eSMartin Matuska 			ds->rbytes_avail = 0;
25216c95142eSMartin Matuska 			ds->state = ST_RD_R0;
25226c95142eSMartin Matuska 			/* FALL THROUGH */
25236c95142eSMartin Matuska 		case ST_RD_R0:
25246c95142eSMartin Matuska 		case ST_RD_R1:
25256c95142eSMartin Matuska 		case ST_RD_R2:
25266c95142eSMartin Matuska 			do {
25276c95142eSMartin Matuska 				uint16_t u16;
25286c95142eSMartin Matuska 				/* Drain bits in the cache buffer of
25296c95142eSMartin Matuska 				 * bit-stream. */
25306c95142eSMartin Matuska 				if (lzx_br_has(br, 32)) {
25316c95142eSMartin Matuska 					u16 = lzx_br_bits(br, 16);
25326c95142eSMartin Matuska 					lzx_br_consume(br, 16);
25336c95142eSMartin Matuska 					archive_le16enc(ds->rbytes, u16);
25346c95142eSMartin Matuska 					u16 = lzx_br_bits(br, 16);
25356c95142eSMartin Matuska 					lzx_br_consume(br, 16);
25366c95142eSMartin Matuska 					archive_le16enc(ds->rbytes+2, u16);
25376c95142eSMartin Matuska 					ds->rbytes_avail = 4;
25386c95142eSMartin Matuska 				} else if (lzx_br_has(br, 16)) {
25396c95142eSMartin Matuska 					u16 = lzx_br_bits(br, 16);
25406c95142eSMartin Matuska 					lzx_br_consume(br, 16);
25416c95142eSMartin Matuska 					archive_le16enc(ds->rbytes, u16);
25426c95142eSMartin Matuska 					ds->rbytes_avail = 2;
2543fd082e96SMartin Matuska 				}
25446c95142eSMartin Matuska 				if (ds->rbytes_avail < 4 && ds->br.have_odd) {
25456c95142eSMartin Matuska 					ds->rbytes[ds->rbytes_avail++] =
25466c95142eSMartin Matuska 					    ds->br.odd;
25476c95142eSMartin Matuska 					ds->br.have_odd = 0;
25486c95142eSMartin Matuska 				}
25496c95142eSMartin Matuska 				while (ds->rbytes_avail < 4) {
25506c95142eSMartin Matuska 					if (strm->avail_in <= 0) {
25516c95142eSMartin Matuska 						if (last)
25526c95142eSMartin Matuska 							goto failed;
25536c95142eSMartin Matuska 						return (ARCHIVE_OK);
25546c95142eSMartin Matuska 					}
25556c95142eSMartin Matuska 					ds->rbytes[ds->rbytes_avail++] =
25566c95142eSMartin Matuska 					    *strm->next_in++;
25576c95142eSMartin Matuska 					strm->avail_in--;
25586c95142eSMartin Matuska 				}
2559fd082e96SMartin Matuska 				ds->rbytes_avail = 0;
25606c95142eSMartin Matuska 				if (ds->state == ST_RD_R0) {
25616c95142eSMartin Matuska 					ds->r0 = archive_le32dec(ds->rbytes);
25626c95142eSMartin Matuska 					if (ds->r0 < 0)
25636c95142eSMartin Matuska 						goto failed;
25646c95142eSMartin Matuska 					ds->state = ST_RD_R1;
25656c95142eSMartin Matuska 				} else if (ds->state == ST_RD_R1) {
25666c95142eSMartin Matuska 					ds->r1 = archive_le32dec(ds->rbytes);
25676c95142eSMartin Matuska 					if (ds->r1 < 0)
25686c95142eSMartin Matuska 						goto failed;
25696c95142eSMartin Matuska 					ds->state = ST_RD_R2;
25706c95142eSMartin Matuska 				} else if (ds->state == ST_RD_R2) {
25716c95142eSMartin Matuska 					ds->r2 = archive_le32dec(ds->rbytes);
25726c95142eSMartin Matuska 					if (ds->r2 < 0)
25736c95142eSMartin Matuska 						goto failed;
25746c95142eSMartin Matuska 					/* We've gotten all repeated offsets. */
25756c95142eSMartin Matuska 					ds->state = ST_COPY_UNCOMP1;
25766c95142eSMartin Matuska 				}
25776c95142eSMartin Matuska 			} while (ds->state != ST_COPY_UNCOMP1);
25786c95142eSMartin Matuska 			/* FALL THROUGH */
25796c95142eSMartin Matuska 		case ST_COPY_UNCOMP1:
25806c95142eSMartin Matuska 			/*
25816c95142eSMartin Matuska 			 * Copy bytes form next_in to next_out directly.
25826c95142eSMartin Matuska 			 */
25836c95142eSMartin Matuska 			while (ds->block_bytes_avail) {
2584fd082e96SMartin Matuska 				int l;
25856c95142eSMartin Matuska 
25866c95142eSMartin Matuska 				if (strm->avail_out <= 0)
25876c95142eSMartin Matuska 					/* Output buffer is empty. */
25886c95142eSMartin Matuska 					return (ARCHIVE_OK);
25896c95142eSMartin Matuska 				if (strm->avail_in <= 0) {
25906c95142eSMartin Matuska 					/* Input buffer is empty. */
25916c95142eSMartin Matuska 					if (last)
25926c95142eSMartin Matuska 						goto failed;
25936c95142eSMartin Matuska 					return (ARCHIVE_OK);
25946c95142eSMartin Matuska 				}
2595acc60b03SMartin Matuska 				l = (int)ds->block_bytes_avail;
25966c95142eSMartin Matuska 				if (l > ds->w_size - ds->w_pos)
25976c95142eSMartin Matuska 					l = ds->w_size - ds->w_pos;
25986c95142eSMartin Matuska 				if (l > strm->avail_out)
25996c95142eSMartin Matuska 					l = (int)strm->avail_out;
26006c95142eSMartin Matuska 				if (l > strm->avail_in)
26016c95142eSMartin Matuska 					l = (int)strm->avail_in;
2602fd082e96SMartin Matuska 				memcpy(strm->next_out, strm->next_in, l);
2603fd082e96SMartin Matuska 				memcpy(&(ds->w_buff[ds->w_pos]),
2604fd082e96SMartin Matuska 				    strm->next_in, l);
2605fd082e96SMartin Matuska 				strm->next_in += l;
2606fd082e96SMartin Matuska 				strm->avail_in -= l;
2607fd082e96SMartin Matuska 				strm->next_out += l;
2608fd082e96SMartin Matuska 				strm->avail_out -= l;
2609fd082e96SMartin Matuska 				strm->total_out += l;
2610fd082e96SMartin Matuska 				ds->w_pos = (ds->w_pos + l) & ds->w_mask;
2611fd082e96SMartin Matuska 				ds->block_bytes_avail -= l;
26126c95142eSMartin Matuska 			}
26136c95142eSMartin Matuska 			/* FALL THROUGH */
26146c95142eSMartin Matuska 		case ST_COPY_UNCOMP2:
26156c95142eSMartin Matuska 			/* Re-align; skip padding byte. */
26166c95142eSMartin Matuska 			if (ds->block_size & 1) {
26176c95142eSMartin Matuska 				if (strm->avail_in <= 0) {
26186c95142eSMartin Matuska 					/* Input buffer is empty. */
26196c95142eSMartin Matuska 					ds->state = ST_COPY_UNCOMP2;
26206c95142eSMartin Matuska 					if (last)
26216c95142eSMartin Matuska 						goto failed;
26226c95142eSMartin Matuska 					return (ARCHIVE_OK);
26236c95142eSMartin Matuska 				}
26246c95142eSMartin Matuska 				strm->next_in++;
26256c95142eSMartin Matuska 				strm->avail_in --;
26266c95142eSMartin Matuska 			}
26276c95142eSMartin Matuska 			/* This block ended. */
26286c95142eSMartin Matuska 			ds->state = ST_RD_BLOCK_TYPE;
26296c95142eSMartin Matuska 			return (ARCHIVE_EOF);
26306c95142eSMartin Matuska 			/********************/
26316c95142eSMartin Matuska 		case ST_RD_ALIGNED_OFFSET:
26326c95142eSMartin Matuska 			/*
26336c95142eSMartin Matuska 			 * Read Aligned offset tree.
26346c95142eSMartin Matuska 			 */
26356c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) {
26366c95142eSMartin Matuska 				ds->state = ST_RD_ALIGNED_OFFSET;
26376c95142eSMartin Matuska 				if (last)
26386c95142eSMartin Matuska 					goto failed;
26396c95142eSMartin Matuska 				return (ARCHIVE_OK);
26406c95142eSMartin Matuska 			}
26416c95142eSMartin Matuska 			memset(ds->at.freq, 0, sizeof(ds->at.freq));
26426c95142eSMartin Matuska 			for (i = 0; i < ds->at.len_size; i++) {
26436c95142eSMartin Matuska 				ds->at.bitlen[i] = lzx_br_bits(br, 3);
26446c95142eSMartin Matuska 				ds->at.freq[ds->at.bitlen[i]]++;
26456c95142eSMartin Matuska 				lzx_br_consume(br, 3);
26466c95142eSMartin Matuska 			}
26476c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->at))
26486c95142eSMartin Matuska 				goto failed;
26496c95142eSMartin Matuska 			/* FALL THROUGH */
26506c95142eSMartin Matuska 		case ST_RD_VERBATIM:
26516c95142eSMartin Matuska 			ds->loop = 0;
26526c95142eSMartin Matuska 			/* FALL THROUGH */
26536c95142eSMartin Matuska 		case ST_RD_PRE_MAIN_TREE_256:
26546c95142eSMartin Matuska 			/*
26556c95142eSMartin Matuska 			 * Read Pre-tree for first 256 elements of main tree.
26566c95142eSMartin Matuska 			 */
26576c95142eSMartin Matuska 			if (!lzx_read_pre_tree(strm)) {
26586c95142eSMartin Matuska 				ds->state = ST_RD_PRE_MAIN_TREE_256;
26596c95142eSMartin Matuska 				if (last)
26606c95142eSMartin Matuska 					goto failed;
26616c95142eSMartin Matuska 				return (ARCHIVE_OK);
26626c95142eSMartin Matuska 			}
26636c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->pt))
26646c95142eSMartin Matuska 				goto failed;
26656c95142eSMartin Matuska 			ds->loop = 0;
26666c95142eSMartin Matuska 			/* FALL THROUGH */
26676c95142eSMartin Matuska 		case ST_MAIN_TREE_256:
26686c95142eSMartin Matuska 			/*
26696c95142eSMartin Matuska 			 * Get path lengths of first 256 elements of main tree.
26706c95142eSMartin Matuska 			 */
26716c95142eSMartin Matuska 			r = lzx_read_bitlen(strm, &ds->mt, 256);
26726c95142eSMartin Matuska 			if (r < 0)
26736c95142eSMartin Matuska 				goto failed;
26746c95142eSMartin Matuska 			else if (!r) {
26756c95142eSMartin Matuska 				ds->state = ST_MAIN_TREE_256;
26766c95142eSMartin Matuska 				if (last)
26776c95142eSMartin Matuska 					goto failed;
26786c95142eSMartin Matuska 				return (ARCHIVE_OK);
26796c95142eSMartin Matuska 			}
26806c95142eSMartin Matuska 			ds->loop = 0;
26816c95142eSMartin Matuska 			/* FALL THROUGH */
26826c95142eSMartin Matuska 		case ST_RD_PRE_MAIN_TREE_REM:
26836c95142eSMartin Matuska 			/*
26846c95142eSMartin Matuska 			 * Read Pre-tree for remaining elements of main tree.
26856c95142eSMartin Matuska 			 */
26866c95142eSMartin Matuska 			if (!lzx_read_pre_tree(strm)) {
26876c95142eSMartin Matuska 				ds->state = ST_RD_PRE_MAIN_TREE_REM;
26886c95142eSMartin Matuska 				if (last)
26896c95142eSMartin Matuska 					goto failed;
26906c95142eSMartin Matuska 				return (ARCHIVE_OK);
26916c95142eSMartin Matuska 			}
26926c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->pt))
26936c95142eSMartin Matuska 				goto failed;
26946c95142eSMartin Matuska 			ds->loop = 256;
26956c95142eSMartin Matuska 			/* FALL THROUGH */
26966c95142eSMartin Matuska 		case ST_MAIN_TREE_REM:
26976c95142eSMartin Matuska 			/*
26986c95142eSMartin Matuska 			 * Get path lengths of remaining elements of main tree.
26996c95142eSMartin Matuska 			 */
27006c95142eSMartin Matuska 			r = lzx_read_bitlen(strm, &ds->mt, -1);
27016c95142eSMartin Matuska 			if (r < 0)
27026c95142eSMartin Matuska 				goto failed;
27036c95142eSMartin Matuska 			else if (!r) {
27046c95142eSMartin Matuska 				ds->state = ST_MAIN_TREE_REM;
27056c95142eSMartin Matuska 				if (last)
27066c95142eSMartin Matuska 					goto failed;
27076c95142eSMartin Matuska 				return (ARCHIVE_OK);
27086c95142eSMartin Matuska 			}
27096c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->mt))
27106c95142eSMartin Matuska 				goto failed;
27116c95142eSMartin Matuska 			ds->loop = 0;
27126c95142eSMartin Matuska 			/* FALL THROUGH */
27136c95142eSMartin Matuska 		case ST_RD_PRE_LENGTH_TREE:
27146c95142eSMartin Matuska 			/*
27156c95142eSMartin Matuska 			 * Read Pre-tree for remaining elements of main tree.
27166c95142eSMartin Matuska 			 */
27176c95142eSMartin Matuska 			if (!lzx_read_pre_tree(strm)) {
27186c95142eSMartin Matuska 				ds->state = ST_RD_PRE_LENGTH_TREE;
27196c95142eSMartin Matuska 				if (last)
27206c95142eSMartin Matuska 					goto failed;
27216c95142eSMartin Matuska 				return (ARCHIVE_OK);
27226c95142eSMartin Matuska 			}
27236c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->pt))
27246c95142eSMartin Matuska 				goto failed;
27256c95142eSMartin Matuska 			ds->loop = 0;
27266c95142eSMartin Matuska 			/* FALL THROUGH */
27276c95142eSMartin Matuska 		case ST_LENGTH_TREE:
27286c95142eSMartin Matuska 			/*
27296c95142eSMartin Matuska 			 * Get path lengths of remaining elements of main tree.
27306c95142eSMartin Matuska 			 */
27316c95142eSMartin Matuska 			r = lzx_read_bitlen(strm, &ds->lt, -1);
27326c95142eSMartin Matuska 			if (r < 0)
27336c95142eSMartin Matuska 				goto failed;
27346c95142eSMartin Matuska 			else if (!r) {
27356c95142eSMartin Matuska 				ds->state = ST_LENGTH_TREE;
27366c95142eSMartin Matuska 				if (last)
27376c95142eSMartin Matuska 					goto failed;
27386c95142eSMartin Matuska 				return (ARCHIVE_OK);
27396c95142eSMartin Matuska 			}
27406c95142eSMartin Matuska 			if (!lzx_make_huffman_table(&ds->lt))
27416c95142eSMartin Matuska 				goto failed;
27426c95142eSMartin Matuska 			ds->state = ST_MAIN;
27436c95142eSMartin Matuska 			return (100);
27446c95142eSMartin Matuska 		}
27456c95142eSMartin Matuska 	}
27466c95142eSMartin Matuska failed:
27476c95142eSMartin Matuska 	return (ds->error = ARCHIVE_FAILED);
27486c95142eSMartin Matuska }
27496c95142eSMartin Matuska 
27506c95142eSMartin Matuska static int
27516c95142eSMartin Matuska lzx_decode_blocks(struct lzx_stream *strm, int last)
27526c95142eSMartin Matuska {
27536c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
27546c95142eSMartin Matuska 	struct lzx_br bre = ds->br;
27556c95142eSMartin Matuska 	struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
27566c95142eSMartin Matuska 	const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
2757acc60b03SMartin Matuska 	unsigned char *noutp = strm->next_out;
2758acc60b03SMartin Matuska 	unsigned char *endp = noutp + strm->avail_out;
27596c95142eSMartin Matuska 	unsigned char *w_buff = ds->w_buff;
27606c95142eSMartin Matuska 	unsigned char *at_bitlen = at->bitlen;
27616c95142eSMartin Matuska 	unsigned char *lt_bitlen = lt->bitlen;
27626c95142eSMartin Matuska 	unsigned char *mt_bitlen = mt->bitlen;
27636c95142eSMartin Matuska 	size_t block_bytes_avail = ds->block_bytes_avail;
27646c95142eSMartin Matuska 	int at_max_bits = at->max_bits;
27656c95142eSMartin Matuska 	int lt_max_bits = lt->max_bits;
27666c95142eSMartin Matuska 	int mt_max_bits = mt->max_bits;
27676c95142eSMartin Matuska 	int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos;
27686c95142eSMartin Matuska 	int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size;
27696c95142eSMartin Matuska 	int length_header = ds->length_header;
27706c95142eSMartin Matuska 	int offset_bits = ds->offset_bits;
27716c95142eSMartin Matuska 	int position_slot = ds->position_slot;
27726c95142eSMartin Matuska 	int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2;
27736c95142eSMartin Matuska 	int state = ds->state;
27746c95142eSMartin Matuska 	char block_type = ds->block_type;
27756c95142eSMartin Matuska 
27766c95142eSMartin Matuska 	for (;;) {
27776c95142eSMartin Matuska 		switch (state) {
27786c95142eSMartin Matuska 		case ST_MAIN:
27796c95142eSMartin Matuska 			for (;;) {
27806c95142eSMartin Matuska 				if (block_bytes_avail == 0) {
27816c95142eSMartin Matuska 					/* This block ended. */
27826c95142eSMartin Matuska 					ds->state = ST_RD_BLOCK_TYPE;
27836c95142eSMartin Matuska 					ds->br = bre;
27846c95142eSMartin Matuska 					ds->block_bytes_avail =
27856c95142eSMartin Matuska 					    block_bytes_avail;
27866c95142eSMartin Matuska 					ds->copy_len = copy_len;
27876c95142eSMartin Matuska 					ds->copy_pos = copy_pos;
27886c95142eSMartin Matuska 					ds->length_header = length_header;
27896c95142eSMartin Matuska 					ds->position_slot = position_slot;
27906c95142eSMartin Matuska 					ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
27916c95142eSMartin Matuska 					ds->w_pos = w_pos;
2792acc60b03SMartin Matuska 					strm->avail_out = endp - noutp;
27936c95142eSMartin Matuska 					return (ARCHIVE_EOF);
27946c95142eSMartin Matuska 				}
2795acc60b03SMartin Matuska 				if (noutp >= endp)
27966c95142eSMartin Matuska 					/* Output buffer is empty. */
27976c95142eSMartin Matuska 					goto next_data;
27986c95142eSMartin Matuska 
27996c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, &bre,
28006c95142eSMartin Matuska 				    mt_max_bits)) {
28016c95142eSMartin Matuska 					if (!last)
28026c95142eSMartin Matuska 						goto next_data;
28036c95142eSMartin Matuska 					/* Remaining bits are less than
28046c95142eSMartin Matuska 					 * maximum bits(mt.max_bits) but maybe
28056c95142eSMartin Matuska 					 * it still remains as much as we need,
28066c95142eSMartin Matuska 					 * so we should try to use it with
28076c95142eSMartin Matuska 					 * dummy bits. */
28086c95142eSMartin Matuska 					c = lzx_decode_huffman(mt,
28096c95142eSMartin Matuska 					      lzx_br_bits_forced(
28106c95142eSMartin Matuska 				 	        &bre, mt_max_bits));
28116c95142eSMartin Matuska 					lzx_br_consume(&bre, mt_bitlen[c]);
28126c95142eSMartin Matuska 					if (!lzx_br_has(&bre, 0))
28136c95142eSMartin Matuska 						goto failed;/* Over read. */
28146c95142eSMartin Matuska 				} else {
28156c95142eSMartin Matuska 					c = lzx_decode_huffman(mt,
28166c95142eSMartin Matuska 					      lzx_br_bits(&bre, mt_max_bits));
28176c95142eSMartin Matuska 					lzx_br_consume(&bre, mt_bitlen[c]);
28186c95142eSMartin Matuska 				}
28196c95142eSMartin Matuska 				if (c > UCHAR_MAX)
28206c95142eSMartin Matuska 					break;
28216c95142eSMartin Matuska 				/*
28226c95142eSMartin Matuska 				 * 'c' is exactly literal code.
28236c95142eSMartin Matuska 				 */
28246c95142eSMartin Matuska 				/* Save a decoded code to reference it
28256c95142eSMartin Matuska 				 * afterward. */
28266c95142eSMartin Matuska 				w_buff[w_pos] = c;
28276c95142eSMartin Matuska 				w_pos = (w_pos + 1) & w_mask;
28286c95142eSMartin Matuska 				/* Store the decoded code to output buffer. */
2829acc60b03SMartin Matuska 				*noutp++ = c;
28306c95142eSMartin Matuska 				block_bytes_avail--;
28316c95142eSMartin Matuska 			}
28326c95142eSMartin Matuska 			/*
28336c95142eSMartin Matuska 			 * Get a match code, its length and offset.
28346c95142eSMartin Matuska 			 */
28356c95142eSMartin Matuska 			c -= UCHAR_MAX + 1;
28366c95142eSMartin Matuska 			length_header = c & 7;
28376c95142eSMartin Matuska 			position_slot = c >> 3;
28386c95142eSMartin Matuska 			/* FALL THROUGH */
28396c95142eSMartin Matuska 		case ST_LENGTH:
28406c95142eSMartin Matuska 			/*
28416c95142eSMartin Matuska 			 * Get a length.
28426c95142eSMartin Matuska 			 */
28436c95142eSMartin Matuska 			if (length_header == 7) {
28446c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, &bre,
28456c95142eSMartin Matuska 				    lt_max_bits)) {
28466c95142eSMartin Matuska 					if (!last) {
28476c95142eSMartin Matuska 						state = ST_LENGTH;
28486c95142eSMartin Matuska 						goto next_data;
28496c95142eSMartin Matuska 					}
28506c95142eSMartin Matuska 					c = lzx_decode_huffman(lt,
28516c95142eSMartin Matuska 					      lzx_br_bits_forced(
28526c95142eSMartin Matuska 					        &bre, lt_max_bits));
28536c95142eSMartin Matuska 					lzx_br_consume(&bre, lt_bitlen[c]);
28546c95142eSMartin Matuska 					if (!lzx_br_has(&bre, 0))
28556c95142eSMartin Matuska 						goto failed;/* Over read. */
28566c95142eSMartin Matuska 				} else {
28576c95142eSMartin Matuska 					c = lzx_decode_huffman(lt,
28586c95142eSMartin Matuska 					    lzx_br_bits(&bre, lt_max_bits));
28596c95142eSMartin Matuska 					lzx_br_consume(&bre, lt_bitlen[c]);
28606c95142eSMartin Matuska 				}
28616c95142eSMartin Matuska 				copy_len = c + 7 + 2;
28626c95142eSMartin Matuska 			} else
28636c95142eSMartin Matuska 				copy_len = length_header + 2;
28646c95142eSMartin Matuska 			if ((size_t)copy_len > block_bytes_avail)
28656c95142eSMartin Matuska 				goto failed;
28666c95142eSMartin Matuska 			/*
28676c95142eSMartin Matuska 			 * Get an offset.
28686c95142eSMartin Matuska 			 */
28696c95142eSMartin Matuska 			switch (position_slot) {
28706c95142eSMartin Matuska 			case 0: /* Use repeated offset 0. */
28716c95142eSMartin Matuska 				copy_pos = r0;
28726c95142eSMartin Matuska 				state = ST_REAL_POS;
28736c95142eSMartin Matuska 				continue;
28746c95142eSMartin Matuska 			case 1: /* Use repeated offset 1. */
28756c95142eSMartin Matuska 				copy_pos = r1;
28766c95142eSMartin Matuska 				/* Swap repeated offset. */
28776c95142eSMartin Matuska 				r1 = r0;
28786c95142eSMartin Matuska 				r0 = copy_pos;
28796c95142eSMartin Matuska 				state = ST_REAL_POS;
28806c95142eSMartin Matuska 				continue;
28816c95142eSMartin Matuska 			case 2: /* Use repeated offset 2. */
28826c95142eSMartin Matuska 				copy_pos = r2;
28836c95142eSMartin Matuska 				/* Swap repeated offset. */
28846c95142eSMartin Matuska 				r2 = r0;
28856c95142eSMartin Matuska 				r0 = copy_pos;
28866c95142eSMartin Matuska 				state = ST_REAL_POS;
28876c95142eSMartin Matuska 				continue;
28886c95142eSMartin Matuska 			default:
28896c95142eSMartin Matuska 				offset_bits =
28906c95142eSMartin Matuska 				    pos_tbl[position_slot].footer_bits;
28916c95142eSMartin Matuska 				break;
28926c95142eSMartin Matuska 			}
28936c95142eSMartin Matuska 			/* FALL THROUGH */
28946c95142eSMartin Matuska 		case ST_OFFSET:
28956c95142eSMartin Matuska 			/*
28966c95142eSMartin Matuska 			 * Get the offset, which is a distance from
28976c95142eSMartin Matuska 			 * current window position.
28986c95142eSMartin Matuska 			 */
28996c95142eSMartin Matuska 			if (block_type == ALIGNED_OFFSET_BLOCK &&
29006c95142eSMartin Matuska 			    offset_bits >= 3) {
29016c95142eSMartin Matuska 				int offbits = offset_bits - 3;
29026c95142eSMartin Matuska 
29036c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, &bre, offbits)) {
29046c95142eSMartin Matuska 					state = ST_OFFSET;
29056c95142eSMartin Matuska 					if (last)
29066c95142eSMartin Matuska 						goto failed;
29076c95142eSMartin Matuska 					goto next_data;
29086c95142eSMartin Matuska 				}
29096c95142eSMartin Matuska 				copy_pos = lzx_br_bits(&bre, offbits) << 3;
29106c95142eSMartin Matuska 
29116c95142eSMartin Matuska 				/* Get an aligned number. */
29126c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, &bre,
29136c95142eSMartin Matuska 				    offbits + at_max_bits)) {
29146c95142eSMartin Matuska 					if (!last) {
29156c95142eSMartin Matuska 						state = ST_OFFSET;
29166c95142eSMartin Matuska 						goto next_data;
29176c95142eSMartin Matuska 					}
29186c95142eSMartin Matuska 					lzx_br_consume(&bre, offbits);
29196c95142eSMartin Matuska 					c = lzx_decode_huffman(at,
29206c95142eSMartin Matuska 					      lzx_br_bits_forced(&bre,
29216c95142eSMartin Matuska 					        at_max_bits));
29226c95142eSMartin Matuska 					lzx_br_consume(&bre, at_bitlen[c]);
29236c95142eSMartin Matuska 					if (!lzx_br_has(&bre, 0))
29246c95142eSMartin Matuska 						goto failed;/* Over read. */
29256c95142eSMartin Matuska 				} else {
29266c95142eSMartin Matuska 					lzx_br_consume(&bre, offbits);
29276c95142eSMartin Matuska 					c = lzx_decode_huffman(at,
29286c95142eSMartin Matuska 					      lzx_br_bits(&bre, at_max_bits));
29296c95142eSMartin Matuska 					lzx_br_consume(&bre, at_bitlen[c]);
29306c95142eSMartin Matuska 				}
29316c95142eSMartin Matuska 				/* Add an aligned number. */
29326c95142eSMartin Matuska 				copy_pos += c;
29336c95142eSMartin Matuska 			} else {
29346c95142eSMartin Matuska 				if (!lzx_br_read_ahead(strm, &bre,
29356c95142eSMartin Matuska 				    offset_bits)) {
29366c95142eSMartin Matuska 					state = ST_OFFSET;
29376c95142eSMartin Matuska 					if (last)
29386c95142eSMartin Matuska 						goto failed;
29396c95142eSMartin Matuska 					goto next_data;
29406c95142eSMartin Matuska 				}
29416c95142eSMartin Matuska 				copy_pos = lzx_br_bits(&bre, offset_bits);
29426c95142eSMartin Matuska 				lzx_br_consume(&bre, offset_bits);
29436c95142eSMartin Matuska 			}
29446c95142eSMartin Matuska 			copy_pos += pos_tbl[position_slot].base -2;
29456c95142eSMartin Matuska 
29466c95142eSMartin Matuska 			/* Update repeated offset LRU queue. */
29476c95142eSMartin Matuska 			r2 = r1;
29486c95142eSMartin Matuska 			r1 = r0;
29496c95142eSMartin Matuska 			r0 = copy_pos;
29506c95142eSMartin Matuska 			/* FALL THROUGH */
29516c95142eSMartin Matuska 		case ST_REAL_POS:
29526c95142eSMartin Matuska 			/*
29536c95142eSMartin Matuska 			 * Compute a real position in window.
29546c95142eSMartin Matuska 			 */
29556c95142eSMartin Matuska 			copy_pos = (w_pos - copy_pos) & w_mask;
29566c95142eSMartin Matuska 			/* FALL THROUGH */
29576c95142eSMartin Matuska 		case ST_COPY:
29586c95142eSMartin Matuska 			/*
29596c95142eSMartin Matuska 			 * Copy several bytes as extracted data from the window
29606c95142eSMartin Matuska 			 * into the output buffer.
29616c95142eSMartin Matuska 			 */
29626c95142eSMartin Matuska 			for (;;) {
29636c95142eSMartin Matuska 				const unsigned char *s;
29646c95142eSMartin Matuska 				int l;
29656c95142eSMartin Matuska 
29666c95142eSMartin Matuska 				l = copy_len;
29676c95142eSMartin Matuska 				if (copy_pos > w_pos) {
29686c95142eSMartin Matuska 					if (l > w_size - copy_pos)
29696c95142eSMartin Matuska 						l = w_size - copy_pos;
29706c95142eSMartin Matuska 				} else {
29716c95142eSMartin Matuska 					if (l > w_size - w_pos)
29726c95142eSMartin Matuska 						l = w_size - w_pos;
29736c95142eSMartin Matuska 				}
2974acc60b03SMartin Matuska 				if (noutp + l >= endp)
2975acc60b03SMartin Matuska 					l = (int)(endp - noutp);
29766c95142eSMartin Matuska 				s = w_buff + copy_pos;
29776c95142eSMartin Matuska 				if (l >= 8 && ((copy_pos + l < w_pos)
29786c95142eSMartin Matuska 				  || (w_pos + l < copy_pos))) {
29796c95142eSMartin Matuska 					memcpy(w_buff + w_pos, s, l);
2980acc60b03SMartin Matuska 					memcpy(noutp, s, l);
29816c95142eSMartin Matuska 				} else {
29826c95142eSMartin Matuska 					unsigned char *d;
29836c95142eSMartin Matuska 					int li;
29846c95142eSMartin Matuska 
29856c95142eSMartin Matuska 					d = w_buff + w_pos;
29866c95142eSMartin Matuska 					for (li = 0; li < l; li++)
2987acc60b03SMartin Matuska 						noutp[li] = d[li] = s[li];
29886c95142eSMartin Matuska 				}
2989acc60b03SMartin Matuska 				noutp += l;
29906c95142eSMartin Matuska 				copy_pos = (copy_pos + l) & w_mask;
29916c95142eSMartin Matuska 				w_pos = (w_pos + l) & w_mask;
29926c95142eSMartin Matuska 				block_bytes_avail -= l;
29936c95142eSMartin Matuska 				if (copy_len <= l)
29946c95142eSMartin Matuska 					/* A copy of current pattern ended. */
29956c95142eSMartin Matuska 					break;
29966c95142eSMartin Matuska 				copy_len -= l;
2997acc60b03SMartin Matuska 				if (noutp >= endp) {
29986c95142eSMartin Matuska 					/* Output buffer is empty. */
29996c95142eSMartin Matuska 					state = ST_COPY;
30006c95142eSMartin Matuska 					goto next_data;
30016c95142eSMartin Matuska 				}
30026c95142eSMartin Matuska 			}
30036c95142eSMartin Matuska 			state = ST_MAIN;
30046c95142eSMartin Matuska 			break;
30056c95142eSMartin Matuska 		}
30066c95142eSMartin Matuska 	}
30076c95142eSMartin Matuska failed:
30086c95142eSMartin Matuska 	return (ds->error = ARCHIVE_FAILED);
30096c95142eSMartin Matuska next_data:
30106c95142eSMartin Matuska 	ds->br = bre;
30116c95142eSMartin Matuska 	ds->block_bytes_avail = block_bytes_avail;
30126c95142eSMartin Matuska 	ds->copy_len = copy_len;
30136c95142eSMartin Matuska 	ds->copy_pos = copy_pos;
30146c95142eSMartin Matuska 	ds->length_header = length_header;
30156c95142eSMartin Matuska 	ds->offset_bits = offset_bits;
30166c95142eSMartin Matuska 	ds->position_slot = position_slot;
30176c95142eSMartin Matuska 	ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
30186c95142eSMartin Matuska 	ds->state = state;
30196c95142eSMartin Matuska 	ds->w_pos = w_pos;
3020acc60b03SMartin Matuska 	strm->avail_out = endp - noutp;
30216c95142eSMartin Matuska 	return (ARCHIVE_OK);
30226c95142eSMartin Matuska }
30236c95142eSMartin Matuska 
30246c95142eSMartin Matuska static int
30256c95142eSMartin Matuska lzx_read_pre_tree(struct lzx_stream *strm)
30266c95142eSMartin Matuska {
30276c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
30286c95142eSMartin Matuska 	struct lzx_br *br = &(ds->br);
30296c95142eSMartin Matuska 	int i;
30306c95142eSMartin Matuska 
30316c95142eSMartin Matuska 	if (ds->loop == 0)
30326c95142eSMartin Matuska 		memset(ds->pt.freq, 0, sizeof(ds->pt.freq));
30336c95142eSMartin Matuska 	for (i = ds->loop; i < ds->pt.len_size; i++) {
30346c95142eSMartin Matuska 		if (!lzx_br_read_ahead(strm, br, 4)) {
30356c95142eSMartin Matuska 			ds->loop = i;
30366c95142eSMartin Matuska 			return (0);
30376c95142eSMartin Matuska 		}
30386c95142eSMartin Matuska 		ds->pt.bitlen[i] = lzx_br_bits(br, 4);
30396c95142eSMartin Matuska 		ds->pt.freq[ds->pt.bitlen[i]]++;
30406c95142eSMartin Matuska 		lzx_br_consume(br, 4);
30416c95142eSMartin Matuska 	}
30426c95142eSMartin Matuska 	ds->loop = i;
30436c95142eSMartin Matuska 	return (1);
30446c95142eSMartin Matuska }
30456c95142eSMartin Matuska 
30466c95142eSMartin Matuska /*
30476c95142eSMartin Matuska  * Read a bunch of bit-lengths from pre-tree.
30486c95142eSMartin Matuska  */
30496c95142eSMartin Matuska static int
30506c95142eSMartin Matuska lzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end)
30516c95142eSMartin Matuska {
30526c95142eSMartin Matuska 	struct lzx_dec *ds = strm->ds;
30536c95142eSMartin Matuska 	struct lzx_br *br = &(ds->br);
30546c95142eSMartin Matuska 	int c, i, j, ret, same;
30556c95142eSMartin Matuska 	unsigned rbits;
30566c95142eSMartin Matuska 
30576c95142eSMartin Matuska 	i = ds->loop;
30586c95142eSMartin Matuska 	if (i == 0)
30596c95142eSMartin Matuska 		memset(d->freq, 0, sizeof(d->freq));
30606c95142eSMartin Matuska 	ret = 0;
30616c95142eSMartin Matuska 	if (end < 0)
30626c95142eSMartin Matuska 		end = d->len_size;
30636c95142eSMartin Matuska 	while (i < end) {
30646c95142eSMartin Matuska 		ds->loop = i;
30656c95142eSMartin Matuska 		if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits))
30666c95142eSMartin Matuska 			goto getdata;
30676c95142eSMartin Matuska 		rbits = lzx_br_bits(br, ds->pt.max_bits);
30686c95142eSMartin Matuska 		c = lzx_decode_huffman(&(ds->pt), rbits);
30696c95142eSMartin Matuska 		switch (c) {
30706c95142eSMartin Matuska 		case 17:/* several zero lengths, from 4 to 19. */
30716c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4))
30726c95142eSMartin Matuska 				goto getdata;
30736c95142eSMartin Matuska 			lzx_br_consume(br, ds->pt.bitlen[c]);
30746c95142eSMartin Matuska 			same = lzx_br_bits(br, 4) + 4;
30756c95142eSMartin Matuska 			if (i + same > end)
30766c95142eSMartin Matuska 				return (-1);/* Invalid */
30776c95142eSMartin Matuska 			lzx_br_consume(br, 4);
30786c95142eSMartin Matuska 			for (j = 0; j < same; j++)
30796c95142eSMartin Matuska 				d->bitlen[i++] = 0;
30806c95142eSMartin Matuska 			break;
30816c95142eSMartin Matuska 		case 18:/* many zero lengths, from 20 to 51. */
30826c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5))
30836c95142eSMartin Matuska 				goto getdata;
30846c95142eSMartin Matuska 			lzx_br_consume(br, ds->pt.bitlen[c]);
30856c95142eSMartin Matuska 			same = lzx_br_bits(br, 5) + 20;
30866c95142eSMartin Matuska 			if (i + same > end)
30876c95142eSMartin Matuska 				return (-1);/* Invalid */
30886c95142eSMartin Matuska 			lzx_br_consume(br, 5);
30896c95142eSMartin Matuska 			memset(d->bitlen + i, 0, same);
30906c95142eSMartin Matuska 			i += same;
30916c95142eSMartin Matuska 			break;
30926c95142eSMartin Matuska 		case 19:/* a few same lengths. */
30936c95142eSMartin Matuska 			if (!lzx_br_read_ahead(strm, br,
30946c95142eSMartin Matuska 			    ds->pt.bitlen[c]+1+ds->pt.max_bits))
30956c95142eSMartin Matuska 				goto getdata;
30966c95142eSMartin Matuska 			lzx_br_consume(br, ds->pt.bitlen[c]);
30976c95142eSMartin Matuska 			same = lzx_br_bits(br, 1) + 4;
30986c95142eSMartin Matuska 			if (i + same > end)
30996c95142eSMartin Matuska 				return (-1);
31006c95142eSMartin Matuska 			lzx_br_consume(br, 1);
31016c95142eSMartin Matuska 			rbits = lzx_br_bits(br, ds->pt.max_bits);
31026c95142eSMartin Matuska 			c = lzx_decode_huffman(&(ds->pt), rbits);
31036c95142eSMartin Matuska 			lzx_br_consume(br, ds->pt.bitlen[c]);
31046c95142eSMartin Matuska 			c = (d->bitlen[i] - c + 17) % 17;
31056c95142eSMartin Matuska 			if (c < 0)
31066c95142eSMartin Matuska 				return (-1);/* Invalid */
31076c95142eSMartin Matuska 			for (j = 0; j < same; j++)
31086c95142eSMartin Matuska 				d->bitlen[i++] = c;
31096c95142eSMartin Matuska 			d->freq[c] += same;
31106c95142eSMartin Matuska 			break;
31116c95142eSMartin Matuska 		default:
31126c95142eSMartin Matuska 			lzx_br_consume(br, ds->pt.bitlen[c]);
31136c95142eSMartin Matuska 			c = (d->bitlen[i] - c + 17) % 17;
31146c95142eSMartin Matuska 			if (c < 0)
31156c95142eSMartin Matuska 				return (-1);/* Invalid */
31166c95142eSMartin Matuska 			d->freq[c]++;
31176c95142eSMartin Matuska 			d->bitlen[i++] = c;
31186c95142eSMartin Matuska 			break;
31196c95142eSMartin Matuska 		}
31206c95142eSMartin Matuska 	}
31216c95142eSMartin Matuska 	ret = 1;
31226c95142eSMartin Matuska getdata:
31236c95142eSMartin Matuska 	ds->loop = i;
31246c95142eSMartin Matuska 	return (ret);
31256c95142eSMartin Matuska }
31266c95142eSMartin Matuska 
31276c95142eSMartin Matuska static int
31286c95142eSMartin Matuska lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
31296c95142eSMartin Matuska {
31306c95142eSMartin Matuska 	int bits;
31316c95142eSMartin Matuska 
31326c95142eSMartin Matuska 	if (hf->bitlen == NULL || hf->len_size != (int)len_size) {
31336c95142eSMartin Matuska 		free(hf->bitlen);
31346c95142eSMartin Matuska 		hf->bitlen = calloc(len_size,  sizeof(hf->bitlen[0]));
31356c95142eSMartin Matuska 		if (hf->bitlen == NULL)
31366c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
3137acc60b03SMartin Matuska 		hf->len_size = (int)len_size;
31386c95142eSMartin Matuska 	} else
31396c95142eSMartin Matuska 		memset(hf->bitlen, 0, len_size *  sizeof(hf->bitlen[0]));
31406c95142eSMartin Matuska 	if (hf->tbl == NULL) {
31416c95142eSMartin Matuska 		if (tbl_bits < HTBL_BITS)
31426c95142eSMartin Matuska 			bits = tbl_bits;
31436c95142eSMartin Matuska 		else
31446c95142eSMartin Matuska 			bits = HTBL_BITS;
3145acc60b03SMartin Matuska 		hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
31466c95142eSMartin Matuska 		if (hf->tbl == NULL)
31476c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
31486c95142eSMartin Matuska 		hf->tbl_bits = tbl_bits;
31496c95142eSMartin Matuska 	}
31506c95142eSMartin Matuska 	if (hf->tree == NULL && tbl_bits > HTBL_BITS) {
31516c95142eSMartin Matuska 		hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4);
31526c95142eSMartin Matuska 		hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0]));
31536c95142eSMartin Matuska 		if (hf->tree == NULL)
31546c95142eSMartin Matuska 			return (ARCHIVE_FATAL);
31556c95142eSMartin Matuska 	}
31566c95142eSMartin Matuska 	return (ARCHIVE_OK);
31576c95142eSMartin Matuska }
31586c95142eSMartin Matuska 
31596c95142eSMartin Matuska static void
31606c95142eSMartin Matuska lzx_huffman_free(struct huffman *hf)
31616c95142eSMartin Matuska {
31626c95142eSMartin Matuska 	free(hf->bitlen);
31636c95142eSMartin Matuska 	free(hf->tbl);
31646c95142eSMartin Matuska 	free(hf->tree);
31656c95142eSMartin Matuska }
31666c95142eSMartin Matuska 
31676c95142eSMartin Matuska /*
31686c95142eSMartin Matuska  * Make a huffman coding table.
31696c95142eSMartin Matuska  */
31706c95142eSMartin Matuska static int
31716c95142eSMartin Matuska lzx_make_huffman_table(struct huffman *hf)
31726c95142eSMartin Matuska {
31736c95142eSMartin Matuska 	uint16_t *tbl;
31746c95142eSMartin Matuska 	const unsigned char *bitlen;
31756c95142eSMartin Matuska 	int bitptn[17], weight[17];
31766c95142eSMartin Matuska 	int i, maxbits = 0, ptn, tbl_size, w;
31776c95142eSMartin Matuska 	int diffbits, len_avail;
31786c95142eSMartin Matuska 
31796c95142eSMartin Matuska 	/*
31806c95142eSMartin Matuska 	 * Initialize bit patterns.
31816c95142eSMartin Matuska 	 */
31826c95142eSMartin Matuska 	ptn = 0;
31836c95142eSMartin Matuska 	for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) {
31846c95142eSMartin Matuska 		bitptn[i] = ptn;
31856c95142eSMartin Matuska 		weight[i] = w;
31866c95142eSMartin Matuska 		if (hf->freq[i]) {
31876c95142eSMartin Matuska 			ptn += hf->freq[i] * w;
31886c95142eSMartin Matuska 			maxbits = i;
31896c95142eSMartin Matuska 		}
31906c95142eSMartin Matuska 	}
31916c95142eSMartin Matuska 	if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits)
31926c95142eSMartin Matuska 		return (0);/* Invalid */
31936c95142eSMartin Matuska 
31946c95142eSMartin Matuska 	hf->max_bits = maxbits;
31956c95142eSMartin Matuska 
31966c95142eSMartin Matuska 	/*
31976c95142eSMartin Matuska 	 * Cut out extra bits which we won't house in the table.
31986c95142eSMartin Matuska 	 * This preparation reduces the same calculation in the for-loop
31996c95142eSMartin Matuska 	 * making the table.
32006c95142eSMartin Matuska 	 */
32016c95142eSMartin Matuska 	if (maxbits < 16) {
32026c95142eSMartin Matuska 		int ebits = 16 - maxbits;
32036c95142eSMartin Matuska 		for (i = 1; i <= maxbits; i++) {
32046c95142eSMartin Matuska 			bitptn[i] >>= ebits;
32056c95142eSMartin Matuska 			weight[i] >>= ebits;
32066c95142eSMartin Matuska 		}
32076c95142eSMartin Matuska 	}
32086c95142eSMartin Matuska 	if (maxbits > HTBL_BITS) {
32096c95142eSMartin Matuska 		int htbl_max;
32106c95142eSMartin Matuska 		uint16_t *p;
32116c95142eSMartin Matuska 
32126c95142eSMartin Matuska 		diffbits = maxbits - HTBL_BITS;
32136c95142eSMartin Matuska 		for (i = 1; i <= HTBL_BITS; i++) {
32146c95142eSMartin Matuska 			bitptn[i] >>= diffbits;
32156c95142eSMartin Matuska 			weight[i] >>= diffbits;
32166c95142eSMartin Matuska 		}
32176c95142eSMartin Matuska 		htbl_max = bitptn[HTBL_BITS] +
32186c95142eSMartin Matuska 		    weight[HTBL_BITS] * hf->freq[HTBL_BITS];
32196c95142eSMartin Matuska 		p = &(hf->tbl[htbl_max]);
32206c95142eSMartin Matuska 		while (p < &hf->tbl[1U<<HTBL_BITS])
32216c95142eSMartin Matuska 			*p++ = 0;
32226c95142eSMartin Matuska 	} else
32236c95142eSMartin Matuska 		diffbits = 0;
32246c95142eSMartin Matuska 	hf->shift_bits = diffbits;
32256c95142eSMartin Matuska 
32266c95142eSMartin Matuska 	/*
32276c95142eSMartin Matuska 	 * Make the table.
32286c95142eSMartin Matuska 	 */
32296c95142eSMartin Matuska 	tbl_size = 1 << HTBL_BITS;
32306c95142eSMartin Matuska 	tbl = hf->tbl;
32316c95142eSMartin Matuska 	bitlen = hf->bitlen;
32326c95142eSMartin Matuska 	len_avail = hf->len_size;
32336c95142eSMartin Matuska 	hf->tree_used = 0;
32346c95142eSMartin Matuska 	for (i = 0; i < len_avail; i++) {
32356c95142eSMartin Matuska 		uint16_t *p;
32366c95142eSMartin Matuska 		int len, cnt;
32376c95142eSMartin Matuska 		uint16_t bit;
32386c95142eSMartin Matuska 		int extlen;
32396c95142eSMartin Matuska 		struct htree_t *ht;
32406c95142eSMartin Matuska 
32416c95142eSMartin Matuska 		if (bitlen[i] == 0)
32426c95142eSMartin Matuska 			continue;
32436c95142eSMartin Matuska 		/* Get a bit pattern */
32446c95142eSMartin Matuska 		len = bitlen[i];
32456c95142eSMartin Matuska 		ptn = bitptn[len];
32466c95142eSMartin Matuska 		cnt = weight[len];
32476c95142eSMartin Matuska 		if (len <= HTBL_BITS) {
32486c95142eSMartin Matuska 			/* Calculate next bit pattern */
32496c95142eSMartin Matuska 			if ((bitptn[len] = ptn + cnt) > tbl_size)
32506c95142eSMartin Matuska 				return (0);/* Invalid */
32516c95142eSMartin Matuska 			/* Update the table */
32526c95142eSMartin Matuska 			p = &(tbl[ptn]);
32536c95142eSMartin Matuska 			while (--cnt >= 0)
32546c95142eSMartin Matuska 				p[cnt] = (uint16_t)i;
32556c95142eSMartin Matuska 			continue;
32566c95142eSMartin Matuska 		}
32576c95142eSMartin Matuska 
32586c95142eSMartin Matuska 		/*
32596c95142eSMartin Matuska 		 * A bit length is too big to be housed to a direct table,
32606c95142eSMartin Matuska 		 * so we use a tree model for its extra bits.
32616c95142eSMartin Matuska 		 */
32626c95142eSMartin Matuska 		bitptn[len] = ptn + cnt;
32636c95142eSMartin Matuska 		bit = 1U << (diffbits -1);
32646c95142eSMartin Matuska 		extlen = len - HTBL_BITS;
32656c95142eSMartin Matuska 
32666c95142eSMartin Matuska 		p = &(tbl[ptn >> diffbits]);
32676c95142eSMartin Matuska 		if (*p == 0) {
32686c95142eSMartin Matuska 			*p = len_avail + hf->tree_used;
32696c95142eSMartin Matuska 			ht = &(hf->tree[hf->tree_used++]);
32706c95142eSMartin Matuska 			if (hf->tree_used > hf->tree_avail)
32716c95142eSMartin Matuska 				return (0);/* Invalid */
32726c95142eSMartin Matuska 			ht->left = 0;
32736c95142eSMartin Matuska 			ht->right = 0;
32746c95142eSMartin Matuska 		} else {
32756c95142eSMartin Matuska 			if (*p < len_avail ||
32766c95142eSMartin Matuska 			    *p >= (len_avail + hf->tree_used))
32776c95142eSMartin Matuska 				return (0);/* Invalid */
32786c95142eSMartin Matuska 			ht = &(hf->tree[*p - len_avail]);
32796c95142eSMartin Matuska 		}
32806c95142eSMartin Matuska 		while (--extlen > 0) {
32816c95142eSMartin Matuska 			if (ptn & bit) {
32826c95142eSMartin Matuska 				if (ht->left < len_avail) {
32836c95142eSMartin Matuska 					ht->left = len_avail + hf->tree_used;
32846c95142eSMartin Matuska 					ht = &(hf->tree[hf->tree_used++]);
32856c95142eSMartin Matuska 					if (hf->tree_used > hf->tree_avail)
32866c95142eSMartin Matuska 						return (0);/* Invalid */
32876c95142eSMartin Matuska 					ht->left = 0;
32886c95142eSMartin Matuska 					ht->right = 0;
32896c95142eSMartin Matuska 				} else {
32906c95142eSMartin Matuska 					ht = &(hf->tree[ht->left - len_avail]);
32916c95142eSMartin Matuska 				}
32926c95142eSMartin Matuska 			} else {
32936c95142eSMartin Matuska 				if (ht->right < len_avail) {
32946c95142eSMartin Matuska 					ht->right = len_avail + hf->tree_used;
32956c95142eSMartin Matuska 					ht = &(hf->tree[hf->tree_used++]);
32966c95142eSMartin Matuska 					if (hf->tree_used > hf->tree_avail)
32976c95142eSMartin Matuska 						return (0);/* Invalid */
32986c95142eSMartin Matuska 					ht->left = 0;
32996c95142eSMartin Matuska 					ht->right = 0;
33006c95142eSMartin Matuska 				} else {
33016c95142eSMartin Matuska 					ht = &(hf->tree[ht->right - len_avail]);
33026c95142eSMartin Matuska 				}
33036c95142eSMartin Matuska 			}
33046c95142eSMartin Matuska 			bit >>= 1;
33056c95142eSMartin Matuska 		}
33066c95142eSMartin Matuska 		if (ptn & bit) {
33076c95142eSMartin Matuska 			if (ht->left != 0)
33086c95142eSMartin Matuska 				return (0);/* Invalid */
33096c95142eSMartin Matuska 			ht->left = (uint16_t)i;
33106c95142eSMartin Matuska 		} else {
33116c95142eSMartin Matuska 			if (ht->right != 0)
33126c95142eSMartin Matuska 				return (0);/* Invalid */
33136c95142eSMartin Matuska 			ht->right = (uint16_t)i;
33146c95142eSMartin Matuska 		}
33156c95142eSMartin Matuska 	}
33166c95142eSMartin Matuska 	return (1);
33176c95142eSMartin Matuska }
33186c95142eSMartin Matuska 
33196c95142eSMartin Matuska static int
33206c95142eSMartin Matuska lzx_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c)
33216c95142eSMartin Matuska {
33226c95142eSMartin Matuska 	struct htree_t *ht;
33236c95142eSMartin Matuska 	int extlen;
33246c95142eSMartin Matuska 
33256c95142eSMartin Matuska 	ht = hf->tree;
33266c95142eSMartin Matuska 	extlen = hf->shift_bits;
33276c95142eSMartin Matuska 	while (c >= hf->len_size) {
33286c95142eSMartin Matuska 		c -= hf->len_size;
33296c95142eSMartin Matuska 		if (extlen-- <= 0 || c >= hf->tree_used)
33306c95142eSMartin Matuska 			return (0);
33316c95142eSMartin Matuska 		if (rbits & (1U << extlen))
33326c95142eSMartin Matuska 			c = ht[c].left;
33336c95142eSMartin Matuska 		else
33346c95142eSMartin Matuska 			c = ht[c].right;
33356c95142eSMartin Matuska 	}
33366c95142eSMartin Matuska 	return (c);
33376c95142eSMartin Matuska }
33386c95142eSMartin Matuska 
33396c95142eSMartin Matuska static inline int
33406c95142eSMartin Matuska lzx_decode_huffman(struct huffman *hf, unsigned rbits)
33416c95142eSMartin Matuska {
33426c95142eSMartin Matuska 	int c;
33436c95142eSMartin Matuska 	/*
33446c95142eSMartin Matuska 	 * At first search an index table for a bit pattern.
33456c95142eSMartin Matuska 	 * If it fails, search a huffman tree for.
33466c95142eSMartin Matuska 	 */
33476c95142eSMartin Matuska 	c = hf->tbl[rbits >> hf->shift_bits];
33486c95142eSMartin Matuska 	if (c < hf->len_size)
33496c95142eSMartin Matuska 		return (c);
33506c95142eSMartin Matuska 	/* This bit pattern needs to be found out at a huffman tree. */
33516c95142eSMartin Matuska 	return (lzx_decode_huffman_tree(hf, rbits, c));
33526c95142eSMartin Matuska }
33536c95142eSMartin Matuska 
3354