| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * mpq-pkware.c -- PKWARE Data Compression Library implementation. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003-2026 Maik Broemme <mbroemme@libmpq.org> | ||
| 5 | * | ||
| 6 | * This source was adapted from the C++ version of pkware.cpp included | ||
| 7 | * in stormlib. The C++ version belongs to the following authors: | ||
| 8 | * | ||
| 9 | * Ladislav Zezula <ladik@zezula.net> | ||
| 10 | * | ||
| 11 | * This file is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU Lesser General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2.1 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This file is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU Lesser General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU Lesser General Public License | ||
| 22 | * along with this file; if not, see <https://www.gnu.org/licenses/>. | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include "mpq-pkware.h" | ||
| 26 | #include <libmpq/mpq.h> | ||
| 27 | |||
| 28 | #include <stdlib.h> | ||
| 29 | #include <string.h> | ||
| 30 | |||
| 31 | /* Distance bit lengths used by the PKWARE explode distance decoder. */ | ||
| 32 | static const uint8_t pkzip_dist_bits[] = { | ||
| 33 | 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, | ||
| 34 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
| 35 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
| 36 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 | ||
| 37 | }; | ||
| 38 | |||
| 39 | /* Distance code lookup table used by the PKWARE explode decoder. */ | ||
| 40 | static const uint8_t pkzip_dist_code[] = { | ||
| 41 | 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, | ||
| 42 | 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, | ||
| 43 | 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, | ||
| 44 | 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* Extra bit counts for decoded copy lengths. */ | ||
| 48 | static const uint8_t pkzip_clen_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 49 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; | ||
| 50 | |||
| 51 | /* Base values for decoded copy lengths. */ | ||
| 52 | static const uint16_t pkzip_len_base[] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, | ||
| 53 | 0x0006, 0x0007, 0x0008, 0x000A, 0x000E, 0x0016, | ||
| 54 | 0x0026, 0x0046, 0x0086, 0x0106 }; | ||
| 55 | |||
| 56 | /* Bit lengths for the static copy-length Huffman table. */ | ||
| 57 | static const uint8_t pkzip_slen_bits[] = { 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, | ||
| 58 | 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 }; | ||
| 59 | |||
| 60 | /* Codes for the static copy-length Huffman table. */ | ||
| 61 | static const uint8_t pkzip_len_code[] = { 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, | ||
| 62 | 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 }; | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Append a low-bit-first PKWARE code to the output bitstream. | ||
| 66 | * The caller provides a zeroed output buffer and a bit cursor, and this helper | ||
| 67 | * sets only the bits represented by the requested code. | ||
| 68 | */ | ||
| 69 | static void | ||
| 70 | 1285594 | pkzip_put_bits(uint8_t *out, size_t *bit_pos, uint32_t value, unsigned bits) | |
| 71 | { | ||
| 72 | unsigned i; | ||
| 73 |
2/2✓ Branch 0 taken 5845067 times.
✓ Branch 1 taken 1285594 times.
|
7130661 | for (i = 0; i < bits; i++, (*bit_pos)++) |
| 74 |
2/2✓ Branch 0 taken 2608266 times.
✓ Branch 1 taken 3236801 times.
|
5845067 | if (value & (1u << i)) |
| 75 | 2608266 | out[*bit_pos >> 3] |= (uint8_t)(1u << (*bit_pos & 7)); | |
| 76 | 1285594 | } | |
| 77 | |||
| 78 | /* Bit lengths for the ASCII literal table. */ | ||
| 79 | static const uint8_t pkzip_bits_asc[] = { | ||
| 80 | 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, | ||
| 81 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, | ||
| 82 | 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, | ||
| 83 | 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, | ||
| 84 | 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, | ||
| 85 | 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, | ||
| 86 | 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, | ||
| 87 | 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, | ||
| 88 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, | ||
| 89 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, | ||
| 90 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, | ||
| 91 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, | ||
| 92 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, | ||
| 93 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, | ||
| 94 | 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, | ||
| 95 | 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* Codes for the ASCII literal table. */ | ||
| 99 | static const uint16_t pkzip_code_asc[] = { | ||
| 100 | 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, 0x01E0, 0x00B8, 0x0062, 0x0EE0, | ||
| 101 | 0x06E0, 0x0022, 0x0AE0, 0x02E0, 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, | ||
| 102 | 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, 0x000F, 0x0250, 0x0038, 0x0260, | ||
| 103 | 0x0050, 0x0C60, 0x0390, 0x00D8, 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, | ||
| 104 | 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, 0x0074, 0x00E8, 0x0068, 0x0460, | ||
| 105 | 0x0090, 0x0034, 0x00B0, 0x0710, 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, | ||
| 106 | 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, 0x0024, 0x0510, 0x000E, 0x0036, | ||
| 107 | 0x0016, 0x0044, 0x0030, 0x00C8, 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, | ||
| 108 | 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, 0x000A, 0x000B, 0x0210, 0x0004, | ||
| 109 | 0x0013, 0x0032, 0x0003, 0x001D, 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, | ||
| 110 | 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, 0x0240, 0x1C40, 0x0C40, 0x1440, | ||
| 111 | 0x0440, 0x1840, 0x0840, 0x1040, 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, | ||
| 112 | 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, 0x0180, 0x1E80, 0x0E80, 0x1680, | ||
| 113 | 0x0680, 0x1A80, 0x0A80, 0x1280, 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, | ||
| 114 | 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, 0x0DA0, 0x05A0, 0x09A0, 0x01A0, | ||
| 115 | 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, | ||
| 116 | 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, 0x0C20, 0x0420, 0x0820, 0x0020, | ||
| 117 | 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, | ||
| 118 | 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, 0x0300, 0x0D40, 0x1D00, 0x0D00, | ||
| 119 | 0x1500, 0x0540, 0x0500, 0x1900, 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, | ||
| 120 | 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, 0x1C00, 0x0C00, 0x1400, 0x0400, | ||
| 121 | 0x1800, 0x0800, 0x1000, 0x0000 | ||
| 122 | }; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Consume bits from the PKWARE input accumulator. | ||
| 126 | * It refills the eight-bit staging window through the configured callback and | ||
| 127 | * returns a nonzero value when the compressed input ends prematurely. | ||
| 128 | */ | ||
| 129 | static int32_t | ||
| 130 | 740487 | skip_bit(pkzip_cmp_s *mpq_pkzip, uint32_t bits) | |
| 131 | { | ||
| 132 |
2/2✓ Branch 0 taken 340103 times.
✓ Branch 1 taken 400384 times.
|
740487 | if (bits <= mpq_pkzip->extra_bits) { |
| 133 | 340103 | mpq_pkzip->extra_bits -= bits; | |
| 134 | 340103 | mpq_pkzip->bit_buf >>= bits; | |
| 135 | 340103 | return 0; | |
| 136 | } | ||
| 137 | |||
| 138 | /* Refill the bit buffer from the input callback when the staging buffer is empty. */ | ||
| 139 | 400384 | mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits; | |
| 140 |
2/2✓ Branch 0 taken 1212 times.
✓ Branch 1 taken 399172 times.
|
400384 | if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) { |
| 141 | 1212 | uint32_t in_size = sizeof(mpq_pkzip->in_buf); | |
| 142 | |||
| 143 |
2/2✓ Branch 0 taken 1100 times.
✓ Branch 1 taken 112 times.
|
1212 | if ((mpq_pkzip->in_bytes = |
| 144 | 1212 | mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &in_size, mpq_pkzip->param)) == 0) { | |
| 145 | 1100 | return 1; | |
| 146 | } | ||
| 147 | 112 | mpq_pkzip->in_pos = 0; | |
| 148 | } | ||
| 149 | |||
| 150 | 399284 | mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8); | |
| 151 | 399284 | mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits); | |
| 152 | 399284 | mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8; | |
| 153 | |||
| 154 | 399284 | return 0; | |
| 155 | } | ||
| 156 | |||
| 157 | /* | ||
| 158 | * Build a decode lookup table from PKWARE canonical bit codes. | ||
| 159 | * Each short code is expanded across all matching low-byte prefixes so the | ||
| 160 | * decoder can resolve literals and lengths without walking a tree at runtime. | ||
| 161 | */ | ||
| 162 | static void | ||
| 163 | 2200 | generate_tables_decode(int32_t count, uint8_t *bits, const uint8_t *code, uint8_t *buf2) | |
| 164 | { | ||
| 165 | |||
| 166 | /* Walk backwards because the original table order assigns higher codes first. */ | ||
| 167 | int32_t i; | ||
| 168 | |||
| 169 |
2/2✓ Branch 0 taken 88000 times.
✓ Branch 1 taken 2200 times.
|
90200 | for (i = count - 1; i >= 0; i--) { |
| 170 | |||
| 171 | /* Fill every lookup slot reachable by this code prefix. */ | ||
| 172 | 88000 | uint32_t idx1 = code[i]; | |
| 173 | 88000 | uint32_t idx2 = 1 << bits[i]; | |
| 174 | |||
| 175 | do { | ||
| 176 | 563200 | buf2[idx1] = (uint8_t)i; | |
| 177 | 563200 | idx1 += idx2; | |
| 178 |
2/2✓ Branch 0 taken 475200 times.
✓ Branch 1 taken 88000 times.
|
563200 | } while (idx1 < 0x100); |
| 179 | } | ||
| 180 | 2200 | } | |
| 181 | |||
| 182 | /* | ||
| 183 | * Build the ASCII literal lookup tables used by the PKWARE decoder. | ||
| 184 | * The static canonical tables are expanded into prefix tables that support | ||
| 185 | * the variable-length ASCII mode used by DCL streams. | ||
| 186 | */ | ||
| 187 | static void | ||
| 188 | ✗ | generate_tables_ascii(pkzip_cmp_s *mpq_pkzip) | |
| 189 | { | ||
| 190 | |||
| 191 | /* ASCII table cursor and bit expansion state. */ | ||
| 192 | ✗ | const uint16_t *code_asc = &pkzip_code_asc[0xFF]; | |
| 193 | uint32_t acc; | ||
| 194 | uint32_t add; | ||
| 195 | uint16_t count; | ||
| 196 | |||
| 197 | /* Expand the static ASCII literal codes into the decoder lookup tables. */ | ||
| 198 | ✗ | for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) { | |
| 199 | ✗ | uint8_t *bits_asc = mpq_pkzip->bits_asc + count; | |
| 200 | ✗ | uint8_t bits_tmp = *bits_asc; | |
| 201 | |||
| 202 | ✗ | if (bits_tmp <= 8) { | |
| 203 | ✗ | add = (1 << bits_tmp); | |
| 204 | ✗ | acc = *code_asc; | |
| 205 | ✗ | while (acc < 0x100) { | |
| 206 | ✗ | mpq_pkzip->offs_2c34[acc] = (uint8_t)count; | |
| 207 | ✗ | acc += add; | |
| 208 | } | ||
| 209 | } else { | ||
| 210 | ✗ | if ((acc = (*code_asc & 0xFF)) != 0) { | |
| 211 | ✗ | mpq_pkzip->offs_2c34[acc] = 0xFF; | |
| 212 | ✗ | if (*code_asc & 0x3F) { | |
| 213 | ✗ | bits_tmp -= 4; | |
| 214 | ✗ | *bits_asc = bits_tmp; | |
| 215 | ✗ | add = (1 << bits_tmp); | |
| 216 | ✗ | acc = *code_asc >> 4; | |
| 217 | do { | ||
| 218 | ✗ | mpq_pkzip->offs_2d34[acc] = (uint8_t)count; | |
| 219 | ✗ | acc += add; | |
| 220 | ✗ | } while (acc < 0x100); | |
| 221 | } else { | ||
| 222 | ✗ | bits_tmp -= 6; | |
| 223 | ✗ | *bits_asc = bits_tmp; | |
| 224 | ✗ | add = (1 << bits_tmp); | |
| 225 | ✗ | acc = *code_asc >> 6; | |
| 226 | do { | ||
| 227 | ✗ | mpq_pkzip->offs_2e34[acc] = (uint8_t)count; | |
| 228 | ✗ | acc += add; | |
| 229 | ✗ | } while (acc < 0x80); | |
| 230 | } | ||
| 231 | } else { | ||
| 232 | ✗ | bits_tmp -= 8; | |
| 233 | ✗ | *bits_asc = bits_tmp; | |
| 234 | ✗ | add = (1 << bits_tmp); | |
| 235 | ✗ | acc = *code_asc >> 8; | |
| 236 | do { | ||
| 237 | ✗ | mpq_pkzip->offs_2eb4[acc] = (uint8_t)count; | |
| 238 | ✗ | acc += add; | |
| 239 | ✗ | } while (acc < 0x100); | |
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | ✗ | } | |
| 244 | |||
| 245 | /* | ||
| 246 | * Decode one PKWARE literal or copy marker. | ||
| 247 | * The low control bit distinguishes a length/distance match from a literal, | ||
| 248 | * and the selected mode determines whether literals are binary or ASCII-coded. | ||
| 249 | */ | ||
| 250 | static uint32_t | ||
| 251 | 331788 | decode_literal(pkzip_cmp_s *mpq_pkzip) | |
| 252 | { | ||
| 253 | uint32_t bits; | ||
| 254 | uint32_t value; | ||
| 255 | |||
| 256 | /* A set low bit marks a length code; an unset bit marks a literal code. */ | ||
| 257 |
2/2✓ Branch 0 taken 32490 times.
✓ Branch 1 taken 299298 times.
|
331788 | if (mpq_pkzip->bit_buf & 1) { |
| 258 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32490 times.
|
32490 | if (skip_bit(mpq_pkzip, 1)) { |
| 259 | ✗ | return 0x306; | |
| 260 | } | ||
| 261 | |||
| 262 | /* The next prefix selects a length-code table entry. */ | ||
| 263 | 32490 | value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)]; | |
| 264 | |||
| 265 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32490 times.
|
32490 | if (skip_bit(mpq_pkzip, mpq_pkzip->slen_bits[value])) { |
| 266 | ✗ | return 0x306; | |
| 267 | } | ||
| 268 | |||
| 269 |
2/2✓ Branch 0 taken 14127 times.
✓ Branch 1 taken 18363 times.
|
32490 | if ((bits = mpq_pkzip->clen_bits[value]) != 0) { |
| 270 | |||
| 271 | /* Decoded literal symbol and bit length for this table entry. */ | ||
| 272 | 14127 | uint32_t val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1); | |
| 273 | |||
| 274 |
2/2✓ Branch 1 taken 1098 times.
✓ Branch 2 taken 13029 times.
|
14127 | if (skip_bit(mpq_pkzip, bits)) { |
| 275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1098 times.
|
1098 | if ((value + val2) != 0x10E) { |
| 276 | ✗ | return 0x306; | |
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | 14127 | value = mpq_pkzip->len_base[value] + val2; | |
| 281 | } | ||
| 282 | |||
| 283 | 32490 | return value + 0x100; | |
| 284 | } | ||
| 285 | |||
| 286 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 299298 times.
|
299298 | if (skip_bit(mpq_pkzip, 1)) { |
| 287 | ✗ | return 0x306; | |
| 288 | } | ||
| 289 | |||
| 290 | /* Binary mode carries literal bytes directly after the control bit. */ | ||
| 291 |
1/2✓ Branch 0 taken 299298 times.
✗ Branch 1 not taken.
|
299298 | if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) { |
| 292 | 299298 | value = mpq_pkzip->bit_buf & 0xFF; | |
| 293 | |||
| 294 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 299297 times.
|
299298 | if (skip_bit(mpq_pkzip, 8)) { |
| 295 | 1 | return 0x306; | |
| 296 | } | ||
| 297 | |||
| 298 | 299297 | return value; | |
| 299 | } | ||
| 300 | |||
| 301 | /* ASCII mode resolves short prefixes through progressively wider tables. */ | ||
| 302 | ✗ | if (mpq_pkzip->bit_buf & 0xFF) { | |
| 303 | ✗ | value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF]; | |
| 304 | |||
| 305 | ✗ | if (value == 0xFF) { | |
| 306 | ✗ | if (mpq_pkzip->bit_buf & 0x3F) { | |
| 307 | ✗ | if (skip_bit(mpq_pkzip, 4)) { | |
| 308 | ✗ | return 0x306; | |
| 309 | } | ||
| 310 | |||
| 311 | ✗ | value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF]; | |
| 312 | } else { | ||
| 313 | ✗ | if (skip_bit(mpq_pkzip, 6)) { | |
| 314 | ✗ | return 0x306; | |
| 315 | } | ||
| 316 | |||
| 317 | ✗ | value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F]; | |
| 318 | } | ||
| 319 | } | ||
| 320 | } else { | ||
| 321 | |||
| 322 | /* Ensure eight bits are available before advancing the bit buffer. */ | ||
| 323 | ✗ | if (skip_bit(mpq_pkzip, 8)) { | |
| 324 | ✗ | return 0x306; | |
| 325 | } | ||
| 326 | |||
| 327 | ✗ | value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF]; | |
| 328 | } | ||
| 329 | |||
| 330 | ✗ | return skip_bit(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value; | |
| 331 | } | ||
| 332 | |||
| 333 | /* | ||
| 334 | * Decode the backward distance for a PKWARE copy operation. | ||
| 335 | * Two-byte matches use a fixed suffix width, while longer matches use the | ||
| 336 | * dictionary-size-dependent distance width configured in the stream header. | ||
| 337 | */ | ||
| 338 | static uint32_t | ||
| 339 | 31392 | decode_distance(pkzip_cmp_s *mpq_pkzip, uint32_t length) | |
| 340 | { | ||
| 341 | |||
| 342 | /* Distance prefix, extra bits and final byte distance. */ | ||
| 343 | 31392 | uint32_t pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)]; | |
| 344 | |||
| 345 | 31392 | uint32_t skip = mpq_pkzip->dist_bits[pos]; | |
| 346 | |||
| 347 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 31392 times.
|
31392 | if (skip_bit(mpq_pkzip, skip) == 1) { |
| 348 | ✗ | return 0; | |
| 349 | } | ||
| 350 | |||
| 351 | /* Two-byte matches use a fixed two-bit distance suffix. */ | ||
| 352 |
2/2✓ Branch 0 taken 4022 times.
✓ Branch 1 taken 27370 times.
|
31392 | if (length == 2) { |
| 353 | 4022 | pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03); | |
| 354 | |||
| 355 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4022 times.
|
4022 | if (skip_bit(mpq_pkzip, 2) == 1) { |
| 356 | ✗ | return 0; | |
| 357 | } | ||
| 358 | } else { | ||
| 359 | 27370 | pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask); | |
| 360 | |||
| 361 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 27369 times.
|
27370 | if (skip_bit(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) { |
| 362 | 1 | return 0; | |
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | 31391 | return pos + 1; | |
| 367 | } | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Supply compressed bytes to the PKWARE decoder callback. | ||
| 371 | * The callback clamps each request to the remaining input and advances the | ||
| 372 | * wrapper-owned cursor so the codec never reads beyond the MPQ block. | ||
| 373 | */ | ||
| 374 | static uint32_t | ||
| 375 | 2318 | data_read_input(char *buf, uint32_t *size, void *param) | |
| 376 | { | ||
| 377 | |||
| 378 | /* Source state passed by the public decompression wrapper. */ | ||
| 379 | 2318 | pkzip_data_s *info = (pkzip_data_s *)param; | |
| 380 | 2318 | uint32_t max_avail = (info->in_bytes - info->in_pos); | |
| 381 | 2318 | uint32_t to_read = *size; | |
| 382 | |||
| 383 |
2/2✓ Branch 0 taken 2206 times.
✓ Branch 1 taken 112 times.
|
2318 | if (to_read > max_avail) { |
| 384 | 2206 | to_read = max_avail; | |
| 385 | } | ||
| 386 | |||
| 387 | 2318 | memcpy(buf, info->in_buf + info->in_pos, to_read); | |
| 388 | 2318 | info->in_pos += to_read; | |
| 389 | |||
| 390 | 2318 | return to_read; | |
| 391 | } | ||
| 392 | |||
| 393 | /* | ||
| 394 | * Receive expanded bytes from the PKWARE decoder callback. | ||
| 395 | * Output is clamped to the caller's capacity and the accepted byte count is | ||
| 396 | * recorded for the extraction wrapper after each decoder flush. | ||
| 397 | */ | ||
| 398 | static void | ||
| 399 | 1424 | data_write_output(char *buf, uint32_t *size, void *param) | |
| 400 | { | ||
| 401 | |||
| 402 | /* Destination state passed by the public decompression wrapper. */ | ||
| 403 | 1424 | pkzip_data_s *info = (pkzip_data_s *)param; | |
| 404 | 1424 | uint32_t max_write = (info->max_out - info->out_pos); | |
| 405 | 1424 | uint32_t to_write = *size; | |
| 406 | |||
| 407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1424 times.
|
1424 | if (to_write > max_write) { |
| 408 | ✗ | to_write = max_write; | |
| 409 | } | ||
| 410 | |||
| 411 | 1424 | memcpy(info->out_buf + info->out_pos, buf, to_write); | |
| 412 | 1424 | info->out_pos += to_write; | |
| 413 | 1424 | } | |
| 414 | |||
| 415 | /* | ||
| 416 | * Expand one complete PKWARE stream using its configured callbacks. | ||
| 417 | * The sliding 4 KiB window supplies LZ history while completed upper-half | ||
| 418 | * data is flushed incrementally through the output callback. | ||
| 419 | */ | ||
| 420 | static uint32_t | ||
| 421 | 1100 | expand(pkzip_cmp_s *mpq_pkzip) | |
| 422 | { | ||
| 423 | uint32_t copy_bytes; | ||
| 424 | uint32_t one_byte; | ||
| 425 | uint32_t result; | ||
| 426 | |||
| 427 | /* The lower half preserves history while the upper half is flushed to the caller. */ | ||
| 428 | 1100 | mpq_pkzip->out_pos = 0x1000; | |
| 429 | |||
| 430 |
2/2✓ Branch 1 taken 330689 times.
✓ Branch 2 taken 1099 times.
|
331788 | while ((result = one_byte = decode_literal(mpq_pkzip)) < 0x305) { |
| 431 | |||
| 432 | /* Values above 0x100 are LZ matches; lower values are literal bytes. */ | ||
| 433 |
2/2✓ Branch 0 taken 31392 times.
✓ Branch 1 taken 299297 times.
|
330689 | if (one_byte >= 0x100) { |
| 434 | uint8_t *source; | ||
| 435 | uint8_t *target; | ||
| 436 | |||
| 437 | /* Decoded match length and backward copy distance. */ | ||
| 438 | 31392 | uint32_t copy_length = one_byte - 0xFE; | |
| 439 | uint32_t move_back; | ||
| 440 | |||
| 441 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 31391 times.
|
31392 | if ((move_back = decode_distance(mpq_pkzip, copy_length)) == 0) { |
| 442 | 1 | result = 0x306; | |
| 443 | 1 | break; | |
| 444 | } | ||
| 445 | |||
| 446 | /* Copy from the sliding history window, allowing overlapping matches. */ | ||
| 447 | 31391 | target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos]; | |
| 448 | 31391 | source = target - move_back; | |
| 449 | 31391 | mpq_pkzip->out_pos += copy_length; | |
| 450 | |||
| 451 |
2/2✓ Branch 0 taken 1689224 times.
✓ Branch 1 taken 31391 times.
|
1720615 | while (copy_length-- > 0) { |
| 452 | 1689224 | *target++ = *source++; | |
| 453 | } | ||
| 454 | } else { | ||
| 455 | 299297 | mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (uint8_t)one_byte; | |
| 456 | } | ||
| 457 | |||
| 458 | /* Flush half the window while retaining the other half as match history. */ | ||
| 459 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 330364 times.
|
330688 | if (mpq_pkzip->out_pos >= 0x2000) { |
| 460 | 324 | copy_bytes = 0x1000; | |
| 461 | 324 | mpq_pkzip->write_buf( | |
| 462 | 324 | (char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param | |
| 463 | ); | ||
| 464 | |||
| 465 | 324 | memmove(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000); | |
| 466 | 324 | mpq_pkzip->out_pos -= 0x1000; | |
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | 1100 | copy_bytes = mpq_pkzip->out_pos - 0x1000; | |
| 471 | 1100 | mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); | |
| 472 | |||
| 473 | 1100 | return result; | |
| 474 | } | ||
| 475 | |||
| 476 | /* Bound match history and search work independently of the input size. */ | ||
| 477 | #define PKZIP_DICTIONARY_SIZE 4096u | ||
| 478 | #define PKZIP_MATCH_MAX 516u | ||
| 479 | #define PKZIP_SEARCH_MAX 256u | ||
| 480 | |||
| 481 | /* Hash chains retain absolute positions in a circular dictionary. */ | ||
| 482 | typedef struct | ||
| 483 | { | ||
| 484 | uint32_t head[PKZIP_DICTIONARY_SIZE]; | ||
| 485 | uint32_t previous[PKZIP_DICTIONARY_SIZE]; | ||
| 486 | } pkzip_match_s; | ||
| 487 | |||
| 488 | /* Hash a byte pair so two-byte matches remain discoverable. */ | ||
| 489 | static uint32_t | ||
| 490 | 2569038 | pair_hash(const uint8_t *data) | |
| 491 | { | ||
| 492 | 2569038 | return ((uint32_t)data[0] * 251u + data[1]) & (PKZIP_DICTIONARY_SIZE - 1u); | |
| 493 | } | ||
| 494 | |||
| 495 | /* Find the longest recent match, allowing copies to overlap their source. */ | ||
| 496 | static uint32_t | ||
| 497 | 626030 | find_match( | |
| 498 | const pkzip_match_s *history, const uint8_t *input, uint32_t size, uint32_t position, | ||
| 499 | uint32_t *distance | ||
| 500 | ) | ||
| 501 | { | ||
| 502 | 626030 | uint32_t limit = size - position; | |
| 503 | 626030 | uint32_t best = 1; | |
| 504 | uint32_t candidate; | ||
| 505 | 626030 | uint32_t probes = 0; | |
| 506 | |||
| 507 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 625805 times.
|
626030 | if (limit < 2) |
| 508 | 225 | return best; | |
| 509 |
2/2✓ Branch 0 taken 550120 times.
✓ Branch 1 taken 75685 times.
|
625805 | if (limit > PKZIP_MATCH_MAX) |
| 510 | 550120 | limit = PKZIP_MATCH_MAX; | |
| 511 | 625805 | candidate = history->head[pair_hash(input + position)]; | |
| 512 |
4/4✓ Branch 0 taken 1396405 times.
✓ Branch 1 taken 513085 times.
✓ Branch 2 taken 1284407 times.
✓ Branch 3 taken 111998 times.
|
1909490 | while (candidate != UINT32_MAX && position - candidate <= PKZIP_DICTIONARY_SIZE && |
| 513 |
2/2✓ Branch 0 taken 1284405 times.
✓ Branch 1 taken 2 times.
|
1284407 | probes++ < PKZIP_SEARCH_MAX) { |
| 514 | 1284405 | uint32_t length = 0; | |
| 515 | 1284405 | uint32_t back = position - candidate; | |
| 516 | |||
| 517 |
4/4✓ Branch 0 taken 5524044 times.
✓ Branch 1 taken 729 times.
✓ Branch 2 taken 4240368 times.
✓ Branch 3 taken 1283676 times.
|
5524773 | while (length < limit && input[candidate + length] == input[position + length]) |
| 518 | 4240368 | ++length; | |
| 519 | |||
| 520 | /* Length two has only two distance suffix bits, hence a 256-byte range. */ | ||
| 521 |
6/6✓ Branch 0 taken 56024 times.
✓ Branch 1 taken 1228381 times.
✓ Branch 2 taken 26665 times.
✓ Branch 3 taken 29359 times.
✓ Branch 4 taken 8576 times.
✓ Branch 5 taken 18089 times.
|
1284405 | if (length > best && (length > 2 || back <= 256u)) { |
| 522 | 37935 | best = length; | |
| 523 | 37935 | *distance = back; | |
| 524 |
2/2✓ Branch 0 taken 720 times.
✓ Branch 1 taken 37215 times.
|
37935 | if (best == limit) |
| 525 | 720 | break; | |
| 526 | } | ||
| 527 | 1283685 | candidate = history->previous[candidate & (PKZIP_DICTIONARY_SIZE - 1u)]; | |
| 528 | } | ||
| 529 | 625805 | return best; | |
| 530 | } | ||
| 531 | |||
| 532 | /* Encode binary input with general dictionary matches and the DCL terminator. */ | ||
| 533 | int32_t | ||
| 534 | 671 | libmpq__pkzip_compress( | |
| 535 | const uint8_t *in_buf, uint32_t in_size, uint8_t **out_buf, uint32_t *out_size | ||
| 536 | ) | ||
| 537 | { | ||
| 538 | 671 | uint64_t maximum_bits = (uint64_t)in_size * 9u + 16u; | |
| 539 | 671 | uint64_t maximum_bytes = 2u + (maximum_bits + 7u) / 8u; | |
| 540 | 671 | size_t bit_count = 0; | |
| 541 | pkzip_match_s *history; | ||
| 542 | uint8_t *out; | ||
| 543 | uint32_t i; | ||
| 544 | |||
| 545 |
5/8✓ Branch 0 taken 671 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 671 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 663 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 663 times.
|
671 | if (out_buf == NULL || out_size == NULL || (in_size != 0 && in_buf == NULL)) |
| 546 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
|
671 | if (maximum_bits > SIZE_MAX || maximum_bytes > UINT32_MAX || maximum_bytes > SIZE_MAX) |
| 548 | ✗ | return LIBMPQ_ERROR_SIZE; | |
| 549 | 671 | out = calloc(1, (size_t)maximum_bytes); | |
| 550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
|
671 | if (out == NULL) |
| 551 | ✗ | return LIBMPQ_ERROR_MALLOC; | |
| 552 | 671 | history = malloc(sizeof(*history)); | |
| 553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 671 times.
|
671 | if (history == NULL) { |
| 554 | ✗ | free(out); | |
| 555 | ✗ | return LIBMPQ_ERROR_MALLOC; | |
| 556 | } | ||
| 557 | 671 | memset(history, 0xff, sizeof(*history)); | |
| 558 | 671 | out[0] = LIBMPQ_PKZIP_CMP_BINARY; | |
| 559 | 671 | out[1] = 6; | |
| 560 | |||
| 561 | /* Six distance suffix bits select the full 4 KiB dictionary. */ | ||
| 562 |
2/2✓ Branch 0 taken 626030 times.
✓ Branch 1 taken 671 times.
|
626701 | for (i = 0; i < in_size;) { |
| 563 | 626030 | uint32_t distance = 0; | |
| 564 | 626030 | uint32_t match_length = find_match(history, in_buf, in_size, i, &distance); | |
| 565 | 626030 | uint32_t end = i + match_length; | |
| 566 | |||
| 567 |
2/2✓ Branch 0 taken 32863 times.
✓ Branch 1 taken 593167 times.
|
626030 | if (match_length >= 2) { |
| 568 | uint32_t value; | ||
| 569 | uint32_t entry; | ||
| 570 | uint32_t extra; | ||
| 571 | uint32_t code; | ||
| 572 |
2/2✓ Branch 0 taken 6035 times.
✓ Branch 1 taken 26828 times.
|
32863 | uint32_t suffix = match_length == 2 ? 2u : 6u; |
| 573 | 32863 | uint32_t encoded_distance = distance - 1u; | |
| 574 | 32863 | uint32_t prefix = encoded_distance >> suffix; | |
| 575 | 32863 | value = match_length - 2; | |
| 576 |
1/2✓ Branch 0 taken 220197 times.
✗ Branch 1 not taken.
|
220197 | for (entry = 0; entry < 16; entry++) { |
| 577 | 220197 | extra = pkzip_clen_bits[entry]; | |
| 578 |
3/4✓ Branch 0 taken 220197 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32863 times.
✓ Branch 3 taken 187334 times.
|
220197 | if (value >= pkzip_len_base[entry] && value < pkzip_len_base[entry] + (1u << extra)) |
| 579 | 32863 | break; | |
| 580 | } | ||
| 581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32863 times.
|
32863 | if (entry == 16) |
| 582 | ✗ | entry = 15; | |
| 583 | 32863 | code = ((value - pkzip_len_base[entry]) << (pkzip_slen_bits[entry] + 1)) | | |
| 584 | 32863 | (pkzip_len_code[entry] * 2u) | 1u; | |
| 585 | 32863 | pkzip_put_bits( | |
| 586 | 32863 | out + 2, &bit_count, code, pkzip_slen_bits[entry] + pkzip_clen_bits[entry] + 1 | |
| 587 | ); | ||
| 588 | |||
| 589 | 32863 | pkzip_put_bits(out + 2, &bit_count, pkzip_dist_code[prefix], pkzip_dist_bits[prefix]); | |
| 590 | 32863 | pkzip_put_bits(out + 2, &bit_count, encoded_distance & ((1u << suffix) - 1u), suffix); | |
| 591 | } else { | ||
| 592 | 593167 | pkzip_put_bits(out + 2, &bit_count, 0, 1); | |
| 593 | 593167 | pkzip_put_bits(out + 2, &bit_count, in_buf[i], 8); | |
| 594 | } | ||
| 595 | |||
| 596 | /* Index every consumed position, including positions inside a match. */ | ||
| 597 |
2/2✓ Branch 0 taken 1943896 times.
✓ Branch 1 taken 626030 times.
|
2569926 | for (; i < end; ++i) { |
| 598 |
2/2✓ Branch 0 taken 1943233 times.
✓ Branch 1 taken 663 times.
|
1943896 | if (in_size - i >= 2) { |
| 599 | 1943233 | uint32_t hash = pair_hash(in_buf + i); | |
| 600 | |||
| 601 | 1943233 | history->previous[i & (PKZIP_DICTIONARY_SIZE - 1u)] = history->head[hash]; | |
| 602 | 1943233 | history->head[hash] = i; | |
| 603 | } | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | /* Length table 15, extra value 255: the canonical 0x305 terminator. */ | ||
| 608 | 671 | pkzip_put_bits(out + 2, &bit_count, 0xFF01u, 16); | |
| 609 | 671 | free(history); | |
| 610 | 671 | *out_buf = out; | |
| 611 | 671 | *out_size = (uint32_t)(2 + (bit_count + 7) / 8); | |
| 612 | 671 | return 0; | |
| 613 | } | ||
| 614 | |||
| 615 | /* PKWARE copyright banner kept for parity with the original implementation. */ | ||
| 616 | char pkware_copyright[] = "PKWARE Data Compression Library for Win32\r\n" | ||
| 617 | "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" | ||
| 618 | "Patent No. 5,051,745\r\n" | ||
| 619 | "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" | ||
| 620 | "Version 1.11\r\n"; | ||
| 621 | |||
| 622 | /* | ||
| 623 | * Initialize PKWARE decoder state and explode the compressed data stream. | ||
| 624 | * The caller owns the work buffer and callback parameter; this routine fills | ||
| 625 | * the codec state, validates the stream header, and delegates expansion. | ||
| 626 | */ | ||
| 627 | uint32_t | ||
| 628 | 1106 | libmpq__pkzip_decompress(uint8_t *work_buf, void *param) | |
| 629 | { | ||
| 630 | |||
| 631 | /* Caller-provided work buffer interpreted as PKWARE decoder state. */ | ||
| 632 | 1106 | pkzip_cmp_s *mpq_pkzip = (pkzip_cmp_s *)work_buf; | |
| 633 | |||
| 634 | 1106 | memset(mpq_pkzip, 0, sizeof(pkzip_cmp_s)); | |
| 635 | |||
| 636 | 1106 | mpq_pkzip->read_buf = data_read_input; | |
| 637 | 1106 | mpq_pkzip->write_buf = data_write_output; | |
| 638 | 1106 | mpq_pkzip->param = param; | |
| 639 | 1106 | mpq_pkzip->in_pos = 0; | |
| 640 | |||
| 641 | 1106 | uint32_t in_size = sizeof(mpq_pkzip->in_buf); | |
| 642 | 1106 | mpq_pkzip->in_bytes = | |
| 643 | 1106 | mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &in_size, mpq_pkzip->param); | |
| 644 | |||
| 645 | /* An empty stream needs only the two-byte header and its end marker. */ | ||
| 646 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1102 times.
|
1106 | if (mpq_pkzip->in_bytes < 4) { |
| 647 | 4 | return LIBMPQ_PKZIP_CMP_BAD_DATA; | |
| 648 | } | ||
| 649 | |||
| 650 | /* The two-byte header selects literal mode and dictionary width. */ | ||
| 651 | 1102 | mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; | |
| 652 | 1102 | mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; | |
| 653 | 1102 | mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; | |
| 654 | 1102 | mpq_pkzip->extra_bits = 0; | |
| 655 | 1102 | mpq_pkzip->in_pos = 3; | |
| 656 | |||
| 657 |
3/4✓ Branch 0 taken 1101 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1101 times.
|
1102 | if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) { |
| 658 | 1 | return LIBMPQ_PKZIP_CMP_INV_DICTSIZE; | |
| 659 | } | ||
| 660 | |||
| 661 | /* Mask the variable-width distance suffix for the selected dictionary size. */ | ||
| 662 | 1101 | mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); | |
| 663 | |||
| 664 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1100 times.
|
1101 | if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) { |
| 665 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) { |
| 666 | 1 | return LIBMPQ_PKZIP_CMP_INV_MODE; | |
| 667 | } | ||
| 668 | |||
| 669 | ✗ | memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc)); | |
| 670 | ✗ | generate_tables_ascii(mpq_pkzip); | |
| 671 | } | ||
| 672 | |||
| 673 | /* Build lookup tables for copy lengths, distances and optional ASCII literals. */ | ||
| 674 | 1100 | memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits)); | |
| 675 | 1100 | generate_tables_decode(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2); | |
| 676 | |||
| 677 | 1100 | memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits)); | |
| 678 | 1100 | memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base)); | |
| 679 | 1100 | memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits)); | |
| 680 | 1100 | generate_tables_decode(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1); | |
| 681 | |||
| 682 |
2/2✓ Branch 1 taken 1098 times.
✓ Branch 2 taken 2 times.
|
1100 | if (expand(mpq_pkzip) != 0x306) { |
| 683 | 1098 | return LIBMPQ_PKZIP_CMP_NO_ERROR; | |
| 684 | } | ||
| 685 | |||
| 686 | 2 | return LIBMPQ_PKZIP_CMP_ABORT; | |
| 687 | } | ||
| 688 |