1231200Smm/*- 2232153Smm * Copyright (c) 2010-2012 Michihiro NAKAJIMA 3231200Smm * All rights reserved. 4231200Smm * 5231200Smm * Redistribution and use in source and binary forms, with or without 6231200Smm * modification, are permitted provided that the following conditions 7231200Smm * are met: 8231200Smm * 1. Redistributions of source code must retain the above copyright 9231200Smm * notice, this list of conditions and the following disclaimer. 10231200Smm * 2. Redistributions in binary form must reproduce the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer in the 12231200Smm * documentation and/or other materials provided with the distribution. 13231200Smm * 14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24231200Smm */ 25231200Smm 26231200Smm#include "archive_platform.h" 27231200Smm 28231200Smm#ifdef HAVE_ERRNO_H 29231200Smm#include <errno.h> 30231200Smm#endif 31231200Smm#ifdef HAVE_LIMITS_H 32231200Smm#include <limits.h> 33231200Smm#endif 34231200Smm#ifdef HAVE_STDLIB_H 35231200Smm#include <stdlib.h> 36231200Smm#endif 37231200Smm#ifdef HAVE_STRING_H 38231200Smm#include <string.h> 39231200Smm#endif 40231200Smm#ifdef HAVE_ZLIB_H 41231200Smm#include <zlib.h> 42231200Smm#endif 43231200Smm 44231200Smm#include "archive.h" 45231200Smm#include "archive_entry.h" 46231200Smm#include "archive_entry_locale.h" 47231200Smm#include "archive_private.h" 48231200Smm#include "archive_read_private.h" 49231200Smm#include "archive_endian.h" 50231200Smm 51231200Smm 52231200Smmstruct lzx_dec { 53231200Smm /* Decoding status. */ 54231200Smm int state; 55231200Smm 56231200Smm /* 57231200Smm * Window to see last decoded data, from 32KBi to 2MBi. 58231200Smm */ 59231200Smm int w_size; 60231200Smm int w_mask; 61231200Smm /* Window buffer, which is a loop buffer. */ 62231200Smm unsigned char *w_buff; 63231200Smm /* The insert position to the window. */ 64231200Smm int w_pos; 65231200Smm /* The position where we can copy decoded code from the window. */ 66231200Smm int copy_pos; 67231200Smm /* The length how many bytes we can copy decoded code from 68231200Smm * the window. */ 69231200Smm int copy_len; 70311042Smm /* Translation reversal for x86 processor CALL byte sequence(E8). 71231200Smm * This is used for LZX only. */ 72231200Smm uint32_t translation_size; 73231200Smm char translation; 74231200Smm char block_type; 75231200Smm#define VERBATIM_BLOCK 1 76231200Smm#define ALIGNED_OFFSET_BLOCK 2 77231200Smm#define UNCOMPRESSED_BLOCK 3 78231200Smm size_t block_size; 79231200Smm size_t block_bytes_avail; 80231200Smm /* Repeated offset. */ 81231200Smm int r0, r1, r2; 82231200Smm unsigned char rbytes[4]; 83231200Smm int rbytes_avail; 84231200Smm int length_header; 85231200Smm int position_slot; 86231200Smm int offset_bits; 87231200Smm 88231200Smm struct lzx_pos_tbl { 89231200Smm int base; 90231200Smm int footer_bits; 91231200Smm } *pos_tbl; 92231200Smm /* 93231200Smm * Bit stream reader. 94231200Smm */ 95231200Smm struct lzx_br { 96231200Smm#define CACHE_TYPE uint64_t 97231200Smm#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) 98231200Smm /* Cache buffer. */ 99231200Smm CACHE_TYPE cache_buffer; 100231200Smm /* Indicates how many bits avail in cache_buffer. */ 101231200Smm int cache_avail; 102231200Smm unsigned char odd; 103231200Smm char have_odd; 104231200Smm } br; 105231200Smm 106231200Smm /* 107231200Smm * Huffman coding. 108231200Smm */ 109231200Smm struct huffman { 110231200Smm int len_size; 111231200Smm int freq[17]; 112231200Smm unsigned char *bitlen; 113231200Smm 114231200Smm /* 115231200Smm * Use a index table. It's faster than searching a huffman 116231200Smm * coding tree, which is a binary tree. But a use of a large 117231200Smm * index table causes L1 cache read miss many times. 118231200Smm */ 119231200Smm int max_bits; 120231200Smm int tbl_bits; 121231200Smm int tree_used; 122231200Smm /* Direct access table. */ 123231200Smm uint16_t *tbl; 124231200Smm } at, lt, mt, pt; 125231200Smm 126231200Smm int loop; 127231200Smm int error; 128231200Smm}; 129231200Smm 130231200Smmstatic const int slots[] = { 131231200Smm 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290 132231200Smm}; 133231200Smm#define SLOT_BASE 15 134231200Smm#define SLOT_MAX 21/*->25*/ 135231200Smm 136231200Smmstruct lzx_stream { 137231200Smm const unsigned char *next_in; 138231200Smm int64_t avail_in; 139231200Smm int64_t total_in; 140231200Smm unsigned char *next_out; 141231200Smm int64_t avail_out; 142231200Smm int64_t total_out; 143231200Smm struct lzx_dec *ds; 144231200Smm}; 145231200Smm 146231200Smm/* 147231200Smm * Cabinet file definitions. 148231200Smm */ 149231200Smm/* CFHEADER offset */ 150231200Smm#define CFHEADER_signature 0 151231200Smm#define CFHEADER_cbCabinet 8 152231200Smm#define CFHEADER_coffFiles 16 153231200Smm#define CFHEADER_versionMinor 24 154231200Smm#define CFHEADER_versionMajor 25 155231200Smm#define CFHEADER_cFolders 26 156231200Smm#define CFHEADER_cFiles 28 157231200Smm#define CFHEADER_flags 30 158231200Smm#define CFHEADER_setID 32 159231200Smm#define CFHEADER_iCabinet 34 160231200Smm#define CFHEADER_cbCFHeader 36 161231200Smm#define CFHEADER_cbCFFolder 38 162231200Smm#define CFHEADER_cbCFData 39 163231200Smm 164231200Smm/* CFFOLDER offset */ 165231200Smm#define CFFOLDER_coffCabStart 0 166231200Smm#define CFFOLDER_cCFData 4 167231200Smm#define CFFOLDER_typeCompress 6 168231200Smm#define CFFOLDER_abReserve 8 169231200Smm 170231200Smm/* CFFILE offset */ 171231200Smm#define CFFILE_cbFile 0 172231200Smm#define CFFILE_uoffFolderStart 4 173231200Smm#define CFFILE_iFolder 8 174231200Smm#define CFFILE_date_time 10 175231200Smm#define CFFILE_attribs 14 176231200Smm 177231200Smm/* CFDATA offset */ 178231200Smm#define CFDATA_csum 0 179231200Smm#define CFDATA_cbData 4 180231200Smm#define CFDATA_cbUncomp 6 181231200Smm 182316338Smmstatic const char * const compression_name[] = { 183231200Smm "NONE", 184231200Smm "MSZIP", 185231200Smm "Quantum", 186231200Smm "LZX", 187231200Smm}; 188231200Smm 189231200Smmstruct cfdata { 190231200Smm /* Sum value of this CFDATA. */ 191231200Smm uint32_t sum; 192231200Smm uint16_t compressed_size; 193231200Smm uint16_t compressed_bytes_remaining; 194231200Smm uint16_t uncompressed_size; 195231200Smm uint16_t uncompressed_bytes_remaining; 196231200Smm /* To know how many bytes we have decompressed. */ 197231200Smm uint16_t uncompressed_avail; 198231200Smm /* Offset from the beginning of compressed data of this CFDATA */ 199231200Smm uint16_t read_offset; 200231200Smm int64_t unconsumed; 201231200Smm /* To keep memory image of this CFDATA to compute the sum. */ 202231200Smm size_t memimage_size; 203231200Smm unsigned char *memimage; 204231200Smm /* Result of calculation of sum. */ 205231200Smm uint32_t sum_calculated; 206231200Smm unsigned char sum_extra[4]; 207231200Smm int sum_extra_avail; 208231200Smm const void *sum_ptr; 209231200Smm}; 210231200Smm 211231200Smmstruct cffolder { 212231200Smm uint32_t cfdata_offset_in_cab; 213231200Smm uint16_t cfdata_count; 214231200Smm uint16_t comptype; 215231200Smm#define COMPTYPE_NONE 0x0000 216231200Smm#define COMPTYPE_MSZIP 0x0001 217231200Smm#define COMPTYPE_QUANTUM 0x0002 218231200Smm#define COMPTYPE_LZX 0x0003 219231200Smm uint16_t compdata; 220231200Smm const char *compname; 221231200Smm /* At the time reading CFDATA */ 222231200Smm struct cfdata cfdata; 223231200Smm int cfdata_index; 224231200Smm /* Flags to mark progress of decompression. */ 225231200Smm char decompress_init; 226231200Smm}; 227231200Smm 228231200Smmstruct cffile { 229231200Smm uint32_t uncompressed_size; 230231200Smm uint32_t offset; 231231200Smm time_t mtime; 232231200Smm uint16_t folder; 233231200Smm#define iFoldCONTINUED_FROM_PREV 0xFFFD 234231200Smm#define iFoldCONTINUED_TO_NEXT 0xFFFE 235231200Smm#define iFoldCONTINUED_PREV_AND_NEXT 0xFFFF 236231200Smm unsigned char attr; 237231200Smm#define ATTR_RDONLY 0x01 238231200Smm#define ATTR_NAME_IS_UTF 0x80 239231200Smm struct archive_string pathname; 240231200Smm}; 241231200Smm 242231200Smmstruct cfheader { 243231200Smm /* Total bytes of all file size in a Cabinet. */ 244231200Smm uint32_t total_bytes; 245231200Smm uint32_t files_offset; 246231200Smm uint16_t folder_count; 247231200Smm uint16_t file_count; 248231200Smm uint16_t flags; 249231200Smm#define PREV_CABINET 0x0001 250231200Smm#define NEXT_CABINET 0x0002 251231200Smm#define RESERVE_PRESENT 0x0004 252231200Smm uint16_t setid; 253231200Smm uint16_t cabinet; 254231200Smm /* Version number. */ 255231200Smm unsigned char major; 256231200Smm unsigned char minor; 257231200Smm unsigned char cffolder; 258231200Smm unsigned char cfdata; 259231200Smm /* All folders in a cabinet. */ 260231200Smm struct cffolder *folder_array; 261231200Smm /* All files in a cabinet. */ 262231200Smm struct cffile *file_array; 263231200Smm int file_index; 264231200Smm}; 265231200Smm 266231200Smmstruct cab { 267231200Smm /* entry_bytes_remaining is the number of bytes we expect. */ 268231200Smm int64_t entry_offset; 269231200Smm int64_t entry_bytes_remaining; 270231200Smm int64_t entry_unconsumed; 271231200Smm int64_t entry_compressed_bytes_read; 272231200Smm int64_t entry_uncompressed_bytes_read; 273231200Smm struct cffolder *entry_cffolder; 274231200Smm struct cffile *entry_cffile; 275231200Smm struct cfdata *entry_cfdata; 276231200Smm 277231200Smm /* Offset from beginning of a cabinet file. */ 278231200Smm int64_t cab_offset; 279231200Smm struct cfheader cfheader; 280231200Smm struct archive_wstring ws; 281231200Smm 282231200Smm /* Flag to mark progress that an archive was read their first header.*/ 283231200Smm char found_header; 284231200Smm char end_of_archive; 285231200Smm char end_of_entry; 286231200Smm char end_of_entry_cleanup; 287238856Smm char read_data_invoked; 288238856Smm int64_t bytes_skipped; 289231200Smm 290231200Smm unsigned char *uncompressed_buffer; 291231200Smm size_t uncompressed_buffer_size; 292231200Smm 293231200Smm int init_default_conversion; 294231200Smm struct archive_string_conv *sconv; 295231200Smm struct archive_string_conv *sconv_default; 296231200Smm struct archive_string_conv *sconv_utf8; 297231200Smm char format_name[64]; 298231200Smm 299231200Smm#ifdef HAVE_ZLIB_H 300231200Smm z_stream stream; 301231200Smm char stream_valid; 302231200Smm#endif 303231200Smm struct lzx_stream xstrm; 304231200Smm}; 305231200Smm 306231200Smmstatic int archive_read_format_cab_bid(struct archive_read *, int); 307231200Smmstatic int archive_read_format_cab_options(struct archive_read *, 308231200Smm const char *, const char *); 309231200Smmstatic int archive_read_format_cab_read_header(struct archive_read *, 310231200Smm struct archive_entry *); 311231200Smmstatic int archive_read_format_cab_read_data(struct archive_read *, 312231200Smm const void **, size_t *, int64_t *); 313231200Smmstatic int archive_read_format_cab_read_data_skip(struct archive_read *); 314231200Smmstatic int archive_read_format_cab_cleanup(struct archive_read *); 315231200Smm 316231200Smmstatic int cab_skip_sfx(struct archive_read *); 317231200Smmstatic time_t cab_dos_time(const unsigned char *); 318231200Smmstatic int cab_read_data(struct archive_read *, const void **, 319231200Smm size_t *, int64_t *); 320231200Smmstatic int cab_read_header(struct archive_read *); 321231200Smmstatic uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t); 322231200Smmstatic uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t); 323231200Smmstatic void cab_checksum_update(struct archive_read *, size_t); 324231200Smmstatic int cab_checksum_finish(struct archive_read *); 325231200Smmstatic int cab_next_cfdata(struct archive_read *); 326231200Smmstatic const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *); 327231200Smmstatic const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *); 328231200Smmstatic const void *cab_read_ahead_cfdata_deflate(struct archive_read *, 329231200Smm ssize_t *); 330231200Smmstatic const void *cab_read_ahead_cfdata_lzx(struct archive_read *, 331231200Smm ssize_t *); 332231200Smmstatic int64_t cab_consume_cfdata(struct archive_read *, int64_t); 333231200Smmstatic int64_t cab_minimum_consume_cfdata(struct archive_read *, int64_t); 334231200Smmstatic int lzx_decode_init(struct lzx_stream *, int); 335231200Smmstatic int lzx_read_blocks(struct lzx_stream *, int); 336231200Smmstatic int lzx_decode_blocks(struct lzx_stream *, int); 337231200Smmstatic void lzx_decode_free(struct lzx_stream *); 338231200Smmstatic void lzx_translation(struct lzx_stream *, void *, size_t, uint32_t); 339231200Smmstatic void lzx_cleanup_bitstream(struct lzx_stream *); 340231200Smmstatic int lzx_decode(struct lzx_stream *, int); 341231200Smmstatic int lzx_read_pre_tree(struct lzx_stream *); 342231200Smmstatic int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int); 343231200Smmstatic int lzx_huffman_init(struct huffman *, size_t, int); 344231200Smmstatic void lzx_huffman_free(struct huffman *); 345231200Smmstatic int lzx_make_huffman_table(struct huffman *); 346232153Smmstatic inline int lzx_decode_huffman(struct huffman *, unsigned); 347231200Smm 348231200Smm 349231200Smmint 350231200Smmarchive_read_support_format_cab(struct archive *_a) 351231200Smm{ 352231200Smm struct archive_read *a = (struct archive_read *)_a; 353231200Smm struct cab *cab; 354231200Smm int r; 355231200Smm 356231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 357231200Smm ARCHIVE_STATE_NEW, "archive_read_support_format_cab"); 358231200Smm 359231200Smm cab = (struct cab *)calloc(1, sizeof(*cab)); 360231200Smm if (cab == NULL) { 361231200Smm archive_set_error(&a->archive, ENOMEM, 362231200Smm "Can't allocate CAB data"); 363231200Smm return (ARCHIVE_FATAL); 364231200Smm } 365231200Smm archive_string_init(&cab->ws); 366231200Smm archive_wstring_ensure(&cab->ws, 256); 367231200Smm 368231200Smm r = __archive_read_register_format(a, 369231200Smm cab, 370231200Smm "cab", 371231200Smm archive_read_format_cab_bid, 372231200Smm archive_read_format_cab_options, 373231200Smm archive_read_format_cab_read_header, 374231200Smm archive_read_format_cab_read_data, 375231200Smm archive_read_format_cab_read_data_skip, 376248616Smm NULL, 377302001Smm archive_read_format_cab_cleanup, 378302001Smm NULL, 379302001Smm NULL); 380231200Smm 381231200Smm if (r != ARCHIVE_OK) 382231200Smm free(cab); 383231200Smm return (ARCHIVE_OK); 384231200Smm} 385231200Smm 386231200Smmstatic int 387231200Smmfind_cab_magic(const char *p) 388231200Smm{ 389231200Smm switch (p[4]) { 390231200Smm case 0: 391231200Smm /* 392231200Smm * Note: Self-Extraction program has 'MSCF' string in their 393231200Smm * program. If we were finding 'MSCF' string only, we got 394231200Smm * wrong place for Cabinet header, thus, we have to check 395231200Smm * following four bytes which are reserved and must be set 396231200Smm * to zero. 397231200Smm */ 398231200Smm if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) 399231200Smm return 0; 400231200Smm return 5; 401231200Smm case 'F': return 1; 402231200Smm case 'C': return 2; 403231200Smm case 'S': return 3; 404231200Smm case 'M': return 4; 405231200Smm default: return 5; 406231200Smm } 407231200Smm} 408231200Smm 409231200Smmstatic int 410231200Smmarchive_read_format_cab_bid(struct archive_read *a, int best_bid) 411231200Smm{ 412231200Smm const char *p; 413231200Smm ssize_t bytes_avail, offset, window; 414231200Smm 415231200Smm /* If there's already a better bid than we can ever 416231200Smm make, don't bother testing. */ 417231200Smm if (best_bid > 64) 418231200Smm return (-1); 419231200Smm 420231200Smm if ((p = __archive_read_ahead(a, 8, NULL)) == NULL) 421231200Smm return (-1); 422231200Smm 423231200Smm if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) 424231200Smm return (64); 425231200Smm 426231200Smm /* 427231200Smm * Attempt to handle self-extracting archives 428231200Smm * by noting a PE header and searching forward 429231200Smm * up to 128k for a 'MSCF' marker. 430231200Smm */ 431231200Smm if (p[0] == 'M' && p[1] == 'Z') { 432231200Smm offset = 0; 433231200Smm window = 4096; 434231200Smm while (offset < (1024 * 128)) { 435231200Smm const char *h = __archive_read_ahead(a, offset + window, 436231200Smm &bytes_avail); 437231200Smm if (h == NULL) { 438231200Smm /* Remaining bytes are less than window. */ 439231200Smm window >>= 1; 440231200Smm if (window < 128) 441231200Smm return (0); 442231200Smm continue; 443231200Smm } 444231200Smm p = h + offset; 445231200Smm while (p + 8 < h + bytes_avail) { 446231200Smm int next; 447231200Smm if ((next = find_cab_magic(p)) == 0) 448231200Smm return (64); 449231200Smm p += next; 450231200Smm } 451231200Smm offset = p - h; 452231200Smm } 453231200Smm } 454231200Smm return (0); 455231200Smm} 456231200Smm 457231200Smmstatic int 458231200Smmarchive_read_format_cab_options(struct archive_read *a, 459231200Smm const char *key, const char *val) 460231200Smm{ 461231200Smm struct cab *cab; 462231200Smm int ret = ARCHIVE_FAILED; 463231200Smm 464231200Smm cab = (struct cab *)(a->format->data); 465231200Smm if (strcmp(key, "hdrcharset") == 0) { 466231200Smm if (val == NULL || val[0] == 0) 467231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 468231200Smm "cab: hdrcharset option needs a character-set name"); 469231200Smm else { 470231200Smm cab->sconv = archive_string_conversion_from_charset( 471231200Smm &a->archive, val, 0); 472231200Smm if (cab->sconv != NULL) 473231200Smm ret = ARCHIVE_OK; 474231200Smm else 475231200Smm ret = ARCHIVE_FATAL; 476231200Smm } 477232153Smm return (ret); 478232153Smm } 479231200Smm 480232153Smm /* Note: The "warn" return is just to inform the options 481232153Smm * supervisor that we didn't handle it. It will generate 482232153Smm * a suitable error if no one used this option. */ 483232153Smm return (ARCHIVE_WARN); 484231200Smm} 485231200Smm 486231200Smmstatic int 487231200Smmcab_skip_sfx(struct archive_read *a) 488231200Smm{ 489231200Smm const char *p, *q; 490231200Smm size_t skip; 491231200Smm ssize_t bytes, window; 492231200Smm 493231200Smm window = 4096; 494231200Smm for (;;) { 495231200Smm const char *h = __archive_read_ahead(a, window, &bytes); 496231200Smm if (h == NULL) { 497231200Smm /* Remaining size are less than window. */ 498231200Smm window >>= 1; 499231200Smm if (window < 128) { 500231200Smm archive_set_error(&a->archive, 501231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 502231200Smm "Couldn't find out CAB header"); 503231200Smm return (ARCHIVE_FATAL); 504231200Smm } 505231200Smm continue; 506231200Smm } 507231200Smm p = h; 508231200Smm q = p + bytes; 509231200Smm 510231200Smm /* 511231200Smm * Scan ahead until we find something that looks 512231200Smm * like the cab header. 513231200Smm */ 514231200Smm while (p + 8 < q) { 515231200Smm int next; 516231200Smm if ((next = find_cab_magic(p)) == 0) { 517231200Smm skip = p - h; 518231200Smm __archive_read_consume(a, skip); 519231200Smm return (ARCHIVE_OK); 520231200Smm } 521231200Smm p += next; 522231200Smm } 523231200Smm skip = p - h; 524231200Smm __archive_read_consume(a, skip); 525231200Smm } 526231200Smm} 527231200Smm 528231200Smmstatic int 529231200Smmtruncated_error(struct archive_read *a) 530231200Smm{ 531231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 532231200Smm "Truncated CAB header"); 533231200Smm return (ARCHIVE_FATAL); 534231200Smm} 535231200Smm 536248616Smmstatic ssize_t 537231200Smmcab_strnlen(const unsigned char *p, size_t maxlen) 538231200Smm{ 539231200Smm size_t i; 540231200Smm 541231200Smm for (i = 0; i <= maxlen; i++) { 542231200Smm if (p[i] == 0) 543231200Smm break; 544231200Smm } 545231200Smm if (i > maxlen) 546231200Smm return (-1);/* invalid */ 547248616Smm return ((ssize_t)i); 548231200Smm} 549231200Smm 550231200Smm/* Read bytes as much as remaining. */ 551231200Smmstatic const void * 552231200Smmcab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail) 553231200Smm{ 554231200Smm const void *p; 555231200Smm 556231200Smm while (min > 0) { 557231200Smm p = __archive_read_ahead(a, min, avail); 558231200Smm if (p != NULL) 559231200Smm return (p); 560231200Smm min--; 561231200Smm } 562231200Smm return (NULL); 563231200Smm} 564231200Smm 565231200Smm/* Convert a path separator '\' -> '/' */ 566231200Smmstatic int 567231200Smmcab_convert_path_separator_1(struct archive_string *fn, unsigned char attr) 568231200Smm{ 569231200Smm size_t i; 570231200Smm int mb; 571231200Smm 572231200Smm /* Easy check if we have '\' in multi-byte string. */ 573231200Smm mb = 0; 574231200Smm for (i = 0; i < archive_strlen(fn); i++) { 575231200Smm if (fn->s[i] == '\\') { 576231200Smm if (mb) { 577231200Smm /* This may be second byte of multi-byte 578231200Smm * character. */ 579231200Smm break; 580231200Smm } 581231200Smm fn->s[i] = '/'; 582231200Smm mb = 0; 583231200Smm } else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF)) 584231200Smm mb = 1; 585231200Smm else 586231200Smm mb = 0; 587231200Smm } 588231200Smm if (i == archive_strlen(fn)) 589231200Smm return (0); 590231200Smm return (-1); 591231200Smm} 592231200Smm 593231200Smm/* 594231200Smm * Replace a character '\' with '/' in wide character. 595231200Smm */ 596231200Smmstatic void 597231200Smmcab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry) 598231200Smm{ 599231200Smm const wchar_t *wp; 600231200Smm size_t i; 601231200Smm 602231200Smm /* If a conversion to wide character failed, force the replacement. */ 603231200Smm if ((wp = archive_entry_pathname_w(entry)) != NULL) { 604231200Smm archive_wstrcpy(&(cab->ws), wp); 605231200Smm for (i = 0; i < archive_strlen(&(cab->ws)); i++) { 606231200Smm if (cab->ws.s[i] == L'\\') 607231200Smm cab->ws.s[i] = L'/'; 608231200Smm } 609231200Smm archive_entry_copy_pathname_w(entry, cab->ws.s); 610231200Smm } 611231200Smm} 612231200Smm 613231200Smm/* 614231200Smm * Read CFHEADER, CFFOLDER and CFFILE. 615231200Smm */ 616231200Smmstatic int 617231200Smmcab_read_header(struct archive_read *a) 618231200Smm{ 619231200Smm const unsigned char *p; 620231200Smm struct cab *cab; 621231200Smm struct cfheader *hd; 622231200Smm size_t bytes, used; 623248616Smm ssize_t len; 624231200Smm int64_t skip; 625248616Smm int err, i; 626231200Smm int cur_folder, prev_folder; 627231200Smm uint32_t offset32; 628231200Smm 629231200Smm a->archive.archive_format = ARCHIVE_FORMAT_CAB; 630231200Smm if (a->archive.archive_format_name == NULL) 631231200Smm a->archive.archive_format_name = "CAB"; 632231200Smm 633231200Smm if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) 634231200Smm return (truncated_error(a)); 635231200Smm 636231200Smm cab = (struct cab *)(a->format->data); 637231200Smm if (cab->found_header == 0 && 638231200Smm p[0] == 'M' && p[1] == 'Z') { 639311042Smm /* This is an executable? Must be self-extracting... */ 640231200Smm err = cab_skip_sfx(a); 641231200Smm if (err < ARCHIVE_WARN) 642231200Smm return (err); 643231200Smm 644311042Smm /* Re-read header after processing the SFX. */ 645311042Smm if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) 646231200Smm return (truncated_error(a)); 647231200Smm } 648231200Smm 649231200Smm cab->cab_offset = 0; 650231200Smm /* 651231200Smm * Read CFHEADER. 652231200Smm */ 653231200Smm hd = &cab->cfheader; 654231200Smm if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' || 655231200Smm p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') { 656231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 657231200Smm "Couldn't find out CAB header"); 658231200Smm return (ARCHIVE_FATAL); 659231200Smm } 660231200Smm hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet); 661231200Smm hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles); 662231200Smm hd->minor = p[CFHEADER_versionMinor]; 663231200Smm hd->major = p[CFHEADER_versionMajor]; 664231200Smm hd->folder_count = archive_le16dec(p + CFHEADER_cFolders); 665231200Smm if (hd->folder_count == 0) 666231200Smm goto invalid; 667231200Smm hd->file_count = archive_le16dec(p + CFHEADER_cFiles); 668231200Smm if (hd->file_count == 0) 669231200Smm goto invalid; 670231200Smm hd->flags = archive_le16dec(p + CFHEADER_flags); 671231200Smm hd->setid = archive_le16dec(p + CFHEADER_setID); 672231200Smm hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet); 673231200Smm used = CFHEADER_iCabinet + 2; 674231200Smm if (hd->flags & RESERVE_PRESENT) { 675231200Smm uint16_t cfheader; 676231200Smm cfheader = archive_le16dec(p + CFHEADER_cbCFHeader); 677231200Smm if (cfheader > 60000U) 678231200Smm goto invalid; 679231200Smm hd->cffolder = p[CFHEADER_cbCFFolder]; 680231200Smm hd->cfdata = p[CFHEADER_cbCFData]; 681231200Smm used += 4;/* cbCFHeader, cbCFFolder and cbCFData */ 682231200Smm used += cfheader;/* abReserve */ 683231200Smm } else 684231200Smm hd->cffolder = 0;/* Avoid compiling warning. */ 685231200Smm if (hd->flags & PREV_CABINET) { 686231200Smm /* How many bytes are used for szCabinetPrev. */ 687231200Smm if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) 688231200Smm return (truncated_error(a)); 689231200Smm if ((len = cab_strnlen(p + used, 255)) <= 0) 690231200Smm goto invalid; 691231200Smm used += len + 1; 692231200Smm /* How many bytes are used for szDiskPrev. */ 693231200Smm if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) 694231200Smm return (truncated_error(a)); 695231200Smm if ((len = cab_strnlen(p + used, 255)) <= 0) 696231200Smm goto invalid; 697231200Smm used += len + 1; 698231200Smm } 699231200Smm if (hd->flags & NEXT_CABINET) { 700231200Smm /* How many bytes are used for szCabinetNext. */ 701231200Smm if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) 702231200Smm return (truncated_error(a)); 703231200Smm if ((len = cab_strnlen(p + used, 255)) <= 0) 704231200Smm goto invalid; 705231200Smm used += len + 1; 706231200Smm /* How many bytes are used for szDiskNext. */ 707231200Smm if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) 708231200Smm return (truncated_error(a)); 709231200Smm if ((len = cab_strnlen(p + used, 255)) <= 0) 710231200Smm goto invalid; 711231200Smm used += len + 1; 712231200Smm } 713231200Smm __archive_read_consume(a, used); 714231200Smm cab->cab_offset += used; 715231200Smm used = 0; 716231200Smm 717231200Smm /* 718231200Smm * Read CFFOLDER. 719231200Smm */ 720231200Smm hd->folder_array = (struct cffolder *)calloc( 721231200Smm hd->folder_count, sizeof(struct cffolder)); 722231200Smm if (hd->folder_array == NULL) 723231200Smm goto nomem; 724231200Smm 725231200Smm bytes = 8; 726231200Smm if (hd->flags & RESERVE_PRESENT) 727231200Smm bytes += hd->cffolder; 728231200Smm bytes *= hd->folder_count; 729231200Smm if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL) 730231200Smm return (truncated_error(a)); 731231200Smm offset32 = 0; 732231200Smm for (i = 0; i < hd->folder_count; i++) { 733231200Smm struct cffolder *folder = &(hd->folder_array[i]); 734231200Smm folder->cfdata_offset_in_cab = 735231200Smm archive_le32dec(p + CFFOLDER_coffCabStart); 736231200Smm folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData); 737231200Smm folder->comptype = 738231200Smm archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F; 739231200Smm folder->compdata = 740231200Smm archive_le16dec(p+CFFOLDER_typeCompress) >> 8; 741231200Smm /* Get a compression name. */ 742231200Smm if (folder->comptype < 743231200Smm sizeof(compression_name) / sizeof(compression_name[0])) 744231200Smm folder->compname = compression_name[folder->comptype]; 745231200Smm else 746231200Smm folder->compname = "UNKNOWN"; 747231200Smm p += 8; 748231200Smm used += 8; 749231200Smm if (hd->flags & RESERVE_PRESENT) { 750231200Smm p += hd->cffolder;/* abReserve */ 751231200Smm used += hd->cffolder; 752231200Smm } 753231200Smm /* 754231200Smm * Sanity check if each data is acceptable. 755231200Smm */ 756231200Smm if (offset32 >= folder->cfdata_offset_in_cab) 757231200Smm goto invalid; 758231200Smm offset32 = folder->cfdata_offset_in_cab; 759231200Smm 760231200Smm /* Set a request to initialize zlib for the CFDATA of 761231200Smm * this folder. */ 762231200Smm folder->decompress_init = 0; 763231200Smm } 764231200Smm __archive_read_consume(a, used); 765231200Smm cab->cab_offset += used; 766231200Smm 767231200Smm /* 768231200Smm * Read CFFILE. 769231200Smm */ 770231200Smm /* Seek read pointer to the offset of CFFILE if needed. */ 771231200Smm skip = (int64_t)hd->files_offset - cab->cab_offset; 772231200Smm if (skip < 0) { 773231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 774231200Smm "Invalid offset of CFFILE %jd < %jd", 775231200Smm (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset); 776231200Smm return (ARCHIVE_FATAL); 777231200Smm } 778231200Smm if (skip) { 779231200Smm __archive_read_consume(a, skip); 780231200Smm cab->cab_offset += skip; 781231200Smm } 782231200Smm /* Allocate memory for CFDATA */ 783231200Smm hd->file_array = (struct cffile *)calloc( 784231200Smm hd->file_count, sizeof(struct cffile)); 785231200Smm if (hd->file_array == NULL) 786231200Smm goto nomem; 787231200Smm 788231200Smm prev_folder = -1; 789231200Smm for (i = 0; i < hd->file_count; i++) { 790231200Smm struct cffile *file = &(hd->file_array[i]); 791231200Smm ssize_t avail; 792231200Smm 793231200Smm if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) 794231200Smm return (truncated_error(a)); 795231200Smm file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile); 796231200Smm file->offset = archive_le32dec(p + CFFILE_uoffFolderStart); 797231200Smm file->folder = archive_le16dec(p + CFFILE_iFolder); 798231200Smm file->mtime = cab_dos_time(p + CFFILE_date_time); 799238856Smm file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs); 800231200Smm __archive_read_consume(a, 16); 801231200Smm 802231200Smm cab->cab_offset += 16; 803231200Smm if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL) 804231200Smm return (truncated_error(a)); 805231200Smm if ((len = cab_strnlen(p, avail-1)) <= 0) 806231200Smm goto invalid; 807231200Smm 808231200Smm /* Copy a pathname. */ 809231200Smm archive_string_init(&(file->pathname)); 810231200Smm archive_strncpy(&(file->pathname), p, len); 811231200Smm __archive_read_consume(a, len + 1); 812231200Smm cab->cab_offset += len + 1; 813231200Smm 814231200Smm /* 815231200Smm * Sanity check if each data is acceptable. 816231200Smm */ 817231200Smm if (file->uncompressed_size > 0x7FFF8000) 818231200Smm goto invalid;/* Too large */ 819231200Smm if ((int64_t)file->offset + (int64_t)file->uncompressed_size 820231200Smm > ARCHIVE_LITERAL_LL(0x7FFF8000)) 821231200Smm goto invalid;/* Too large */ 822231200Smm switch (file->folder) { 823231200Smm case iFoldCONTINUED_TO_NEXT: 824231200Smm /* This must be last file in a folder. */ 825231200Smm if (i != hd->file_count -1) 826231200Smm goto invalid; 827231200Smm cur_folder = hd->folder_count -1; 828231200Smm break; 829231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 830231200Smm /* This must be only one file in a folder. */ 831231200Smm if (hd->file_count != 1) 832231200Smm goto invalid; 833231200Smm /* FALL THROUGH */ 834231200Smm case iFoldCONTINUED_FROM_PREV: 835231200Smm /* This must be first file in a folder. */ 836231200Smm if (i != 0) 837231200Smm goto invalid; 838231200Smm prev_folder = cur_folder = 0; 839231200Smm offset32 = file->offset; 840231200Smm break; 841231200Smm default: 842231200Smm if (file->folder >= hd->folder_count) 843231200Smm goto invalid; 844231200Smm cur_folder = file->folder; 845231200Smm break; 846231200Smm } 847231200Smm /* Dot not back track. */ 848231200Smm if (cur_folder < prev_folder) 849231200Smm goto invalid; 850231200Smm if (cur_folder != prev_folder) 851231200Smm offset32 = 0; 852231200Smm prev_folder = cur_folder; 853231200Smm 854231200Smm /* Make sure there are not any blanks from last file 855231200Smm * contents. */ 856231200Smm if (offset32 != file->offset) 857231200Smm goto invalid; 858231200Smm offset32 += file->uncompressed_size; 859231200Smm 860231200Smm /* CFDATA is available for file contents. */ 861231200Smm if (file->uncompressed_size > 0 && 862231200Smm hd->folder_array[cur_folder].cfdata_count == 0) 863231200Smm goto invalid; 864231200Smm } 865231200Smm 866231200Smm if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) { 867231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 868231200Smm "Multivolume cabinet file is unsupported"); 869231200Smm return (ARCHIVE_WARN); 870231200Smm } 871231200Smm return (ARCHIVE_OK); 872231200Smminvalid: 873231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 874231200Smm "Invalid CAB header"); 875231200Smm return (ARCHIVE_FATAL); 876231200Smmnomem: 877231200Smm archive_set_error(&a->archive, ENOMEM, 878231200Smm "Can't allocate memory for CAB data"); 879231200Smm return (ARCHIVE_FATAL); 880231200Smm} 881231200Smm 882231200Smmstatic int 883231200Smmarchive_read_format_cab_read_header(struct archive_read *a, 884231200Smm struct archive_entry *entry) 885231200Smm{ 886231200Smm struct cab *cab; 887231200Smm struct cfheader *hd; 888231200Smm struct cffolder *prev_folder; 889231200Smm struct cffile *file; 890231200Smm struct archive_string_conv *sconv; 891231200Smm int err = ARCHIVE_OK, r; 892231200Smm 893231200Smm cab = (struct cab *)(a->format->data); 894231200Smm if (cab->found_header == 0) { 895231200Smm err = cab_read_header(a); 896231200Smm if (err < ARCHIVE_WARN) 897231200Smm return (err); 898231200Smm /* We've found the header. */ 899231200Smm cab->found_header = 1; 900231200Smm } 901231200Smm hd = &cab->cfheader; 902231200Smm 903231200Smm if (hd->file_index >= hd->file_count) { 904231200Smm cab->end_of_archive = 1; 905231200Smm return (ARCHIVE_EOF); 906231200Smm } 907231200Smm file = &hd->file_array[hd->file_index++]; 908231200Smm 909231200Smm cab->end_of_entry = 0; 910231200Smm cab->end_of_entry_cleanup = 0; 911231200Smm cab->entry_compressed_bytes_read = 0; 912231200Smm cab->entry_uncompressed_bytes_read = 0; 913231200Smm cab->entry_unconsumed = 0; 914231200Smm cab->entry_cffile = file; 915231200Smm 916231200Smm /* 917231200Smm * Choose a proper folder. 918231200Smm */ 919231200Smm prev_folder = cab->entry_cffolder; 920231200Smm switch (file->folder) { 921231200Smm case iFoldCONTINUED_FROM_PREV: 922231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 923231200Smm cab->entry_cffolder = &hd->folder_array[0]; 924231200Smm break; 925231200Smm case iFoldCONTINUED_TO_NEXT: 926231200Smm cab->entry_cffolder = &hd->folder_array[hd->folder_count-1]; 927231200Smm break; 928231200Smm default: 929231200Smm cab->entry_cffolder = &hd->folder_array[file->folder]; 930231200Smm break; 931231200Smm } 932231200Smm /* If a cffolder of this file is changed, reset a cfdata to read 933231200Smm * file contents from next cfdata. */ 934231200Smm if (prev_folder != cab->entry_cffolder) 935231200Smm cab->entry_cfdata = NULL; 936231200Smm 937231200Smm /* If a pathname is UTF-8, prepare a string conversion object 938231200Smm * for UTF-8 and use it. */ 939231200Smm if (file->attr & ATTR_NAME_IS_UTF) { 940231200Smm if (cab->sconv_utf8 == NULL) { 941231200Smm cab->sconv_utf8 = 942231200Smm archive_string_conversion_from_charset( 943231200Smm &(a->archive), "UTF-8", 1); 944231200Smm if (cab->sconv_utf8 == NULL) 945231200Smm return (ARCHIVE_FATAL); 946231200Smm } 947231200Smm sconv = cab->sconv_utf8; 948231200Smm } else if (cab->sconv != NULL) { 949231200Smm /* Choose the conversion specified by the option. */ 950231200Smm sconv = cab->sconv; 951231200Smm } else { 952231200Smm /* Choose the default conversion. */ 953231200Smm if (!cab->init_default_conversion) { 954231200Smm cab->sconv_default = 955231200Smm archive_string_default_conversion_for_read( 956231200Smm &(a->archive)); 957231200Smm cab->init_default_conversion = 1; 958231200Smm } 959231200Smm sconv = cab->sconv_default; 960231200Smm } 961231200Smm 962231200Smm /* 963231200Smm * Set a default value and common data 964231200Smm */ 965231200Smm r = cab_convert_path_separator_1(&(file->pathname), file->attr); 966231200Smm if (archive_entry_copy_pathname_l(entry, file->pathname.s, 967231200Smm archive_strlen(&(file->pathname)), sconv) != 0) { 968231200Smm if (errno == ENOMEM) { 969231200Smm archive_set_error(&a->archive, ENOMEM, 970231200Smm "Can't allocate memory for Pathname"); 971231200Smm return (ARCHIVE_FATAL); 972231200Smm } 973231200Smm archive_set_error(&a->archive, 974231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 975231200Smm "Pathname cannot be converted " 976231200Smm "from %s to current locale.", 977231200Smm archive_string_conversion_charset_name(sconv)); 978231200Smm err = ARCHIVE_WARN; 979231200Smm } 980231200Smm if (r < 0) { 981231200Smm /* Convert a path separator '\' -> '/' */ 982231200Smm cab_convert_path_separator_2(cab, entry); 983231200Smm } 984231200Smm 985231200Smm archive_entry_set_size(entry, file->uncompressed_size); 986231200Smm if (file->attr & ATTR_RDONLY) 987231200Smm archive_entry_set_mode(entry, AE_IFREG | 0555); 988231200Smm else 989238856Smm archive_entry_set_mode(entry, AE_IFREG | 0666); 990231200Smm archive_entry_set_mtime(entry, file->mtime, 0); 991231200Smm 992231200Smm cab->entry_bytes_remaining = file->uncompressed_size; 993231200Smm cab->entry_offset = 0; 994231200Smm /* We don't need compress data. */ 995231200Smm if (file->uncompressed_size == 0) 996231200Smm cab->end_of_entry_cleanup = cab->end_of_entry = 1; 997231200Smm 998231200Smm /* Set up a more descriptive format name. */ 999231200Smm sprintf(cab->format_name, "CAB %d.%d (%s)", 1000231200Smm hd->major, hd->minor, cab->entry_cffolder->compname); 1001231200Smm a->archive.archive_format_name = cab->format_name; 1002231200Smm 1003231200Smm return (err); 1004231200Smm} 1005231200Smm 1006231200Smmstatic int 1007231200Smmarchive_read_format_cab_read_data(struct archive_read *a, 1008231200Smm const void **buff, size_t *size, int64_t *offset) 1009231200Smm{ 1010231200Smm struct cab *cab = (struct cab *)(a->format->data); 1011231200Smm int r; 1012231200Smm 1013231200Smm switch (cab->entry_cffile->folder) { 1014231200Smm case iFoldCONTINUED_FROM_PREV: 1015231200Smm case iFoldCONTINUED_TO_NEXT: 1016231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 1017231200Smm *buff = NULL; 1018231200Smm *size = 0; 1019231200Smm *offset = 0; 1020231200Smm archive_clear_error(&a->archive); 1021231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1022231200Smm "Cannot restore this file split in multivolume."); 1023231200Smm return (ARCHIVE_FAILED); 1024231200Smm default: 1025231200Smm break; 1026231200Smm } 1027238856Smm if (cab->read_data_invoked == 0) { 1028238856Smm if (cab->bytes_skipped) { 1029238856Smm if (cab->entry_cfdata == NULL) { 1030238856Smm r = cab_next_cfdata(a); 1031238856Smm if (r < 0) 1032238856Smm return (r); 1033238856Smm } 1034238856Smm if (cab_consume_cfdata(a, cab->bytes_skipped) < 0) 1035238856Smm return (ARCHIVE_FATAL); 1036238856Smm cab->bytes_skipped = 0; 1037238856Smm } 1038238856Smm cab->read_data_invoked = 1; 1039238856Smm } 1040231200Smm if (cab->entry_unconsumed) { 1041231200Smm /* Consume as much as the compressor actually used. */ 1042238856Smm r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); 1043231200Smm cab->entry_unconsumed = 0; 1044231200Smm if (r < 0) 1045231200Smm return (r); 1046231200Smm } 1047231200Smm if (cab->end_of_archive || cab->end_of_entry) { 1048231200Smm if (!cab->end_of_entry_cleanup) { 1049231200Smm /* End-of-entry cleanup done. */ 1050231200Smm cab->end_of_entry_cleanup = 1; 1051231200Smm } 1052231200Smm *offset = cab->entry_offset; 1053231200Smm *size = 0; 1054231200Smm *buff = NULL; 1055231200Smm return (ARCHIVE_EOF); 1056231200Smm } 1057231200Smm 1058231200Smm return (cab_read_data(a, buff, size, offset)); 1059231200Smm} 1060231200Smm 1061231200Smmstatic uint32_t 1062231200Smmcab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed) 1063231200Smm{ 1064231200Smm const unsigned char *b; 1065248616Smm unsigned u32num; 1066231200Smm uint32_t sum; 1067231200Smm 1068248616Smm u32num = (unsigned)bytes / 4; 1069231200Smm sum = seed; 1070231200Smm b = p; 1071248616Smm for (;u32num > 0; --u32num) { 1072231200Smm sum ^= archive_le32dec(b); 1073231200Smm b += 4; 1074231200Smm } 1075231200Smm return (sum); 1076231200Smm} 1077231200Smm 1078231200Smmstatic uint32_t 1079231200Smmcab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed) 1080231200Smm{ 1081231200Smm const unsigned char *b; 1082231200Smm uint32_t sum; 1083231200Smm uint32_t t; 1084231200Smm 1085231200Smm sum = cab_checksum_cfdata_4(p, bytes, seed); 1086231200Smm b = p; 1087231200Smm b += bytes & ~3; 1088231200Smm t = 0; 1089231200Smm switch (bytes & 3) { 1090231200Smm case 3: 1091231200Smm t |= ((uint32_t)(*b++)) << 16; 1092231200Smm /* FALL THROUGH */ 1093231200Smm case 2: 1094231200Smm t |= ((uint32_t)(*b++)) << 8; 1095231200Smm /* FALL THROUGH */ 1096231200Smm case 1: 1097231200Smm t |= *b; 1098231200Smm /* FALL THROUGH */ 1099231200Smm default: 1100231200Smm break; 1101231200Smm } 1102231200Smm sum ^= t; 1103231200Smm 1104231200Smm return (sum); 1105231200Smm} 1106231200Smm 1107231200Smmstatic void 1108231200Smmcab_checksum_update(struct archive_read *a, size_t bytes) 1109231200Smm{ 1110231200Smm struct cab *cab = (struct cab *)(a->format->data); 1111231200Smm struct cfdata *cfdata = cab->entry_cfdata; 1112231200Smm const unsigned char *p; 1113231200Smm size_t sumbytes; 1114231200Smm 1115231200Smm if (cfdata->sum == 0 || cfdata->sum_ptr == NULL) 1116231200Smm return; 1117231200Smm /* 1118231200Smm * Calculate the sum of this CFDATA. 1119231200Smm * Make sure CFDATA must be calculated in four bytes. 1120231200Smm */ 1121231200Smm p = cfdata->sum_ptr; 1122231200Smm sumbytes = bytes; 1123231200Smm if (cfdata->sum_extra_avail) { 1124231200Smm while (cfdata->sum_extra_avail < 4 && sumbytes > 0) { 1125231200Smm cfdata->sum_extra[ 1126231200Smm cfdata->sum_extra_avail++] = *p++; 1127231200Smm sumbytes--; 1128231200Smm } 1129231200Smm if (cfdata->sum_extra_avail == 4) { 1130231200Smm cfdata->sum_calculated = cab_checksum_cfdata_4( 1131231200Smm cfdata->sum_extra, 4, cfdata->sum_calculated); 1132231200Smm cfdata->sum_extra_avail = 0; 1133231200Smm } 1134231200Smm } 1135231200Smm if (sumbytes) { 1136231200Smm int odd = sumbytes & 3; 1137231200Smm if (sumbytes - odd > 0) 1138231200Smm cfdata->sum_calculated = cab_checksum_cfdata_4( 1139231200Smm p, sumbytes - odd, cfdata->sum_calculated); 1140231200Smm if (odd) 1141231200Smm memcpy(cfdata->sum_extra, p + sumbytes - odd, odd); 1142231200Smm cfdata->sum_extra_avail = odd; 1143231200Smm } 1144231200Smm cfdata->sum_ptr = NULL; 1145231200Smm} 1146231200Smm 1147231200Smmstatic int 1148231200Smmcab_checksum_finish(struct archive_read *a) 1149231200Smm{ 1150231200Smm struct cab *cab = (struct cab *)(a->format->data); 1151231200Smm struct cfdata *cfdata = cab->entry_cfdata; 1152231200Smm int l; 1153231200Smm 1154231200Smm /* Do not need to compute a sum. */ 1155231200Smm if (cfdata->sum == 0) 1156231200Smm return (ARCHIVE_OK); 1157231200Smm 1158231200Smm /* 1159231200Smm * Calculate the sum of remaining CFDATA. 1160231200Smm */ 1161231200Smm if (cfdata->sum_extra_avail) { 1162231200Smm cfdata->sum_calculated = 1163231200Smm cab_checksum_cfdata(cfdata->sum_extra, 1164231200Smm cfdata->sum_extra_avail, cfdata->sum_calculated); 1165231200Smm cfdata->sum_extra_avail = 0; 1166231200Smm } 1167231200Smm 1168231200Smm l = 4; 1169231200Smm if (cab->cfheader.flags & RESERVE_PRESENT) 1170231200Smm l += cab->cfheader.cfdata; 1171231200Smm cfdata->sum_calculated = cab_checksum_cfdata( 1172231200Smm cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); 1173231200Smm if (cfdata->sum_calculated != cfdata->sum) { 1174231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1175368708Smm "Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes", 1176231200Smm cab->entry_cffolder->cfdata_index -1, 1177231200Smm cfdata->sum, cfdata->sum_calculated, 1178231200Smm cfdata->compressed_size); 1179231200Smm return (ARCHIVE_FAILED); 1180231200Smm } 1181231200Smm return (ARCHIVE_OK); 1182231200Smm} 1183231200Smm 1184231200Smm/* 1185231200Smm * Read CFDATA if needed. 1186231200Smm */ 1187231200Smmstatic int 1188231200Smmcab_next_cfdata(struct archive_read *a) 1189231200Smm{ 1190231200Smm struct cab *cab = (struct cab *)(a->format->data); 1191231200Smm struct cfdata *cfdata = cab->entry_cfdata; 1192231200Smm 1193231200Smm /* There are remaining bytes in current CFDATA, use it first. */ 1194231200Smm if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0) 1195231200Smm return (ARCHIVE_OK); 1196231200Smm 1197231200Smm if (cfdata == NULL) { 1198231200Smm int64_t skip; 1199231200Smm 1200231200Smm cab->entry_cffolder->cfdata_index = 0; 1201231200Smm 1202231200Smm /* Seek read pointer to the offset of CFDATA if needed. */ 1203231200Smm skip = cab->entry_cffolder->cfdata_offset_in_cab 1204231200Smm - cab->cab_offset; 1205231200Smm if (skip < 0) { 1206231200Smm int folder_index; 1207231200Smm switch (cab->entry_cffile->folder) { 1208231200Smm case iFoldCONTINUED_FROM_PREV: 1209231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 1210231200Smm folder_index = 0; 1211231200Smm break; 1212231200Smm case iFoldCONTINUED_TO_NEXT: 1213231200Smm folder_index = cab->cfheader.folder_count-1; 1214231200Smm break; 1215231200Smm default: 1216231200Smm folder_index = cab->entry_cffile->folder; 1217231200Smm break; 1218231200Smm } 1219231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1220231200Smm "Invalid offset of CFDATA in folder(%d) %jd < %jd", 1221231200Smm folder_index, 1222231200Smm (intmax_t)cab->entry_cffolder->cfdata_offset_in_cab, 1223231200Smm (intmax_t)cab->cab_offset); 1224231200Smm return (ARCHIVE_FATAL); 1225231200Smm } 1226231200Smm if (skip > 0) { 1227231200Smm if (__archive_read_consume(a, skip) < 0) 1228231200Smm return (ARCHIVE_FATAL); 1229231200Smm cab->cab_offset = 1230231200Smm cab->entry_cffolder->cfdata_offset_in_cab; 1231231200Smm } 1232231200Smm } 1233231200Smm 1234231200Smm /* 1235231200Smm * Read a CFDATA. 1236231200Smm */ 1237231200Smm if (cab->entry_cffolder->cfdata_index < 1238231200Smm cab->entry_cffolder->cfdata_count) { 1239231200Smm const unsigned char *p; 1240231200Smm int l; 1241231200Smm 1242231200Smm cfdata = &(cab->entry_cffolder->cfdata); 1243231200Smm cab->entry_cffolder->cfdata_index++; 1244231200Smm cab->entry_cfdata = cfdata; 1245231200Smm cfdata->sum_calculated = 0; 1246231200Smm cfdata->sum_extra_avail = 0; 1247231200Smm cfdata->sum_ptr = NULL; 1248231200Smm l = 8; 1249231200Smm if (cab->cfheader.flags & RESERVE_PRESENT) 1250231200Smm l += cab->cfheader.cfdata; 1251231200Smm if ((p = __archive_read_ahead(a, l, NULL)) == NULL) 1252231200Smm return (truncated_error(a)); 1253231200Smm cfdata->sum = archive_le32dec(p + CFDATA_csum); 1254231200Smm cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData); 1255231200Smm cfdata->compressed_bytes_remaining = cfdata->compressed_size; 1256231200Smm cfdata->uncompressed_size = 1257231200Smm archive_le16dec(p + CFDATA_cbUncomp); 1258231200Smm cfdata->uncompressed_bytes_remaining = 1259231200Smm cfdata->uncompressed_size; 1260231200Smm cfdata->uncompressed_avail = 0; 1261231200Smm cfdata->read_offset = 0; 1262231200Smm cfdata->unconsumed = 0; 1263231200Smm 1264231200Smm /* 1265231200Smm * Sanity check if data size is acceptable. 1266231200Smm */ 1267231200Smm if (cfdata->compressed_size == 0 || 1268231200Smm cfdata->compressed_size > (0x8000+6144)) 1269231200Smm goto invalid; 1270231200Smm if (cfdata->uncompressed_size > 0x8000) 1271231200Smm goto invalid; 1272231200Smm if (cfdata->uncompressed_size == 0) { 1273231200Smm switch (cab->entry_cffile->folder) { 1274231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 1275231200Smm case iFoldCONTINUED_TO_NEXT: 1276231200Smm break; 1277231200Smm case iFoldCONTINUED_FROM_PREV: 1278231200Smm default: 1279231200Smm goto invalid; 1280231200Smm } 1281231200Smm } 1282231200Smm /* If CFDATA is not last in a folder, an uncompressed 1283231200Smm * size must be 0x8000(32KBi) */ 1284231200Smm if ((cab->entry_cffolder->cfdata_index < 1285231200Smm cab->entry_cffolder->cfdata_count) && 1286231200Smm cfdata->uncompressed_size != 0x8000) 1287231200Smm goto invalid; 1288231200Smm 1289231200Smm /* A compressed data size and an uncompressed data size must 1290231200Smm * be the same in no compression mode. */ 1291231200Smm if (cab->entry_cffolder->comptype == COMPTYPE_NONE && 1292231200Smm cfdata->compressed_size != cfdata->uncompressed_size) 1293231200Smm goto invalid; 1294231200Smm 1295231200Smm /* 1296231200Smm * Save CFDATA image for sum check. 1297231200Smm */ 1298231200Smm if (cfdata->memimage_size < (size_t)l) { 1299231200Smm free(cfdata->memimage); 1300231200Smm cfdata->memimage = malloc(l); 1301231200Smm if (cfdata->memimage == NULL) { 1302231200Smm archive_set_error(&a->archive, ENOMEM, 1303231200Smm "Can't allocate memory for CAB data"); 1304231200Smm return (ARCHIVE_FATAL); 1305231200Smm } 1306231200Smm cfdata->memimage_size = l; 1307231200Smm } 1308231200Smm memcpy(cfdata->memimage, p, l); 1309231200Smm 1310231200Smm /* Consume bytes as much as we used. */ 1311231200Smm __archive_read_consume(a, l); 1312231200Smm cab->cab_offset += l; 1313231200Smm } else if (cab->entry_cffolder->cfdata_count > 0) { 1314231200Smm /* Run out of all CFDATA in a folder. */ 1315231200Smm cfdata->compressed_size = 0; 1316231200Smm cfdata->uncompressed_size = 0; 1317231200Smm cfdata->compressed_bytes_remaining = 0; 1318231200Smm cfdata->uncompressed_bytes_remaining = 0; 1319231200Smm } else { 1320231200Smm /* Current folder does not have any CFDATA. */ 1321231200Smm cfdata = &(cab->entry_cffolder->cfdata); 1322231200Smm cab->entry_cfdata = cfdata; 1323231200Smm memset(cfdata, 0, sizeof(*cfdata)); 1324231200Smm } 1325231200Smm return (ARCHIVE_OK); 1326231200Smminvalid: 1327231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1328231200Smm "Invalid CFDATA"); 1329231200Smm return (ARCHIVE_FATAL); 1330231200Smm} 1331231200Smm 1332231200Smm/* 1333231200Smm * Read ahead CFDATA. 1334231200Smm */ 1335231200Smmstatic const void * 1336231200Smmcab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail) 1337231200Smm{ 1338231200Smm struct cab *cab = (struct cab *)(a->format->data); 1339231200Smm int err; 1340231200Smm 1341231200Smm err = cab_next_cfdata(a); 1342231200Smm if (err < ARCHIVE_OK) { 1343231200Smm *avail = err; 1344231200Smm return (NULL); 1345231200Smm } 1346231200Smm 1347231200Smm switch (cab->entry_cffolder->comptype) { 1348231200Smm case COMPTYPE_NONE: 1349231200Smm return (cab_read_ahead_cfdata_none(a, avail)); 1350231200Smm case COMPTYPE_MSZIP: 1351231200Smm return (cab_read_ahead_cfdata_deflate(a, avail)); 1352231200Smm case COMPTYPE_LZX: 1353231200Smm return (cab_read_ahead_cfdata_lzx(a, avail)); 1354231200Smm default: /* Unsupported compression. */ 1355231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1356231200Smm "Unsupported CAB compression : %s", 1357231200Smm cab->entry_cffolder->compname); 1358231200Smm *avail = ARCHIVE_FAILED; 1359231200Smm return (NULL); 1360231200Smm } 1361231200Smm} 1362231200Smm 1363231200Smm/* 1364231200Smm * Read ahead CFDATA as uncompressed data. 1365231200Smm */ 1366231200Smmstatic const void * 1367231200Smmcab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail) 1368231200Smm{ 1369231200Smm struct cab *cab = (struct cab *)(a->format->data); 1370231200Smm struct cfdata *cfdata; 1371231200Smm const void *d; 1372231200Smm 1373231200Smm cfdata = cab->entry_cfdata; 1374231200Smm 1375238856Smm /* 1376238856Smm * Note: '1' here is a performance optimization. 1377238856Smm * Recall that the decompression layer returns a count of 1378238856Smm * available bytes; asking for more than that forces the 1379238856Smm * decompressor to combine reads by copying data. 1380238856Smm */ 1381238856Smm d = __archive_read_ahead(a, 1, avail); 1382238856Smm if (*avail <= 0) { 1383238856Smm *avail = truncated_error(a); 1384238856Smm return (NULL); 1385238856Smm } 1386238856Smm if (*avail > cfdata->uncompressed_bytes_remaining) 1387238856Smm *avail = cfdata->uncompressed_bytes_remaining; 1388238856Smm cfdata->uncompressed_avail = cfdata->uncompressed_size; 1389238856Smm cfdata->unconsumed = *avail; 1390238856Smm cfdata->sum_ptr = d; 1391231200Smm return (d); 1392231200Smm} 1393231200Smm 1394231200Smm/* 1395231200Smm * Read ahead CFDATA as deflate data. 1396231200Smm */ 1397231200Smm#ifdef HAVE_ZLIB_H 1398231200Smmstatic const void * 1399231200Smmcab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) 1400231200Smm{ 1401231200Smm struct cab *cab = (struct cab *)(a->format->data); 1402231200Smm struct cfdata *cfdata; 1403231200Smm const void *d; 1404231200Smm int r, mszip; 1405231200Smm uint16_t uavail; 1406231200Smm char eod = 0; 1407231200Smm 1408231200Smm cfdata = cab->entry_cfdata; 1409231200Smm /* If the buffer hasn't been allocated, allocate it now. */ 1410231200Smm if (cab->uncompressed_buffer == NULL) { 1411231200Smm cab->uncompressed_buffer_size = 0x8000; 1412231200Smm cab->uncompressed_buffer 1413231200Smm = (unsigned char *)malloc(cab->uncompressed_buffer_size); 1414231200Smm if (cab->uncompressed_buffer == NULL) { 1415231200Smm archive_set_error(&a->archive, ENOMEM, 1416231200Smm "No memory for CAB reader"); 1417231200Smm *avail = ARCHIVE_FATAL; 1418231200Smm return (NULL); 1419231200Smm } 1420231200Smm } 1421231200Smm 1422231200Smm uavail = cfdata->uncompressed_avail; 1423231200Smm if (uavail == cfdata->uncompressed_size) { 1424231200Smm d = cab->uncompressed_buffer + cfdata->read_offset; 1425231200Smm *avail = uavail - cfdata->read_offset; 1426231200Smm return (d); 1427231200Smm } 1428231200Smm 1429231200Smm if (!cab->entry_cffolder->decompress_init) { 1430231200Smm cab->stream.next_in = NULL; 1431231200Smm cab->stream.avail_in = 0; 1432231200Smm cab->stream.total_in = 0; 1433231200Smm cab->stream.next_out = NULL; 1434231200Smm cab->stream.avail_out = 0; 1435231200Smm cab->stream.total_out = 0; 1436231200Smm if (cab->stream_valid) 1437231200Smm r = inflateReset(&cab->stream); 1438231200Smm else 1439231200Smm r = inflateInit2(&cab->stream, 1440231200Smm -15 /* Don't check for zlib header */); 1441231200Smm if (r != Z_OK) { 1442231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1443231200Smm "Can't initialize deflate decompression."); 1444231200Smm *avail = ARCHIVE_FATAL; 1445231200Smm return (NULL); 1446231200Smm } 1447231200Smm /* Stream structure has been set up. */ 1448231200Smm cab->stream_valid = 1; 1449231200Smm /* We've initialized decompression for this stream. */ 1450231200Smm cab->entry_cffolder->decompress_init = 1; 1451231200Smm } 1452231200Smm 1453231200Smm if (cfdata->compressed_bytes_remaining == cfdata->compressed_size) 1454231200Smm mszip = 2; 1455231200Smm else 1456231200Smm mszip = 0; 1457231200Smm eod = 0; 1458231200Smm cab->stream.total_out = uavail; 1459231200Smm /* 1460231200Smm * We always uncompress all data in current CFDATA. 1461231200Smm */ 1462231200Smm while (!eod && cab->stream.total_out < cfdata->uncompressed_size) { 1463231200Smm ssize_t bytes_avail; 1464231200Smm 1465231200Smm cab->stream.next_out = 1466231200Smm cab->uncompressed_buffer + cab->stream.total_out; 1467231200Smm cab->stream.avail_out = 1468231200Smm cfdata->uncompressed_size - cab->stream.total_out; 1469231200Smm 1470231200Smm d = __archive_read_ahead(a, 1, &bytes_avail); 1471231200Smm if (bytes_avail <= 0) { 1472231200Smm *avail = truncated_error(a); 1473231200Smm return (NULL); 1474231200Smm } 1475231200Smm if (bytes_avail > cfdata->compressed_bytes_remaining) 1476231200Smm bytes_avail = cfdata->compressed_bytes_remaining; 1477231200Smm /* 1478231200Smm * A bug in zlib.h: stream.next_in should be marked 'const' 1479231200Smm * but isn't (the library never alters data through the 1480231200Smm * next_in pointer, only reads it). The result: this ugly 1481231200Smm * cast to remove 'const'. 1482231200Smm */ 1483231200Smm cab->stream.next_in = (Bytef *)(uintptr_t)d; 1484248616Smm cab->stream.avail_in = (uInt)bytes_avail; 1485231200Smm cab->stream.total_in = 0; 1486231200Smm 1487231200Smm /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ 1488231200Smm if (mszip > 0) { 1489313571Smm if (bytes_avail <= 0) 1490313571Smm goto nomszip; 1491231200Smm if (bytes_avail <= mszip) { 1492231200Smm if (mszip == 2) { 1493231200Smm if (cab->stream.next_in[0] != 0x43) 1494231200Smm goto nomszip; 1495231200Smm if (bytes_avail > 1 && 1496231200Smm cab->stream.next_in[1] != 0x4b) 1497231200Smm goto nomszip; 1498231200Smm } else if (cab->stream.next_in[0] != 0x4b) 1499231200Smm goto nomszip; 1500231200Smm cfdata->unconsumed = bytes_avail; 1501231200Smm cfdata->sum_ptr = d; 1502231200Smm if (cab_minimum_consume_cfdata( 1503231200Smm a, cfdata->unconsumed) < 0) { 1504231200Smm *avail = ARCHIVE_FATAL; 1505231200Smm return (NULL); 1506231200Smm } 1507248616Smm mszip -= (int)bytes_avail; 1508231200Smm continue; 1509231200Smm } 1510231200Smm if (mszip == 1 && cab->stream.next_in[0] != 0x4b) 1511231200Smm goto nomszip; 1512348608Smm else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 || 1513348608Smm cab->stream.next_in[1] != 0x4b)) 1514231200Smm goto nomszip; 1515231200Smm cab->stream.next_in += mszip; 1516231200Smm cab->stream.avail_in -= mszip; 1517231200Smm cab->stream.total_in += mszip; 1518231200Smm mszip = 0; 1519231200Smm } 1520231200Smm 1521231200Smm r = inflate(&cab->stream, 0); 1522231200Smm switch (r) { 1523231200Smm case Z_OK: 1524231200Smm break; 1525231200Smm case Z_STREAM_END: 1526231200Smm eod = 1; 1527231200Smm break; 1528231200Smm default: 1529231200Smm goto zlibfailed; 1530231200Smm } 1531231200Smm cfdata->unconsumed = cab->stream.total_in; 1532231200Smm cfdata->sum_ptr = d; 1533231200Smm if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { 1534231200Smm *avail = ARCHIVE_FATAL; 1535231200Smm return (NULL); 1536231200Smm } 1537231200Smm } 1538238856Smm uavail = (uint16_t)cab->stream.total_out; 1539231200Smm 1540231200Smm if (uavail < cfdata->uncompressed_size) { 1541231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1542231200Smm "Invalid uncompressed size (%d < %d)", 1543231200Smm uavail, cfdata->uncompressed_size); 1544231200Smm *avail = ARCHIVE_FATAL; 1545231200Smm return (NULL); 1546231200Smm } 1547231200Smm 1548231200Smm /* 1549231200Smm * Note: I suspect there is a bug in makecab.exe because, in rare 1550231200Smm * case, compressed bytes are still remaining regardless we have 1551311042Smm * gotten all uncompressed bytes, which size is recorded in CFDATA, 1552231200Smm * as much as we need, and we have to use the garbage so as to 1553231200Smm * correctly compute the sum of CFDATA accordingly. 1554231200Smm */ 1555231200Smm if (cfdata->compressed_bytes_remaining > 0) { 1556231200Smm ssize_t bytes_avail; 1557231200Smm 1558231200Smm d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, 1559231200Smm &bytes_avail); 1560231200Smm if (bytes_avail <= 0) { 1561231200Smm *avail = truncated_error(a); 1562231200Smm return (NULL); 1563231200Smm } 1564231200Smm cfdata->unconsumed = cfdata->compressed_bytes_remaining; 1565231200Smm cfdata->sum_ptr = d; 1566231200Smm if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { 1567231200Smm *avail = ARCHIVE_FATAL; 1568231200Smm return (NULL); 1569231200Smm } 1570231200Smm } 1571231200Smm 1572231200Smm /* 1573231200Smm * Set dictionary data for decompressing of next CFDATA, which 1574231200Smm * in the same folder. This is why we always do decompress CFDATA 1575231200Smm * even if beginning CFDATA or some of CFDATA are not used in 1576231200Smm * skipping file data. 1577231200Smm */ 1578231200Smm if (cab->entry_cffolder->cfdata_index < 1579231200Smm cab->entry_cffolder->cfdata_count) { 1580231200Smm r = inflateReset(&cab->stream); 1581231200Smm if (r != Z_OK) 1582231200Smm goto zlibfailed; 1583231200Smm r = inflateSetDictionary(&cab->stream, 1584231200Smm cab->uncompressed_buffer, cfdata->uncompressed_size); 1585231200Smm if (r != Z_OK) 1586231200Smm goto zlibfailed; 1587231200Smm } 1588231200Smm 1589231200Smm d = cab->uncompressed_buffer + cfdata->read_offset; 1590231200Smm *avail = uavail - cfdata->read_offset; 1591231200Smm cfdata->uncompressed_avail = uavail; 1592231200Smm 1593231200Smm return (d); 1594231200Smm 1595231200Smmzlibfailed: 1596231200Smm switch (r) { 1597231200Smm case Z_MEM_ERROR: 1598231200Smm archive_set_error(&a->archive, ENOMEM, 1599231200Smm "Out of memory for deflate decompression"); 1600231200Smm break; 1601231200Smm default: 1602231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1603231200Smm "Deflate decompression failed (%d)", r); 1604231200Smm break; 1605231200Smm } 1606231200Smm *avail = ARCHIVE_FATAL; 1607231200Smm return (NULL); 1608231200Smmnomszip: 1609231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1610231200Smm "CFDATA incorrect(no MSZIP signature)"); 1611231200Smm *avail = ARCHIVE_FATAL; 1612231200Smm return (NULL); 1613231200Smm} 1614231200Smm 1615231200Smm#else /* HAVE_ZLIB_H */ 1616231200Smm 1617231200Smmstatic const void * 1618231200Smmcab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) 1619231200Smm{ 1620231200Smm *avail = ARCHIVE_FATAL; 1621231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1622231200Smm "libarchive compiled without deflate support (no libz)"); 1623231200Smm return (NULL); 1624231200Smm} 1625231200Smm 1626231200Smm#endif /* HAVE_ZLIB_H */ 1627231200Smm 1628231200Smmstatic const void * 1629231200Smmcab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) 1630231200Smm{ 1631231200Smm struct cab *cab = (struct cab *)(a->format->data); 1632231200Smm struct cfdata *cfdata; 1633231200Smm const void *d; 1634231200Smm int r; 1635231200Smm uint16_t uavail; 1636231200Smm 1637231200Smm cfdata = cab->entry_cfdata; 1638231200Smm /* If the buffer hasn't been allocated, allocate it now. */ 1639231200Smm if (cab->uncompressed_buffer == NULL) { 1640231200Smm cab->uncompressed_buffer_size = 0x8000; 1641231200Smm cab->uncompressed_buffer 1642231200Smm = (unsigned char *)malloc(cab->uncompressed_buffer_size); 1643231200Smm if (cab->uncompressed_buffer == NULL) { 1644231200Smm archive_set_error(&a->archive, ENOMEM, 1645231200Smm "No memory for CAB reader"); 1646231200Smm *avail = ARCHIVE_FATAL; 1647231200Smm return (NULL); 1648231200Smm } 1649231200Smm } 1650231200Smm 1651231200Smm uavail = cfdata->uncompressed_avail; 1652231200Smm if (uavail == cfdata->uncompressed_size) { 1653231200Smm d = cab->uncompressed_buffer + cfdata->read_offset; 1654231200Smm *avail = uavail - cfdata->read_offset; 1655231200Smm return (d); 1656231200Smm } 1657231200Smm 1658231200Smm if (!cab->entry_cffolder->decompress_init) { 1659231200Smm r = lzx_decode_init(&cab->xstrm, 1660231200Smm cab->entry_cffolder->compdata); 1661231200Smm if (r != ARCHIVE_OK) { 1662231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1663231200Smm "Can't initialize LZX decompression."); 1664231200Smm *avail = ARCHIVE_FATAL; 1665231200Smm return (NULL); 1666231200Smm } 1667231200Smm /* We've initialized decompression for this stream. */ 1668231200Smm cab->entry_cffolder->decompress_init = 1; 1669231200Smm } 1670231200Smm 1671231200Smm /* Clean up remaining bits of previous CFDATA. */ 1672231200Smm lzx_cleanup_bitstream(&cab->xstrm); 1673231200Smm cab->xstrm.total_out = uavail; 1674231200Smm while (cab->xstrm.total_out < cfdata->uncompressed_size) { 1675231200Smm ssize_t bytes_avail; 1676231200Smm 1677231200Smm cab->xstrm.next_out = 1678231200Smm cab->uncompressed_buffer + cab->xstrm.total_out; 1679231200Smm cab->xstrm.avail_out = 1680231200Smm cfdata->uncompressed_size - cab->xstrm.total_out; 1681231200Smm 1682231200Smm d = __archive_read_ahead(a, 1, &bytes_avail); 1683231200Smm if (bytes_avail <= 0) { 1684231200Smm archive_set_error(&a->archive, 1685231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 1686231200Smm "Truncated CAB file data"); 1687231200Smm *avail = ARCHIVE_FATAL; 1688231200Smm return (NULL); 1689231200Smm } 1690231200Smm if (bytes_avail > cfdata->compressed_bytes_remaining) 1691231200Smm bytes_avail = cfdata->compressed_bytes_remaining; 1692231200Smm 1693231200Smm cab->xstrm.next_in = d; 1694231200Smm cab->xstrm.avail_in = bytes_avail; 1695231200Smm cab->xstrm.total_in = 0; 1696231200Smm r = lzx_decode(&cab->xstrm, 1697231200Smm cfdata->compressed_bytes_remaining == bytes_avail); 1698231200Smm switch (r) { 1699231200Smm case ARCHIVE_OK: 1700231200Smm case ARCHIVE_EOF: 1701231200Smm break; 1702231200Smm default: 1703231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1704231200Smm "LZX decompression failed (%d)", r); 1705231200Smm *avail = ARCHIVE_FATAL; 1706231200Smm return (NULL); 1707231200Smm } 1708231200Smm cfdata->unconsumed = cab->xstrm.total_in; 1709231200Smm cfdata->sum_ptr = d; 1710231200Smm if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { 1711231200Smm *avail = ARCHIVE_FATAL; 1712231200Smm return (NULL); 1713231200Smm } 1714231200Smm } 1715231200Smm 1716238856Smm uavail = (uint16_t)cab->xstrm.total_out; 1717231200Smm /* 1718231200Smm * Make sure a read pointer advances to next CFDATA. 1719231200Smm */ 1720231200Smm if (cfdata->compressed_bytes_remaining > 0) { 1721231200Smm ssize_t bytes_avail; 1722231200Smm 1723231200Smm d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, 1724231200Smm &bytes_avail); 1725231200Smm if (bytes_avail <= 0) { 1726231200Smm *avail = truncated_error(a); 1727231200Smm return (NULL); 1728231200Smm } 1729231200Smm cfdata->unconsumed = cfdata->compressed_bytes_remaining; 1730231200Smm cfdata->sum_ptr = d; 1731231200Smm if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { 1732231200Smm *avail = ARCHIVE_FATAL; 1733231200Smm return (NULL); 1734231200Smm } 1735231200Smm } 1736231200Smm 1737231200Smm /* 1738311042Smm * Translation reversal of x86 processor CALL byte sequence(E8). 1739231200Smm */ 1740231200Smm lzx_translation(&cab->xstrm, cab->uncompressed_buffer, 1741231200Smm cfdata->uncompressed_size, 1742231200Smm (cab->entry_cffolder->cfdata_index-1) * 0x8000); 1743231200Smm 1744231200Smm d = cab->uncompressed_buffer + cfdata->read_offset; 1745231200Smm *avail = uavail - cfdata->read_offset; 1746231200Smm cfdata->uncompressed_avail = uavail; 1747231200Smm 1748231200Smm return (d); 1749231200Smm} 1750231200Smm 1751231200Smm/* 1752231200Smm * Consume CFDATA. 1753231200Smm * We always decompress CFDATA to consume CFDATA as much as we need 1754231200Smm * in uncompressed bytes because all CFDATA in a folder are related 1755231200Smm * so we do not skip any CFDATA without decompressing. 1756231200Smm * Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or 1757231200Smm * iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for 1758231200Smm * the CFFILE is remaining bytes of previous Multivolume CAB file. 1759231200Smm */ 1760231200Smmstatic int64_t 1761231200Smmcab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) 1762231200Smm{ 1763231200Smm struct cab *cab = (struct cab *)(a->format->data); 1764231200Smm struct cfdata *cfdata; 1765231200Smm int64_t cbytes, rbytes; 1766231200Smm int err; 1767231200Smm 1768231200Smm rbytes = cab_minimum_consume_cfdata(a, consumed_bytes); 1769231200Smm if (rbytes < 0) 1770231200Smm return (ARCHIVE_FATAL); 1771231200Smm 1772231200Smm cfdata = cab->entry_cfdata; 1773231200Smm while (rbytes > 0) { 1774231200Smm ssize_t avail; 1775231200Smm 1776231200Smm if (cfdata->compressed_size == 0) { 1777231200Smm archive_set_error(&a->archive, 1778231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 1779231200Smm "Invalid CFDATA"); 1780231200Smm return (ARCHIVE_FATAL); 1781231200Smm } 1782231200Smm cbytes = cfdata->uncompressed_bytes_remaining; 1783231200Smm if (cbytes > rbytes) 1784231200Smm cbytes = rbytes; 1785231200Smm rbytes -= cbytes; 1786231200Smm 1787231200Smm if (cfdata->uncompressed_avail == 0 && 1788238856Smm (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT || 1789238856Smm cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) { 1790231200Smm /* We have not read any data yet. */ 1791231200Smm if (cbytes == cfdata->uncompressed_bytes_remaining) { 1792231200Smm /* Skip whole current CFDATA. */ 1793231200Smm __archive_read_consume(a, 1794231200Smm cfdata->compressed_size); 1795231200Smm cab->cab_offset += cfdata->compressed_size; 1796231200Smm cfdata->compressed_bytes_remaining = 0; 1797231200Smm cfdata->uncompressed_bytes_remaining = 0; 1798231200Smm err = cab_next_cfdata(a); 1799231200Smm if (err < 0) 1800231200Smm return (err); 1801231200Smm cfdata = cab->entry_cfdata; 1802231200Smm if (cfdata->uncompressed_size == 0) { 1803231200Smm switch (cab->entry_cffile->folder) { 1804231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 1805231200Smm case iFoldCONTINUED_TO_NEXT: 1806231200Smm case iFoldCONTINUED_FROM_PREV: 1807231200Smm rbytes = 0; 1808231200Smm break; 1809231200Smm default: 1810231200Smm break; 1811231200Smm } 1812231200Smm } 1813231200Smm continue; 1814231200Smm } 1815238856Smm cfdata->read_offset += (uint16_t)cbytes; 1816238856Smm cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; 1817231200Smm break; 1818231200Smm } else if (cbytes == 0) { 1819231200Smm err = cab_next_cfdata(a); 1820231200Smm if (err < 0) 1821231200Smm return (err); 1822231200Smm cfdata = cab->entry_cfdata; 1823231200Smm if (cfdata->uncompressed_size == 0) { 1824231200Smm switch (cab->entry_cffile->folder) { 1825231200Smm case iFoldCONTINUED_PREV_AND_NEXT: 1826231200Smm case iFoldCONTINUED_TO_NEXT: 1827231200Smm case iFoldCONTINUED_FROM_PREV: 1828231200Smm return (ARCHIVE_FATAL); 1829231200Smm default: 1830231200Smm break; 1831231200Smm } 1832231200Smm } 1833231200Smm continue; 1834231200Smm } 1835231200Smm while (cbytes > 0) { 1836231200Smm (void)cab_read_ahead_cfdata(a, &avail); 1837231200Smm if (avail <= 0) 1838231200Smm return (ARCHIVE_FATAL); 1839231200Smm if (avail > cbytes) 1840238856Smm avail = (ssize_t)cbytes; 1841231200Smm if (cab_minimum_consume_cfdata(a, avail) < 0) 1842231200Smm return (ARCHIVE_FATAL); 1843231200Smm cbytes -= avail; 1844231200Smm } 1845231200Smm } 1846231200Smm return (consumed_bytes); 1847231200Smm} 1848231200Smm 1849231200Smm/* 1850231200Smm * Consume CFDATA as much as we have already gotten and 1851231200Smm * compute the sum of CFDATA. 1852231200Smm */ 1853231200Smmstatic int64_t 1854231200Smmcab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) 1855231200Smm{ 1856231200Smm struct cab *cab = (struct cab *)(a->format->data); 1857231200Smm struct cfdata *cfdata; 1858231200Smm int64_t cbytes, rbytes; 1859231200Smm int err; 1860231200Smm 1861231200Smm cfdata = cab->entry_cfdata; 1862231200Smm rbytes = consumed_bytes; 1863231200Smm if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { 1864231200Smm if (consumed_bytes < cfdata->unconsumed) 1865231200Smm cbytes = consumed_bytes; 1866231200Smm else 1867231200Smm cbytes = cfdata->unconsumed; 1868231200Smm rbytes -= cbytes; 1869238856Smm cfdata->read_offset += (uint16_t)cbytes; 1870238856Smm cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; 1871231200Smm cfdata->unconsumed -= cbytes; 1872231200Smm } else { 1873231200Smm cbytes = cfdata->uncompressed_avail - cfdata->read_offset; 1874231200Smm if (cbytes > 0) { 1875231200Smm if (consumed_bytes < cbytes) 1876231200Smm cbytes = consumed_bytes; 1877231200Smm rbytes -= cbytes; 1878238856Smm cfdata->read_offset += (uint16_t)cbytes; 1879238856Smm cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; 1880231200Smm } 1881231200Smm 1882231200Smm if (cfdata->unconsumed) { 1883231200Smm cbytes = cfdata->unconsumed; 1884231200Smm cfdata->unconsumed = 0; 1885231200Smm } else 1886231200Smm cbytes = 0; 1887231200Smm } 1888231200Smm if (cbytes) { 1889231200Smm /* Compute the sum. */ 1890238856Smm cab_checksum_update(a, (size_t)cbytes); 1891231200Smm 1892231200Smm /* Consume as much as the compressor actually used. */ 1893231200Smm __archive_read_consume(a, cbytes); 1894231200Smm cab->cab_offset += cbytes; 1895238856Smm cfdata->compressed_bytes_remaining -= (uint16_t)cbytes; 1896231200Smm if (cfdata->compressed_bytes_remaining == 0) { 1897231200Smm err = cab_checksum_finish(a); 1898231200Smm if (err < 0) 1899231200Smm return (err); 1900231200Smm } 1901231200Smm } 1902231200Smm return (rbytes); 1903231200Smm} 1904231200Smm 1905231200Smm/* 1906231200Smm * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets 1907231200Smm * cab->end_of_entry if it consumes all of the data. 1908231200Smm */ 1909231200Smmstatic int 1910231200Smmcab_read_data(struct archive_read *a, const void **buff, 1911231200Smm size_t *size, int64_t *offset) 1912231200Smm{ 1913231200Smm struct cab *cab = (struct cab *)(a->format->data); 1914231200Smm ssize_t bytes_avail; 1915231200Smm 1916231200Smm if (cab->entry_bytes_remaining == 0) { 1917231200Smm *buff = NULL; 1918231200Smm *size = 0; 1919231200Smm *offset = cab->entry_offset; 1920231200Smm cab->end_of_entry = 1; 1921231200Smm return (ARCHIVE_OK); 1922231200Smm } 1923231200Smm 1924231200Smm *buff = cab_read_ahead_cfdata(a, &bytes_avail); 1925231200Smm if (bytes_avail <= 0) { 1926231200Smm *buff = NULL; 1927231200Smm *size = 0; 1928231200Smm *offset = 0; 1929231200Smm if (bytes_avail == 0 && 1930231200Smm cab->entry_cfdata->uncompressed_size == 0) { 1931231200Smm /* All of CFDATA in a folder has been handled. */ 1932231200Smm archive_set_error(&a->archive, 1933231200Smm ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); 1934231200Smm return (ARCHIVE_FATAL); 1935231200Smm } else 1936248616Smm return ((int)bytes_avail); 1937231200Smm } 1938231200Smm if (bytes_avail > cab->entry_bytes_remaining) 1939238856Smm bytes_avail = (ssize_t)cab->entry_bytes_remaining; 1940231200Smm 1941231200Smm *size = bytes_avail; 1942231200Smm *offset = cab->entry_offset; 1943231200Smm cab->entry_offset += bytes_avail; 1944231200Smm cab->entry_bytes_remaining -= bytes_avail; 1945231200Smm if (cab->entry_bytes_remaining == 0) 1946231200Smm cab->end_of_entry = 1; 1947231200Smm cab->entry_unconsumed = bytes_avail; 1948238856Smm if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { 1949238856Smm /* Don't consume more than current entry used. */ 1950238856Smm if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed) 1951238856Smm cab->entry_cfdata->unconsumed = cab->entry_unconsumed; 1952238856Smm } 1953231200Smm return (ARCHIVE_OK); 1954231200Smm} 1955231200Smm 1956231200Smmstatic int 1957231200Smmarchive_read_format_cab_read_data_skip(struct archive_read *a) 1958231200Smm{ 1959231200Smm struct cab *cab; 1960231200Smm int64_t bytes_skipped; 1961231200Smm int r; 1962231200Smm 1963231200Smm cab = (struct cab *)(a->format->data); 1964231200Smm 1965231200Smm if (cab->end_of_archive) 1966231200Smm return (ARCHIVE_EOF); 1967231200Smm 1968238856Smm if (!cab->read_data_invoked) { 1969238856Smm cab->bytes_skipped += cab->entry_bytes_remaining; 1970238856Smm cab->entry_bytes_remaining = 0; 1971238856Smm /* This entry is finished and done. */ 1972238856Smm cab->end_of_entry_cleanup = cab->end_of_entry = 1; 1973238856Smm return (ARCHIVE_OK); 1974238856Smm } 1975238856Smm 1976231200Smm if (cab->entry_unconsumed) { 1977231200Smm /* Consume as much as the compressor actually used. */ 1978238856Smm r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); 1979231200Smm cab->entry_unconsumed = 0; 1980231200Smm if (r < 0) 1981231200Smm return (r); 1982231200Smm } else if (cab->entry_cfdata == NULL) { 1983231200Smm r = cab_next_cfdata(a); 1984231200Smm if (r < 0) 1985231200Smm return (r); 1986231200Smm } 1987231200Smm 1988231200Smm /* if we've already read to end of data, we're done. */ 1989231200Smm if (cab->end_of_entry_cleanup) 1990231200Smm return (ARCHIVE_OK); 1991231200Smm 1992231200Smm /* 1993231200Smm * If the length is at the beginning, we can skip the 1994231200Smm * compressed data much more quickly. 1995231200Smm */ 1996231200Smm bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining); 1997231200Smm if (bytes_skipped < 0) 1998231200Smm return (ARCHIVE_FATAL); 1999231200Smm 2000238856Smm /* If the compression type is none(uncompressed), we've already 2001238856Smm * consumed data as much as the current entry size. */ 2002248616Smm if (cab->entry_cffolder->comptype == COMPTYPE_NONE && 2003248616Smm cab->entry_cfdata != NULL) 2004238856Smm cab->entry_cfdata->unconsumed = 0; 2005238856Smm 2006231200Smm /* This entry is finished and done. */ 2007231200Smm cab->end_of_entry_cleanup = cab->end_of_entry = 1; 2008231200Smm return (ARCHIVE_OK); 2009231200Smm} 2010231200Smm 2011231200Smmstatic int 2012231200Smmarchive_read_format_cab_cleanup(struct archive_read *a) 2013231200Smm{ 2014231200Smm struct cab *cab = (struct cab *)(a->format->data); 2015231200Smm struct cfheader *hd = &cab->cfheader; 2016231200Smm int i; 2017231200Smm 2018231200Smm if (hd->folder_array != NULL) { 2019231200Smm for (i = 0; i < hd->folder_count; i++) 2020231200Smm free(hd->folder_array[i].cfdata.memimage); 2021231200Smm free(hd->folder_array); 2022231200Smm } 2023231200Smm if (hd->file_array != NULL) { 2024231200Smm for (i = 0; i < cab->cfheader.file_count; i++) 2025231200Smm archive_string_free(&(hd->file_array[i].pathname)); 2026231200Smm free(hd->file_array); 2027231200Smm } 2028231200Smm#ifdef HAVE_ZLIB_H 2029231200Smm if (cab->stream_valid) 2030231200Smm inflateEnd(&cab->stream); 2031231200Smm#endif 2032231200Smm lzx_decode_free(&cab->xstrm); 2033231200Smm archive_wstring_free(&cab->ws); 2034231200Smm free(cab->uncompressed_buffer); 2035231200Smm free(cab); 2036231200Smm (a->format->data) = NULL; 2037231200Smm return (ARCHIVE_OK); 2038231200Smm} 2039231200Smm 2040231200Smm/* Convert an MSDOS-style date/time into Unix-style time. */ 2041231200Smmstatic time_t 2042231200Smmcab_dos_time(const unsigned char *p) 2043231200Smm{ 2044231200Smm int msTime, msDate; 2045231200Smm struct tm ts; 2046231200Smm 2047231200Smm msDate = archive_le16dec(p); 2048231200Smm msTime = archive_le16dec(p+2); 2049231200Smm 2050231200Smm memset(&ts, 0, sizeof(ts)); 2051231200Smm ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ 2052231200Smm ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ 2053231200Smm ts.tm_mday = msDate & 0x1f; /* Day of month. */ 2054231200Smm ts.tm_hour = (msTime >> 11) & 0x1f; 2055231200Smm ts.tm_min = (msTime >> 5) & 0x3f; 2056231200Smm ts.tm_sec = (msTime << 1) & 0x3e; 2057231200Smm ts.tm_isdst = -1; 2058231200Smm return (mktime(&ts)); 2059231200Smm} 2060231200Smm 2061231200Smm/***************************************************************** 2062231200Smm * 2063231200Smm * LZX decompression code. 2064231200Smm * 2065231200Smm *****************************************************************/ 2066231200Smm 2067231200Smm/* 2068231200Smm * Initialize LZX decoder. 2069231200Smm * 2070231200Smm * Returns ARCHIVE_OK if initialization was successful. 2071231200Smm * Returns ARCHIVE_FAILED if w_bits has unsupported value. 2072231200Smm * Returns ARCHIVE_FATAL if initialization failed; memory allocation 2073231200Smm * error occurred. 2074231200Smm */ 2075231200Smmstatic int 2076231200Smmlzx_decode_init(struct lzx_stream *strm, int w_bits) 2077231200Smm{ 2078231200Smm struct lzx_dec *ds; 2079231200Smm int slot, w_size, w_slot; 2080231200Smm int base, footer; 2081232153Smm int base_inc[18]; 2082231200Smm 2083231200Smm if (strm->ds == NULL) { 2084231200Smm strm->ds = calloc(1, sizeof(*strm->ds)); 2085231200Smm if (strm->ds == NULL) 2086231200Smm return (ARCHIVE_FATAL); 2087231200Smm } 2088231200Smm ds = strm->ds; 2089231200Smm ds->error = ARCHIVE_FAILED; 2090231200Smm 2091231200Smm /* Allow bits from 15(32KBi) up to 21(2MBi) */ 2092231200Smm if (w_bits < SLOT_BASE || w_bits > SLOT_MAX) 2093231200Smm return (ARCHIVE_FAILED); 2094231200Smm 2095231200Smm ds->error = ARCHIVE_FATAL; 2096231200Smm 2097231200Smm /* 2098231200Smm * Alloc window 2099231200Smm */ 2100231200Smm w_size = ds->w_size; 2101231200Smm w_slot = slots[w_bits - SLOT_BASE]; 2102231200Smm ds->w_size = 1U << w_bits; 2103231200Smm ds->w_mask = ds->w_size -1; 2104231200Smm if (ds->w_buff == NULL || w_size != ds->w_size) { 2105231200Smm free(ds->w_buff); 2106231200Smm ds->w_buff = malloc(ds->w_size); 2107231200Smm if (ds->w_buff == NULL) 2108231200Smm return (ARCHIVE_FATAL); 2109231200Smm free(ds->pos_tbl); 2110231200Smm ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot); 2111231200Smm if (ds->pos_tbl == NULL) 2112231200Smm return (ARCHIVE_FATAL); 2113231200Smm lzx_huffman_free(&(ds->mt)); 2114231200Smm } 2115231200Smm 2116232153Smm for (footer = 0; footer < 18; footer++) 2117232153Smm base_inc[footer] = 1 << footer; 2118231200Smm base = footer = 0; 2119231200Smm for (slot = 0; slot < w_slot; slot++) { 2120231200Smm int n; 2121231200Smm if (footer == 0) 2122231200Smm base = slot; 2123231200Smm else 2124232153Smm base += base_inc[footer]; 2125231200Smm if (footer < 17) { 2126231200Smm footer = -2; 2127231200Smm for (n = base; n; n >>= 1) 2128231200Smm footer++; 2129231200Smm if (footer <= 0) 2130231200Smm footer = 0; 2131231200Smm } 2132231200Smm ds->pos_tbl[slot].base = base; 2133231200Smm ds->pos_tbl[slot].footer_bits = footer; 2134231200Smm } 2135231200Smm 2136231200Smm ds->w_pos = 0; 2137231200Smm ds->state = 0; 2138231200Smm ds->br.cache_buffer = 0; 2139231200Smm ds->br.cache_avail = 0; 2140231200Smm ds->r0 = ds->r1 = ds->r2 = 1; 2141231200Smm 2142231200Smm /* Initialize aligned offset tree. */ 2143231200Smm if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK) 2144231200Smm return (ARCHIVE_FATAL); 2145231200Smm 2146231200Smm /* Initialize pre-tree. */ 2147231200Smm if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK) 2148231200Smm return (ARCHIVE_FATAL); 2149231200Smm 2150231200Smm /* Initialize Main tree. */ 2151231200Smm if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16) 2152231200Smm != ARCHIVE_OK) 2153231200Smm return (ARCHIVE_FATAL); 2154231200Smm 2155231200Smm /* Initialize Length tree. */ 2156231200Smm if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK) 2157231200Smm return (ARCHIVE_FATAL); 2158231200Smm 2159231200Smm ds->error = 0; 2160231200Smm 2161231200Smm return (ARCHIVE_OK); 2162231200Smm} 2163231200Smm 2164231200Smm/* 2165231200Smm * Release LZX decoder. 2166231200Smm */ 2167231200Smmstatic void 2168231200Smmlzx_decode_free(struct lzx_stream *strm) 2169231200Smm{ 2170231200Smm 2171231200Smm if (strm->ds == NULL) 2172231200Smm return; 2173231200Smm free(strm->ds->w_buff); 2174231200Smm free(strm->ds->pos_tbl); 2175231200Smm lzx_huffman_free(&(strm->ds->at)); 2176231200Smm lzx_huffman_free(&(strm->ds->pt)); 2177231200Smm lzx_huffman_free(&(strm->ds->mt)); 2178231200Smm lzx_huffman_free(&(strm->ds->lt)); 2179231200Smm free(strm->ds); 2180231200Smm strm->ds = NULL; 2181231200Smm} 2182231200Smm 2183231200Smm/* 2184231200Smm * E8 Call Translation reversal. 2185231200Smm */ 2186231200Smmstatic void 2187231200Smmlzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) 2188231200Smm{ 2189231200Smm struct lzx_dec *ds = strm->ds; 2190231200Smm unsigned char *b, *end; 2191231200Smm 2192231200Smm if (!ds->translation || size <= 10) 2193231200Smm return; 2194231200Smm b = p; 2195231200Smm end = b + size - 10; 2196231200Smm while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) { 2197231200Smm size_t i = b - (unsigned char *)p; 2198232153Smm int32_t cp, displacement, value; 2199231200Smm 2200248616Smm cp = (int32_t)(offset + (uint32_t)i); 2201231200Smm value = archive_le32dec(&b[1]); 2202232153Smm if (value >= -cp && value < (int32_t)ds->translation_size) { 2203231200Smm if (value >= 0) 2204231200Smm displacement = value - cp; 2205231200Smm else 2206231200Smm displacement = value + ds->translation_size; 2207231200Smm archive_le32enc(&b[1], (uint32_t)displacement); 2208231200Smm } 2209231200Smm b += 5; 2210231200Smm } 2211231200Smm} 2212231200Smm 2213231200Smm/* 2214231200Smm * Bit stream reader. 2215231200Smm */ 2216231200Smm/* Check that the cache buffer has enough bits. */ 2217231200Smm#define lzx_br_has(br, n) ((br)->cache_avail >= n) 2218231200Smm/* Get compressed data by bit. */ 2219231200Smm#define lzx_br_bits(br, n) \ 2220231200Smm (((uint32_t)((br)->cache_buffer >> \ 2221231200Smm ((br)->cache_avail - (n)))) & cache_masks[n]) 2222231200Smm#define lzx_br_bits_forced(br, n) \ 2223231200Smm (((uint32_t)((br)->cache_buffer << \ 2224231200Smm ((n) - (br)->cache_avail))) & cache_masks[n]) 2225231200Smm/* Read ahead to make sure the cache buffer has enough compressed data we 2226231200Smm * will use. 2227231200Smm * True : completed, there is enough data in the cache buffer. 2228231200Smm * False : we met that strm->next_in is empty, we have to get following 2229231200Smm * bytes. */ 2230231200Smm#define lzx_br_read_ahead_0(strm, br, n) \ 2231231200Smm (lzx_br_has((br), (n)) || lzx_br_fillup(strm, br)) 2232231200Smm/* True : the cache buffer has some bits as much as we need. 2233231200Smm * False : there are no enough bits in the cache buffer to be used, 2234231200Smm * we have to get following bytes if we could. */ 2235231200Smm#define lzx_br_read_ahead(strm, br, n) \ 2236231200Smm (lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n))) 2237231200Smm 2238231200Smm/* Notify how many bits we consumed. */ 2239231200Smm#define lzx_br_consume(br, n) ((br)->cache_avail -= (n)) 2240238856Smm#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f) 2241231200Smm 2242238856Smm#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f) 2243238856Smm 2244231200Smmstatic const uint32_t cache_masks[] = { 2245231200Smm 0x00000000, 0x00000001, 0x00000003, 0x00000007, 2246231200Smm 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, 2247231200Smm 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 2248231200Smm 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 2249231200Smm 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 2250231200Smm 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 2251231200Smm 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 2252231200Smm 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 2253231200Smm 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF 2254231200Smm}; 2255231200Smm 2256231200Smm/* 2257231200Smm * Shift away used bits in the cache data and fill it up with following bits. 2258231200Smm * Call this when cache buffer does not have enough bits you need. 2259231200Smm * 2260231200Smm * Returns 1 if the cache buffer is full. 2261231200Smm * Returns 0 if the cache buffer is not full; input buffer is empty. 2262231200Smm */ 2263231200Smmstatic int 2264231200Smmlzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br) 2265231200Smm{ 2266231200Smm/* 2267311042Smm * x86 processor family can read misaligned data without an access error. 2268231200Smm */ 2269231200Smm int n = CACHE_BITS - br->cache_avail; 2270231200Smm 2271231200Smm for (;;) { 2272231200Smm switch (n >> 4) { 2273231200Smm case 4: 2274231200Smm if (strm->avail_in >= 8) { 2275231200Smm br->cache_buffer = 2276231200Smm ((uint64_t)strm->next_in[1]) << 56 | 2277231200Smm ((uint64_t)strm->next_in[0]) << 48 | 2278231200Smm ((uint64_t)strm->next_in[3]) << 40 | 2279231200Smm ((uint64_t)strm->next_in[2]) << 32 | 2280231200Smm ((uint32_t)strm->next_in[5]) << 24 | 2281231200Smm ((uint32_t)strm->next_in[4]) << 16 | 2282231200Smm ((uint32_t)strm->next_in[7]) << 8 | 2283231200Smm (uint32_t)strm->next_in[6]; 2284231200Smm strm->next_in += 8; 2285231200Smm strm->avail_in -= 8; 2286231200Smm br->cache_avail += 8 * 8; 2287231200Smm return (1); 2288231200Smm } 2289231200Smm break; 2290231200Smm case 3: 2291231200Smm if (strm->avail_in >= 6) { 2292231200Smm br->cache_buffer = 2293231200Smm (br->cache_buffer << 48) | 2294231200Smm ((uint64_t)strm->next_in[1]) << 40 | 2295231200Smm ((uint64_t)strm->next_in[0]) << 32 | 2296231200Smm ((uint32_t)strm->next_in[3]) << 24 | 2297231200Smm ((uint32_t)strm->next_in[2]) << 16 | 2298231200Smm ((uint32_t)strm->next_in[5]) << 8 | 2299231200Smm (uint32_t)strm->next_in[4]; 2300231200Smm strm->next_in += 6; 2301231200Smm strm->avail_in -= 6; 2302231200Smm br->cache_avail += 6 * 8; 2303231200Smm return (1); 2304231200Smm } 2305231200Smm break; 2306231200Smm case 0: 2307231200Smm /* We have enough compressed data in 2308231200Smm * the cache buffer.*/ 2309231200Smm return (1); 2310231200Smm default: 2311231200Smm break; 2312231200Smm } 2313231200Smm if (strm->avail_in < 2) { 2314231200Smm /* There is not enough compressed data to 2315231200Smm * fill up the cache buffer. */ 2316231200Smm if (strm->avail_in == 1) { 2317231200Smm br->odd = *strm->next_in++; 2318231200Smm strm->avail_in--; 2319231200Smm br->have_odd = 1; 2320231200Smm } 2321231200Smm return (0); 2322231200Smm } 2323231200Smm br->cache_buffer = 2324231200Smm (br->cache_buffer << 16) | 2325231200Smm archive_le16dec(strm->next_in); 2326231200Smm strm->next_in += 2; 2327231200Smm strm->avail_in -= 2; 2328231200Smm br->cache_avail += 16; 2329231200Smm n -= 16; 2330231200Smm } 2331231200Smm} 2332231200Smm 2333231200Smmstatic void 2334231200Smmlzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br) 2335231200Smm{ 2336231200Smm int n = CACHE_BITS - br->cache_avail; 2337231200Smm 2338231200Smm if (br->have_odd && n >= 16 && strm->avail_in > 0) { 2339231200Smm br->cache_buffer = 2340231200Smm (br->cache_buffer << 16) | 2341231200Smm ((uint16_t)(*strm->next_in)) << 8 | br->odd; 2342231200Smm strm->next_in++; 2343231200Smm strm->avail_in--; 2344231200Smm br->cache_avail += 16; 2345231200Smm br->have_odd = 0; 2346231200Smm } 2347231200Smm} 2348231200Smm 2349231200Smmstatic void 2350231200Smmlzx_cleanup_bitstream(struct lzx_stream *strm) 2351231200Smm{ 2352231200Smm strm->ds->br.cache_avail = 0; 2353231200Smm strm->ds->br.have_odd = 0; 2354231200Smm} 2355231200Smm 2356231200Smm/* 2357231200Smm * Decode LZX. 2358231200Smm * 2359231200Smm * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. 2360231200Smm * Please set available buffer and call this function again. 2361231200Smm * 2. Returns ARCHIVE_EOF if decompression has been completed. 2362231200Smm * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data 2363231200Smm * is broken or you do not set 'last' flag properly. 2364231200Smm */ 2365231200Smm#define ST_RD_TRANSLATION 0 2366231200Smm#define ST_RD_TRANSLATION_SIZE 1 2367231200Smm#define ST_RD_BLOCK_TYPE 2 2368231200Smm#define ST_RD_BLOCK_SIZE 3 2369238856Smm#define ST_RD_ALIGNMENT 4 2370238856Smm#define ST_RD_R0 5 2371238856Smm#define ST_RD_R1 6 2372238856Smm#define ST_RD_R2 7 2373238856Smm#define ST_COPY_UNCOMP1 8 2374238856Smm#define ST_COPY_UNCOMP2 9 2375238856Smm#define ST_RD_ALIGNED_OFFSET 10 2376238856Smm#define ST_RD_VERBATIM 11 2377238856Smm#define ST_RD_PRE_MAIN_TREE_256 12 2378238856Smm#define ST_MAIN_TREE_256 13 2379238856Smm#define ST_RD_PRE_MAIN_TREE_REM 14 2380238856Smm#define ST_MAIN_TREE_REM 15 2381238856Smm#define ST_RD_PRE_LENGTH_TREE 16 2382238856Smm#define ST_LENGTH_TREE 17 2383238856Smm#define ST_MAIN 18 2384238856Smm#define ST_LENGTH 19 2385238856Smm#define ST_OFFSET 20 2386238856Smm#define ST_REAL_POS 21 2387238856Smm#define ST_COPY 22 2388231200Smm 2389231200Smmstatic int 2390231200Smmlzx_decode(struct lzx_stream *strm, int last) 2391231200Smm{ 2392231200Smm struct lzx_dec *ds = strm->ds; 2393231200Smm int64_t avail_in; 2394231200Smm int r; 2395231200Smm 2396231200Smm if (ds->error) 2397231200Smm return (ds->error); 2398231200Smm 2399231200Smm avail_in = strm->avail_in; 2400231200Smm lzx_br_fixup(strm, &(ds->br)); 2401231200Smm do { 2402231200Smm if (ds->state < ST_MAIN) 2403231200Smm r = lzx_read_blocks(strm, last); 2404231200Smm else { 2405231200Smm int64_t bytes_written = strm->avail_out; 2406231200Smm r = lzx_decode_blocks(strm, last); 2407231200Smm bytes_written -= strm->avail_out; 2408231200Smm strm->next_out += bytes_written; 2409231200Smm strm->total_out += bytes_written; 2410231200Smm } 2411231200Smm } while (r == 100); 2412231200Smm strm->total_in += avail_in - strm->avail_in; 2413231200Smm return (r); 2414231200Smm} 2415231200Smm 2416231200Smmstatic int 2417231200Smmlzx_read_blocks(struct lzx_stream *strm, int last) 2418231200Smm{ 2419231200Smm struct lzx_dec *ds = strm->ds; 2420231200Smm struct lzx_br *br = &(ds->br); 2421231200Smm int i, r; 2422231200Smm 2423231200Smm for (;;) { 2424231200Smm switch (ds->state) { 2425231200Smm case ST_RD_TRANSLATION: 2426231200Smm if (!lzx_br_read_ahead(strm, br, 1)) { 2427231200Smm ds->state = ST_RD_TRANSLATION; 2428231200Smm if (last) 2429231200Smm goto failed; 2430231200Smm return (ARCHIVE_OK); 2431231200Smm } 2432231200Smm ds->translation = lzx_br_bits(br, 1); 2433231200Smm lzx_br_consume(br, 1); 2434231200Smm /* FALL THROUGH */ 2435231200Smm case ST_RD_TRANSLATION_SIZE: 2436231200Smm if (ds->translation) { 2437231200Smm if (!lzx_br_read_ahead(strm, br, 32)) { 2438231200Smm ds->state = ST_RD_TRANSLATION_SIZE; 2439231200Smm if (last) 2440231200Smm goto failed; 2441231200Smm return (ARCHIVE_OK); 2442231200Smm } 2443231200Smm ds->translation_size = lzx_br_bits(br, 16); 2444231200Smm lzx_br_consume(br, 16); 2445231200Smm ds->translation_size <<= 16; 2446231200Smm ds->translation_size |= lzx_br_bits(br, 16); 2447231200Smm lzx_br_consume(br, 16); 2448231200Smm } 2449231200Smm /* FALL THROUGH */ 2450231200Smm case ST_RD_BLOCK_TYPE: 2451231200Smm if (!lzx_br_read_ahead(strm, br, 3)) { 2452231200Smm ds->state = ST_RD_BLOCK_TYPE; 2453231200Smm if (last) 2454231200Smm goto failed; 2455231200Smm return (ARCHIVE_OK); 2456231200Smm } 2457231200Smm ds->block_type = lzx_br_bits(br, 3); 2458231200Smm lzx_br_consume(br, 3); 2459231200Smm /* Check a block type. */ 2460231200Smm switch (ds->block_type) { 2461231200Smm case VERBATIM_BLOCK: 2462231200Smm case ALIGNED_OFFSET_BLOCK: 2463231200Smm case UNCOMPRESSED_BLOCK: 2464231200Smm break; 2465231200Smm default: 2466231200Smm goto failed;/* Invalid */ 2467231200Smm } 2468231200Smm /* FALL THROUGH */ 2469231200Smm case ST_RD_BLOCK_SIZE: 2470231200Smm if (!lzx_br_read_ahead(strm, br, 24)) { 2471231200Smm ds->state = ST_RD_BLOCK_SIZE; 2472231200Smm if (last) 2473231200Smm goto failed; 2474231200Smm return (ARCHIVE_OK); 2475231200Smm } 2476231200Smm ds->block_size = lzx_br_bits(br, 8); 2477231200Smm lzx_br_consume(br, 8); 2478231200Smm ds->block_size <<= 16; 2479231200Smm ds->block_size |= lzx_br_bits(br, 16); 2480231200Smm lzx_br_consume(br, 16); 2481231200Smm if (ds->block_size == 0) 2482231200Smm goto failed; 2483231200Smm ds->block_bytes_avail = ds->block_size; 2484231200Smm if (ds->block_type != UNCOMPRESSED_BLOCK) { 2485231200Smm if (ds->block_type == VERBATIM_BLOCK) 2486231200Smm ds->state = ST_RD_VERBATIM; 2487231200Smm else 2488231200Smm ds->state = ST_RD_ALIGNED_OFFSET; 2489231200Smm break; 2490231200Smm } 2491238856Smm /* FALL THROUGH */ 2492238856Smm case ST_RD_ALIGNMENT: 2493231200Smm /* 2494231200Smm * Handle an Uncompressed Block. 2495231200Smm */ 2496231200Smm /* Skip padding to align following field on 2497231200Smm * 16-bit boundary. */ 2498238856Smm if (lzx_br_is_unaligned(br)) 2499238856Smm lzx_br_consume_unaligned_bits(br); 2500238856Smm else { 2501238856Smm if (lzx_br_read_ahead(strm, br, 16)) 2502238856Smm lzx_br_consume(br, 16); 2503238856Smm else { 2504238856Smm ds->state = ST_RD_ALIGNMENT; 2505238856Smm if (last) 2506238856Smm goto failed; 2507238856Smm return (ARCHIVE_OK); 2508238856Smm } 2509238856Smm } 2510231200Smm /* Preparation to read repeated offsets R0,R1 and R2. */ 2511231200Smm ds->rbytes_avail = 0; 2512231200Smm ds->state = ST_RD_R0; 2513231200Smm /* FALL THROUGH */ 2514231200Smm case ST_RD_R0: 2515231200Smm case ST_RD_R1: 2516231200Smm case ST_RD_R2: 2517231200Smm do { 2518231200Smm uint16_t u16; 2519231200Smm /* Drain bits in the cache buffer of 2520231200Smm * bit-stream. */ 2521231200Smm if (lzx_br_has(br, 32)) { 2522231200Smm u16 = lzx_br_bits(br, 16); 2523231200Smm lzx_br_consume(br, 16); 2524231200Smm archive_le16enc(ds->rbytes, u16); 2525231200Smm u16 = lzx_br_bits(br, 16); 2526231200Smm lzx_br_consume(br, 16); 2527231200Smm archive_le16enc(ds->rbytes+2, u16); 2528231200Smm ds->rbytes_avail = 4; 2529231200Smm } else if (lzx_br_has(br, 16)) { 2530231200Smm u16 = lzx_br_bits(br, 16); 2531231200Smm lzx_br_consume(br, 16); 2532231200Smm archive_le16enc(ds->rbytes, u16); 2533231200Smm ds->rbytes_avail = 2; 2534238856Smm } 2535231200Smm if (ds->rbytes_avail < 4 && ds->br.have_odd) { 2536231200Smm ds->rbytes[ds->rbytes_avail++] = 2537231200Smm ds->br.odd; 2538231200Smm ds->br.have_odd = 0; 2539231200Smm } 2540231200Smm while (ds->rbytes_avail < 4) { 2541231200Smm if (strm->avail_in <= 0) { 2542231200Smm if (last) 2543231200Smm goto failed; 2544231200Smm return (ARCHIVE_OK); 2545231200Smm } 2546231200Smm ds->rbytes[ds->rbytes_avail++] = 2547231200Smm *strm->next_in++; 2548231200Smm strm->avail_in--; 2549231200Smm } 2550238856Smm ds->rbytes_avail = 0; 2551231200Smm if (ds->state == ST_RD_R0) { 2552231200Smm ds->r0 = archive_le32dec(ds->rbytes); 2553231200Smm if (ds->r0 < 0) 2554231200Smm goto failed; 2555231200Smm ds->state = ST_RD_R1; 2556231200Smm } else if (ds->state == ST_RD_R1) { 2557231200Smm ds->r1 = archive_le32dec(ds->rbytes); 2558231200Smm if (ds->r1 < 0) 2559231200Smm goto failed; 2560231200Smm ds->state = ST_RD_R2; 2561231200Smm } else if (ds->state == ST_RD_R2) { 2562231200Smm ds->r2 = archive_le32dec(ds->rbytes); 2563231200Smm if (ds->r2 < 0) 2564231200Smm goto failed; 2565231200Smm /* We've gotten all repeated offsets. */ 2566231200Smm ds->state = ST_COPY_UNCOMP1; 2567231200Smm } 2568231200Smm } while (ds->state != ST_COPY_UNCOMP1); 2569231200Smm /* FALL THROUGH */ 2570231200Smm case ST_COPY_UNCOMP1: 2571231200Smm /* 2572231200Smm * Copy bytes form next_in to next_out directly. 2573231200Smm */ 2574231200Smm while (ds->block_bytes_avail) { 2575238856Smm int l; 2576231200Smm 2577231200Smm if (strm->avail_out <= 0) 2578231200Smm /* Output buffer is empty. */ 2579231200Smm return (ARCHIVE_OK); 2580231200Smm if (strm->avail_in <= 0) { 2581231200Smm /* Input buffer is empty. */ 2582231200Smm if (last) 2583231200Smm goto failed; 2584231200Smm return (ARCHIVE_OK); 2585231200Smm } 2586248616Smm l = (int)ds->block_bytes_avail; 2587231200Smm if (l > ds->w_size - ds->w_pos) 2588231200Smm l = ds->w_size - ds->w_pos; 2589231200Smm if (l > strm->avail_out) 2590231200Smm l = (int)strm->avail_out; 2591231200Smm if (l > strm->avail_in) 2592231200Smm l = (int)strm->avail_in; 2593238856Smm memcpy(strm->next_out, strm->next_in, l); 2594238856Smm memcpy(&(ds->w_buff[ds->w_pos]), 2595238856Smm strm->next_in, l); 2596238856Smm strm->next_in += l; 2597238856Smm strm->avail_in -= l; 2598238856Smm strm->next_out += l; 2599238856Smm strm->avail_out -= l; 2600238856Smm strm->total_out += l; 2601238856Smm ds->w_pos = (ds->w_pos + l) & ds->w_mask; 2602238856Smm ds->block_bytes_avail -= l; 2603231200Smm } 2604231200Smm /* FALL THROUGH */ 2605231200Smm case ST_COPY_UNCOMP2: 2606231200Smm /* Re-align; skip padding byte. */ 2607231200Smm if (ds->block_size & 1) { 2608231200Smm if (strm->avail_in <= 0) { 2609231200Smm /* Input buffer is empty. */ 2610231200Smm ds->state = ST_COPY_UNCOMP2; 2611231200Smm if (last) 2612231200Smm goto failed; 2613231200Smm return (ARCHIVE_OK); 2614231200Smm } 2615231200Smm strm->next_in++; 2616231200Smm strm->avail_in --; 2617231200Smm } 2618231200Smm /* This block ended. */ 2619231200Smm ds->state = ST_RD_BLOCK_TYPE; 2620231200Smm return (ARCHIVE_EOF); 2621231200Smm /********************/ 2622231200Smm case ST_RD_ALIGNED_OFFSET: 2623231200Smm /* 2624231200Smm * Read Aligned offset tree. 2625231200Smm */ 2626231200Smm if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) { 2627231200Smm ds->state = ST_RD_ALIGNED_OFFSET; 2628231200Smm if (last) 2629231200Smm goto failed; 2630231200Smm return (ARCHIVE_OK); 2631231200Smm } 2632231200Smm memset(ds->at.freq, 0, sizeof(ds->at.freq)); 2633231200Smm for (i = 0; i < ds->at.len_size; i++) { 2634231200Smm ds->at.bitlen[i] = lzx_br_bits(br, 3); 2635231200Smm ds->at.freq[ds->at.bitlen[i]]++; 2636231200Smm lzx_br_consume(br, 3); 2637231200Smm } 2638231200Smm if (!lzx_make_huffman_table(&ds->at)) 2639231200Smm goto failed; 2640231200Smm /* FALL THROUGH */ 2641231200Smm case ST_RD_VERBATIM: 2642231200Smm ds->loop = 0; 2643231200Smm /* FALL THROUGH */ 2644231200Smm case ST_RD_PRE_MAIN_TREE_256: 2645231200Smm /* 2646231200Smm * Read Pre-tree for first 256 elements of main tree. 2647231200Smm */ 2648231200Smm if (!lzx_read_pre_tree(strm)) { 2649231200Smm ds->state = ST_RD_PRE_MAIN_TREE_256; 2650231200Smm if (last) 2651231200Smm goto failed; 2652231200Smm return (ARCHIVE_OK); 2653231200Smm } 2654231200Smm if (!lzx_make_huffman_table(&ds->pt)) 2655231200Smm goto failed; 2656231200Smm ds->loop = 0; 2657231200Smm /* FALL THROUGH */ 2658231200Smm case ST_MAIN_TREE_256: 2659231200Smm /* 2660231200Smm * Get path lengths of first 256 elements of main tree. 2661231200Smm */ 2662231200Smm r = lzx_read_bitlen(strm, &ds->mt, 256); 2663231200Smm if (r < 0) 2664231200Smm goto failed; 2665231200Smm else if (!r) { 2666231200Smm ds->state = ST_MAIN_TREE_256; 2667231200Smm if (last) 2668231200Smm goto failed; 2669231200Smm return (ARCHIVE_OK); 2670231200Smm } 2671231200Smm ds->loop = 0; 2672231200Smm /* FALL THROUGH */ 2673231200Smm case ST_RD_PRE_MAIN_TREE_REM: 2674231200Smm /* 2675231200Smm * Read Pre-tree for remaining elements of main tree. 2676231200Smm */ 2677231200Smm if (!lzx_read_pre_tree(strm)) { 2678231200Smm ds->state = ST_RD_PRE_MAIN_TREE_REM; 2679231200Smm if (last) 2680231200Smm goto failed; 2681231200Smm return (ARCHIVE_OK); 2682231200Smm } 2683231200Smm if (!lzx_make_huffman_table(&ds->pt)) 2684231200Smm goto failed; 2685231200Smm ds->loop = 256; 2686231200Smm /* FALL THROUGH */ 2687231200Smm case ST_MAIN_TREE_REM: 2688231200Smm /* 2689231200Smm * Get path lengths of remaining elements of main tree. 2690231200Smm */ 2691231200Smm r = lzx_read_bitlen(strm, &ds->mt, -1); 2692231200Smm if (r < 0) 2693231200Smm goto failed; 2694231200Smm else if (!r) { 2695231200Smm ds->state = ST_MAIN_TREE_REM; 2696231200Smm if (last) 2697231200Smm goto failed; 2698231200Smm return (ARCHIVE_OK); 2699231200Smm } 2700231200Smm if (!lzx_make_huffman_table(&ds->mt)) 2701231200Smm goto failed; 2702231200Smm ds->loop = 0; 2703231200Smm /* FALL THROUGH */ 2704231200Smm case ST_RD_PRE_LENGTH_TREE: 2705231200Smm /* 2706231200Smm * Read Pre-tree for remaining elements of main tree. 2707231200Smm */ 2708231200Smm if (!lzx_read_pre_tree(strm)) { 2709231200Smm ds->state = ST_RD_PRE_LENGTH_TREE; 2710231200Smm if (last) 2711231200Smm goto failed; 2712231200Smm return (ARCHIVE_OK); 2713231200Smm } 2714231200Smm if (!lzx_make_huffman_table(&ds->pt)) 2715231200Smm goto failed; 2716231200Smm ds->loop = 0; 2717231200Smm /* FALL THROUGH */ 2718231200Smm case ST_LENGTH_TREE: 2719231200Smm /* 2720231200Smm * Get path lengths of remaining elements of main tree. 2721231200Smm */ 2722231200Smm r = lzx_read_bitlen(strm, &ds->lt, -1); 2723231200Smm if (r < 0) 2724231200Smm goto failed; 2725231200Smm else if (!r) { 2726231200Smm ds->state = ST_LENGTH_TREE; 2727231200Smm if (last) 2728231200Smm goto failed; 2729231200Smm return (ARCHIVE_OK); 2730231200Smm } 2731231200Smm if (!lzx_make_huffman_table(&ds->lt)) 2732231200Smm goto failed; 2733231200Smm ds->state = ST_MAIN; 2734231200Smm return (100); 2735231200Smm } 2736231200Smm } 2737231200Smmfailed: 2738231200Smm return (ds->error = ARCHIVE_FAILED); 2739231200Smm} 2740231200Smm 2741231200Smmstatic int 2742231200Smmlzx_decode_blocks(struct lzx_stream *strm, int last) 2743231200Smm{ 2744231200Smm struct lzx_dec *ds = strm->ds; 2745231200Smm struct lzx_br bre = ds->br; 2746231200Smm struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt); 2747231200Smm const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl; 2748248616Smm unsigned char *noutp = strm->next_out; 2749248616Smm unsigned char *endp = noutp + strm->avail_out; 2750231200Smm unsigned char *w_buff = ds->w_buff; 2751231200Smm unsigned char *at_bitlen = at->bitlen; 2752231200Smm unsigned char *lt_bitlen = lt->bitlen; 2753231200Smm unsigned char *mt_bitlen = mt->bitlen; 2754231200Smm size_t block_bytes_avail = ds->block_bytes_avail; 2755231200Smm int at_max_bits = at->max_bits; 2756231200Smm int lt_max_bits = lt->max_bits; 2757231200Smm int mt_max_bits = mt->max_bits; 2758231200Smm int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos; 2759231200Smm int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; 2760231200Smm int length_header = ds->length_header; 2761231200Smm int offset_bits = ds->offset_bits; 2762231200Smm int position_slot = ds->position_slot; 2763231200Smm int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2; 2764231200Smm int state = ds->state; 2765231200Smm char block_type = ds->block_type; 2766231200Smm 2767231200Smm for (;;) { 2768231200Smm switch (state) { 2769231200Smm case ST_MAIN: 2770231200Smm for (;;) { 2771231200Smm if (block_bytes_avail == 0) { 2772231200Smm /* This block ended. */ 2773231200Smm ds->state = ST_RD_BLOCK_TYPE; 2774231200Smm ds->br = bre; 2775231200Smm ds->block_bytes_avail = 2776231200Smm block_bytes_avail; 2777231200Smm ds->copy_len = copy_len; 2778231200Smm ds->copy_pos = copy_pos; 2779231200Smm ds->length_header = length_header; 2780231200Smm ds->position_slot = position_slot; 2781231200Smm ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; 2782231200Smm ds->w_pos = w_pos; 2783248616Smm strm->avail_out = endp - noutp; 2784231200Smm return (ARCHIVE_EOF); 2785231200Smm } 2786248616Smm if (noutp >= endp) 2787231200Smm /* Output buffer is empty. */ 2788231200Smm goto next_data; 2789231200Smm 2790231200Smm if (!lzx_br_read_ahead(strm, &bre, 2791231200Smm mt_max_bits)) { 2792231200Smm if (!last) 2793231200Smm goto next_data; 2794231200Smm /* Remaining bits are less than 2795231200Smm * maximum bits(mt.max_bits) but maybe 2796231200Smm * it still remains as much as we need, 2797231200Smm * so we should try to use it with 2798231200Smm * dummy bits. */ 2799231200Smm c = lzx_decode_huffman(mt, 2800231200Smm lzx_br_bits_forced( 2801231200Smm &bre, mt_max_bits)); 2802231200Smm lzx_br_consume(&bre, mt_bitlen[c]); 2803231200Smm if (!lzx_br_has(&bre, 0)) 2804231200Smm goto failed;/* Over read. */ 2805231200Smm } else { 2806231200Smm c = lzx_decode_huffman(mt, 2807231200Smm lzx_br_bits(&bre, mt_max_bits)); 2808231200Smm lzx_br_consume(&bre, mt_bitlen[c]); 2809231200Smm } 2810231200Smm if (c > UCHAR_MAX) 2811231200Smm break; 2812231200Smm /* 2813231200Smm * 'c' is exactly literal code. 2814231200Smm */ 2815231200Smm /* Save a decoded code to reference it 2816231200Smm * afterward. */ 2817231200Smm w_buff[w_pos] = c; 2818231200Smm w_pos = (w_pos + 1) & w_mask; 2819231200Smm /* Store the decoded code to output buffer. */ 2820248616Smm *noutp++ = c; 2821231200Smm block_bytes_avail--; 2822231200Smm } 2823231200Smm /* 2824231200Smm * Get a match code, its length and offset. 2825231200Smm */ 2826231200Smm c -= UCHAR_MAX + 1; 2827231200Smm length_header = c & 7; 2828231200Smm position_slot = c >> 3; 2829231200Smm /* FALL THROUGH */ 2830231200Smm case ST_LENGTH: 2831231200Smm /* 2832231200Smm * Get a length. 2833231200Smm */ 2834231200Smm if (length_header == 7) { 2835231200Smm if (!lzx_br_read_ahead(strm, &bre, 2836231200Smm lt_max_bits)) { 2837231200Smm if (!last) { 2838231200Smm state = ST_LENGTH; 2839231200Smm goto next_data; 2840231200Smm } 2841231200Smm c = lzx_decode_huffman(lt, 2842231200Smm lzx_br_bits_forced( 2843231200Smm &bre, lt_max_bits)); 2844231200Smm lzx_br_consume(&bre, lt_bitlen[c]); 2845231200Smm if (!lzx_br_has(&bre, 0)) 2846231200Smm goto failed;/* Over read. */ 2847231200Smm } else { 2848231200Smm c = lzx_decode_huffman(lt, 2849231200Smm lzx_br_bits(&bre, lt_max_bits)); 2850231200Smm lzx_br_consume(&bre, lt_bitlen[c]); 2851231200Smm } 2852231200Smm copy_len = c + 7 + 2; 2853231200Smm } else 2854231200Smm copy_len = length_header + 2; 2855231200Smm if ((size_t)copy_len > block_bytes_avail) 2856231200Smm goto failed; 2857231200Smm /* 2858231200Smm * Get an offset. 2859231200Smm */ 2860231200Smm switch (position_slot) { 2861231200Smm case 0: /* Use repeated offset 0. */ 2862231200Smm copy_pos = r0; 2863231200Smm state = ST_REAL_POS; 2864231200Smm continue; 2865231200Smm case 1: /* Use repeated offset 1. */ 2866231200Smm copy_pos = r1; 2867231200Smm /* Swap repeated offset. */ 2868231200Smm r1 = r0; 2869231200Smm r0 = copy_pos; 2870231200Smm state = ST_REAL_POS; 2871231200Smm continue; 2872231200Smm case 2: /* Use repeated offset 2. */ 2873231200Smm copy_pos = r2; 2874231200Smm /* Swap repeated offset. */ 2875231200Smm r2 = r0; 2876231200Smm r0 = copy_pos; 2877231200Smm state = ST_REAL_POS; 2878231200Smm continue; 2879231200Smm default: 2880231200Smm offset_bits = 2881231200Smm pos_tbl[position_slot].footer_bits; 2882231200Smm break; 2883231200Smm } 2884231200Smm /* FALL THROUGH */ 2885231200Smm case ST_OFFSET: 2886231200Smm /* 2887231200Smm * Get the offset, which is a distance from 2888231200Smm * current window position. 2889231200Smm */ 2890231200Smm if (block_type == ALIGNED_OFFSET_BLOCK && 2891231200Smm offset_bits >= 3) { 2892231200Smm int offbits = offset_bits - 3; 2893231200Smm 2894231200Smm if (!lzx_br_read_ahead(strm, &bre, offbits)) { 2895231200Smm state = ST_OFFSET; 2896231200Smm if (last) 2897231200Smm goto failed; 2898231200Smm goto next_data; 2899231200Smm } 2900231200Smm copy_pos = lzx_br_bits(&bre, offbits) << 3; 2901231200Smm 2902231200Smm /* Get an aligned number. */ 2903231200Smm if (!lzx_br_read_ahead(strm, &bre, 2904231200Smm offbits + at_max_bits)) { 2905231200Smm if (!last) { 2906231200Smm state = ST_OFFSET; 2907231200Smm goto next_data; 2908231200Smm } 2909231200Smm lzx_br_consume(&bre, offbits); 2910231200Smm c = lzx_decode_huffman(at, 2911231200Smm lzx_br_bits_forced(&bre, 2912231200Smm at_max_bits)); 2913231200Smm lzx_br_consume(&bre, at_bitlen[c]); 2914231200Smm if (!lzx_br_has(&bre, 0)) 2915231200Smm goto failed;/* Over read. */ 2916231200Smm } else { 2917231200Smm lzx_br_consume(&bre, offbits); 2918231200Smm c = lzx_decode_huffman(at, 2919231200Smm lzx_br_bits(&bre, at_max_bits)); 2920231200Smm lzx_br_consume(&bre, at_bitlen[c]); 2921231200Smm } 2922231200Smm /* Add an aligned number. */ 2923231200Smm copy_pos += c; 2924231200Smm } else { 2925231200Smm if (!lzx_br_read_ahead(strm, &bre, 2926231200Smm offset_bits)) { 2927231200Smm state = ST_OFFSET; 2928231200Smm if (last) 2929231200Smm goto failed; 2930231200Smm goto next_data; 2931231200Smm } 2932231200Smm copy_pos = lzx_br_bits(&bre, offset_bits); 2933231200Smm lzx_br_consume(&bre, offset_bits); 2934231200Smm } 2935231200Smm copy_pos += pos_tbl[position_slot].base -2; 2936231200Smm 2937231200Smm /* Update repeated offset LRU queue. */ 2938231200Smm r2 = r1; 2939231200Smm r1 = r0; 2940231200Smm r0 = copy_pos; 2941231200Smm /* FALL THROUGH */ 2942231200Smm case ST_REAL_POS: 2943231200Smm /* 2944231200Smm * Compute a real position in window. 2945231200Smm */ 2946231200Smm copy_pos = (w_pos - copy_pos) & w_mask; 2947231200Smm /* FALL THROUGH */ 2948231200Smm case ST_COPY: 2949231200Smm /* 2950231200Smm * Copy several bytes as extracted data from the window 2951231200Smm * into the output buffer. 2952231200Smm */ 2953231200Smm for (;;) { 2954231200Smm const unsigned char *s; 2955231200Smm int l; 2956231200Smm 2957231200Smm l = copy_len; 2958231200Smm if (copy_pos > w_pos) { 2959231200Smm if (l > w_size - copy_pos) 2960231200Smm l = w_size - copy_pos; 2961231200Smm } else { 2962231200Smm if (l > w_size - w_pos) 2963231200Smm l = w_size - w_pos; 2964231200Smm } 2965248616Smm if (noutp + l >= endp) 2966248616Smm l = (int)(endp - noutp); 2967231200Smm s = w_buff + copy_pos; 2968231200Smm if (l >= 8 && ((copy_pos + l < w_pos) 2969231200Smm || (w_pos + l < copy_pos))) { 2970231200Smm memcpy(w_buff + w_pos, s, l); 2971248616Smm memcpy(noutp, s, l); 2972231200Smm } else { 2973231200Smm unsigned char *d; 2974231200Smm int li; 2975231200Smm 2976231200Smm d = w_buff + w_pos; 2977231200Smm for (li = 0; li < l; li++) 2978248616Smm noutp[li] = d[li] = s[li]; 2979231200Smm } 2980248616Smm noutp += l; 2981231200Smm copy_pos = (copy_pos + l) & w_mask; 2982231200Smm w_pos = (w_pos + l) & w_mask; 2983231200Smm block_bytes_avail -= l; 2984231200Smm if (copy_len <= l) 2985231200Smm /* A copy of current pattern ended. */ 2986231200Smm break; 2987231200Smm copy_len -= l; 2988248616Smm if (noutp >= endp) { 2989231200Smm /* Output buffer is empty. */ 2990231200Smm state = ST_COPY; 2991231200Smm goto next_data; 2992231200Smm } 2993231200Smm } 2994231200Smm state = ST_MAIN; 2995231200Smm break; 2996231200Smm } 2997231200Smm } 2998231200Smmfailed: 2999231200Smm return (ds->error = ARCHIVE_FAILED); 3000231200Smmnext_data: 3001231200Smm ds->br = bre; 3002231200Smm ds->block_bytes_avail = block_bytes_avail; 3003231200Smm ds->copy_len = copy_len; 3004231200Smm ds->copy_pos = copy_pos; 3005231200Smm ds->length_header = length_header; 3006231200Smm ds->offset_bits = offset_bits; 3007231200Smm ds->position_slot = position_slot; 3008231200Smm ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; 3009231200Smm ds->state = state; 3010231200Smm ds->w_pos = w_pos; 3011248616Smm strm->avail_out = endp - noutp; 3012231200Smm return (ARCHIVE_OK); 3013231200Smm} 3014231200Smm 3015231200Smmstatic int 3016231200Smmlzx_read_pre_tree(struct lzx_stream *strm) 3017231200Smm{ 3018231200Smm struct lzx_dec *ds = strm->ds; 3019231200Smm struct lzx_br *br = &(ds->br); 3020231200Smm int i; 3021231200Smm 3022231200Smm if (ds->loop == 0) 3023231200Smm memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); 3024231200Smm for (i = ds->loop; i < ds->pt.len_size; i++) { 3025231200Smm if (!lzx_br_read_ahead(strm, br, 4)) { 3026231200Smm ds->loop = i; 3027231200Smm return (0); 3028231200Smm } 3029231200Smm ds->pt.bitlen[i] = lzx_br_bits(br, 4); 3030231200Smm ds->pt.freq[ds->pt.bitlen[i]]++; 3031231200Smm lzx_br_consume(br, 4); 3032231200Smm } 3033231200Smm ds->loop = i; 3034231200Smm return (1); 3035231200Smm} 3036231200Smm 3037231200Smm/* 3038231200Smm * Read a bunch of bit-lengths from pre-tree. 3039231200Smm */ 3040231200Smmstatic int 3041231200Smmlzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end) 3042231200Smm{ 3043231200Smm struct lzx_dec *ds = strm->ds; 3044231200Smm struct lzx_br *br = &(ds->br); 3045231200Smm int c, i, j, ret, same; 3046231200Smm unsigned rbits; 3047231200Smm 3048231200Smm i = ds->loop; 3049231200Smm if (i == 0) 3050231200Smm memset(d->freq, 0, sizeof(d->freq)); 3051231200Smm ret = 0; 3052231200Smm if (end < 0) 3053231200Smm end = d->len_size; 3054231200Smm while (i < end) { 3055231200Smm ds->loop = i; 3056231200Smm if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits)) 3057231200Smm goto getdata; 3058231200Smm rbits = lzx_br_bits(br, ds->pt.max_bits); 3059231200Smm c = lzx_decode_huffman(&(ds->pt), rbits); 3060231200Smm switch (c) { 3061231200Smm case 17:/* several zero lengths, from 4 to 19. */ 3062231200Smm if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4)) 3063231200Smm goto getdata; 3064231200Smm lzx_br_consume(br, ds->pt.bitlen[c]); 3065231200Smm same = lzx_br_bits(br, 4) + 4; 3066231200Smm if (i + same > end) 3067231200Smm return (-1);/* Invalid */ 3068231200Smm lzx_br_consume(br, 4); 3069231200Smm for (j = 0; j < same; j++) 3070231200Smm d->bitlen[i++] = 0; 3071231200Smm break; 3072231200Smm case 18:/* many zero lengths, from 20 to 51. */ 3073231200Smm if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5)) 3074231200Smm goto getdata; 3075231200Smm lzx_br_consume(br, ds->pt.bitlen[c]); 3076231200Smm same = lzx_br_bits(br, 5) + 20; 3077231200Smm if (i + same > end) 3078231200Smm return (-1);/* Invalid */ 3079231200Smm lzx_br_consume(br, 5); 3080231200Smm memset(d->bitlen + i, 0, same); 3081231200Smm i += same; 3082231200Smm break; 3083231200Smm case 19:/* a few same lengths. */ 3084231200Smm if (!lzx_br_read_ahead(strm, br, 3085231200Smm ds->pt.bitlen[c]+1+ds->pt.max_bits)) 3086231200Smm goto getdata; 3087231200Smm lzx_br_consume(br, ds->pt.bitlen[c]); 3088231200Smm same = lzx_br_bits(br, 1) + 4; 3089231200Smm if (i + same > end) 3090231200Smm return (-1); 3091231200Smm lzx_br_consume(br, 1); 3092231200Smm rbits = lzx_br_bits(br, ds->pt.max_bits); 3093231200Smm c = lzx_decode_huffman(&(ds->pt), rbits); 3094231200Smm lzx_br_consume(br, ds->pt.bitlen[c]); 3095231200Smm c = (d->bitlen[i] - c + 17) % 17; 3096231200Smm if (c < 0) 3097231200Smm return (-1);/* Invalid */ 3098231200Smm for (j = 0; j < same; j++) 3099231200Smm d->bitlen[i++] = c; 3100231200Smm d->freq[c] += same; 3101231200Smm break; 3102231200Smm default: 3103231200Smm lzx_br_consume(br, ds->pt.bitlen[c]); 3104231200Smm c = (d->bitlen[i] - c + 17) % 17; 3105231200Smm if (c < 0) 3106231200Smm return (-1);/* Invalid */ 3107231200Smm d->freq[c]++; 3108231200Smm d->bitlen[i++] = c; 3109231200Smm break; 3110231200Smm } 3111231200Smm } 3112231200Smm ret = 1; 3113231200Smmgetdata: 3114231200Smm ds->loop = i; 3115231200Smm return (ret); 3116231200Smm} 3117231200Smm 3118231200Smmstatic int 3119231200Smmlzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) 3120231200Smm{ 3121231200Smm 3122231200Smm if (hf->bitlen == NULL || hf->len_size != (int)len_size) { 3123231200Smm free(hf->bitlen); 3124231200Smm hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0])); 3125231200Smm if (hf->bitlen == NULL) 3126231200Smm return (ARCHIVE_FATAL); 3127248616Smm hf->len_size = (int)len_size; 3128231200Smm } else 3129231200Smm memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0])); 3130231200Smm if (hf->tbl == NULL) { 3131318483Smm hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0])); 3132231200Smm if (hf->tbl == NULL) 3133231200Smm return (ARCHIVE_FATAL); 3134231200Smm hf->tbl_bits = tbl_bits; 3135231200Smm } 3136231200Smm return (ARCHIVE_OK); 3137231200Smm} 3138231200Smm 3139231200Smmstatic void 3140231200Smmlzx_huffman_free(struct huffman *hf) 3141231200Smm{ 3142231200Smm free(hf->bitlen); 3143231200Smm free(hf->tbl); 3144231200Smm} 3145231200Smm 3146231200Smm/* 3147231200Smm * Make a huffman coding table. 3148231200Smm */ 3149231200Smmstatic int 3150231200Smmlzx_make_huffman_table(struct huffman *hf) 3151231200Smm{ 3152231200Smm uint16_t *tbl; 3153231200Smm const unsigned char *bitlen; 3154231200Smm int bitptn[17], weight[17]; 3155231200Smm int i, maxbits = 0, ptn, tbl_size, w; 3156318483Smm int len_avail; 3157231200Smm 3158231200Smm /* 3159231200Smm * Initialize bit patterns. 3160231200Smm */ 3161231200Smm ptn = 0; 3162231200Smm for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { 3163231200Smm bitptn[i] = ptn; 3164231200Smm weight[i] = w; 3165231200Smm if (hf->freq[i]) { 3166231200Smm ptn += hf->freq[i] * w; 3167231200Smm maxbits = i; 3168231200Smm } 3169231200Smm } 3170231200Smm if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits) 3171231200Smm return (0);/* Invalid */ 3172231200Smm 3173231200Smm hf->max_bits = maxbits; 3174231200Smm 3175231200Smm /* 3176231200Smm * Cut out extra bits which we won't house in the table. 3177231200Smm * This preparation reduces the same calculation in the for-loop 3178231200Smm * making the table. 3179231200Smm */ 3180231200Smm if (maxbits < 16) { 3181231200Smm int ebits = 16 - maxbits; 3182231200Smm for (i = 1; i <= maxbits; i++) { 3183231200Smm bitptn[i] >>= ebits; 3184231200Smm weight[i] >>= ebits; 3185231200Smm } 3186231200Smm } 3187231200Smm 3188231200Smm /* 3189231200Smm * Make the table. 3190231200Smm */ 3191318483Smm tbl_size = 1 << hf->tbl_bits; 3192231200Smm tbl = hf->tbl; 3193231200Smm bitlen = hf->bitlen; 3194231200Smm len_avail = hf->len_size; 3195231200Smm hf->tree_used = 0; 3196231200Smm for (i = 0; i < len_avail; i++) { 3197231200Smm uint16_t *p; 3198231200Smm int len, cnt; 3199231200Smm 3200231200Smm if (bitlen[i] == 0) 3201231200Smm continue; 3202231200Smm /* Get a bit pattern */ 3203231200Smm len = bitlen[i]; 3204318483Smm if (len > tbl_size) 3205318483Smm return (0); 3206231200Smm ptn = bitptn[len]; 3207231200Smm cnt = weight[len]; 3208318483Smm /* Calculate next bit pattern */ 3209318483Smm if ((bitptn[len] = ptn + cnt) > tbl_size) 3210318483Smm return (0);/* Invalid */ 3211318483Smm /* Update the table */ 3212318483Smm p = &(tbl[ptn]); 3213318483Smm while (--cnt >= 0) 3214318483Smm p[cnt] = (uint16_t)i; 3215231200Smm } 3216231200Smm return (1); 3217231200Smm} 3218231200Smm 3219231200Smmstatic inline int 3220231200Smmlzx_decode_huffman(struct huffman *hf, unsigned rbits) 3221231200Smm{ 3222231200Smm int c; 3223318483Smm c = hf->tbl[rbits]; 3224231200Smm if (c < hf->len_size) 3225231200Smm return (c); 3226318483Smm return (0); 3227231200Smm} 3228