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