libmspack 0.0.5 → 0.10.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/rake.yml +37 -0
- data/.gitignore +2 -0
- data/.yardopts +1 -1
- data/README.md +1 -1
- data/Rakefile +11 -5
- data/ext/Rakefile +1 -1
- data/ext/libmspack/AUTHORS +1 -0
- data/ext/libmspack/ChangeLog +321 -4
- data/ext/libmspack/INSTALL +368 -0
- data/ext/libmspack/Makefile.am +86 -95
- data/ext/libmspack/Makefile.in +1729 -0
- data/ext/libmspack/README +30 -30
- data/ext/libmspack/acinclude.m4 +99 -0
- data/ext/libmspack/aclocal.m4 +1218 -0
- data/ext/libmspack/ar-lib +270 -0
- data/ext/libmspack/compile +347 -0
- data/ext/libmspack/config.guess +1480 -0
- data/ext/libmspack/config.h.in +129 -0
- data/ext/libmspack/config.sub +1801 -0
- data/ext/libmspack/configure +15487 -0
- data/ext/libmspack/configure.ac +11 -13
- data/ext/libmspack/depcomp +791 -0
- data/ext/libmspack/install-sh +508 -0
- data/ext/libmspack/libmscabd.la +41 -0
- data/ext/libmspack/libmschmd.la +41 -0
- data/ext/libmspack/libmspack.la +41 -0
- data/ext/libmspack/ltmain.sh +11156 -0
- data/ext/libmspack/m4/libtool.m4 +8387 -0
- data/ext/libmspack/m4/ltoptions.m4 +437 -0
- data/ext/libmspack/m4/ltsugar.m4 +124 -0
- data/ext/libmspack/m4/ltversion.m4 +23 -0
- data/ext/libmspack/m4/lt~obsolete.m4 +99 -0
- data/ext/libmspack/missing +215 -0
- data/ext/libmspack/mspack/cab.h +20 -7
- data/ext/libmspack/mspack/cabd.c +301 -236
- data/ext/libmspack/mspack/chmd.c +304 -319
- data/ext/libmspack/mspack/crc32.c +52 -52
- data/ext/libmspack/mspack/crc32.h +1 -1
- data/ext/libmspack/mspack/kwajd.c +178 -172
- data/ext/libmspack/mspack/lzss.h +4 -4
- data/ext/libmspack/mspack/lzssd.c +42 -42
- data/ext/libmspack/mspack/lzx.h +11 -11
- data/ext/libmspack/mspack/lzxd.c +370 -361
- data/ext/libmspack/mspack/mspack.h +109 -77
- data/ext/libmspack/mspack/mszip.h +6 -6
- data/ext/libmspack/mspack/mszipd.c +140 -139
- data/ext/libmspack/mspack/oab.h +1 -0
- data/ext/libmspack/mspack/oabd.c +71 -73
- data/ext/libmspack/mspack/qtm.h +4 -4
- data/ext/libmspack/mspack/qtmd.c +118 -117
- data/ext/libmspack/mspack/readbits.h +52 -52
- data/ext/libmspack/mspack/readhuff.h +61 -61
- data/ext/libmspack/mspack/system.c +15 -9
- data/ext/libmspack/mspack/system.h +38 -50
- data/ext/libmspack/mspack/szddd.c +35 -35
- data/ext/libmspack/test-driver +148 -0
- data/ext/x86_64-linux/libmspack.so +0 -0
- data/ext/x86_64-windows/mspack.dll +0 -0
- data/lib/libmspack/version.rb +2 -1
- data/lib/libmspack.rb +1 -1
- data/libmspack.gemspec +4 -4
- data/spec/libmspack_spec.rb +5 -4
- metadata +38 -105
- data/.travis.yml +0 -5
- data/ext/i386-windows/libmspack.dll +0 -0
- data/ext/libmspack/cleanup.sh +0 -9
- data/ext/libmspack/debian/changelog +0 -6
- data/ext/libmspack/debian/control +0 -14
- data/ext/libmspack/debian/rules +0 -101
- data/ext/libmspack/doc/Doxyfile.in +0 -22
- data/ext/libmspack/doc/Makefile.in +0 -14
- data/ext/libmspack/doc/szdd_kwaj_format.html +0 -331
- data/ext/libmspack/mspack/mspack.def +0 -28
- data/ext/libmspack/mspack/qtmc.c +0 -18
- data/ext/libmspack/rebuild.sh +0 -8
- data/ext/libmspack/test/cabd_c10 +0 -19
- data/ext/libmspack/test/cabd_compare +0 -34
- data/ext/libmspack/test/cabd_md5.c +0 -161
- data/ext/libmspack/test/cabd_memory.c +0 -179
- data/ext/libmspack/test/cabd_test.c +0 -386
- data/ext/libmspack/test/cabrip.c +0 -81
- data/ext/libmspack/test/chmd_compare +0 -38
- data/ext/libmspack/test/chmd_find.c +0 -95
- data/ext/libmspack/test/chmd_md5.c +0 -67
- data/ext/libmspack/test/chmd_order.c +0 -144
- data/ext/libmspack/test/chminfo.c +0 -284
- data/ext/libmspack/test/chmx.c +0 -216
- data/ext/libmspack/test/error.h +0 -22
- data/ext/libmspack/test/expand.c +0 -79
- data/ext/libmspack/test/md5.c +0 -457
- data/ext/libmspack/test/md5.h +0 -165
- data/ext/libmspack/test/md5_fh.h +0 -123
- data/ext/libmspack/test/msdecompile_md5 +0 -24
- data/ext/libmspack/test/msexpand_md5 +0 -39
- data/ext/libmspack/test/multifh.c +0 -435
- data/ext/libmspack/test/oabx.c +0 -41
- data/ext/libmspack/test/test_files/cabd/1.pl +0 -84
- data/ext/libmspack/test/test_files/cabd/2.pl +0 -75
- data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
- data/ext/libmspack/winbuild.sh +0 -26
- data/ext/libmspack.h +0 -259
- data/ext/x86_64-windows/libmspack.dll +0 -0
data/ext/libmspack/mspack/lzxd.c
CHANGED
@@ -83,11 +83,11 @@
|
|
83
83
|
#define BITS_TYPE struct lzxd_stream
|
84
84
|
#define BITS_VAR lzx
|
85
85
|
#define BITS_ORDER_MSB
|
86
|
-
#define READ_BYTES do {
|
87
|
-
unsigned char b0, b1;
|
88
|
-
READ_IF_NEEDED; b0 = *i_ptr++;
|
89
|
-
READ_IF_NEEDED; b1 = *i_ptr++;
|
90
|
-
INJECT_BITS((b1 << 8) | b0, 16);
|
86
|
+
#define READ_BYTES do { \
|
87
|
+
unsigned char b0, b1; \
|
88
|
+
READ_IF_NEEDED; b0 = *i_ptr++; \
|
89
|
+
READ_IF_NEEDED; b1 = *i_ptr++; \
|
90
|
+
INJECT_BITS((b1 << 8) | b0, 16); \
|
91
91
|
} while (0)
|
92
92
|
#include <readbits.h>
|
93
93
|
|
@@ -100,43 +100,43 @@
|
|
100
100
|
#include <readhuff.h>
|
101
101
|
|
102
102
|
/* BUILD_TABLE(tbl) builds a huffman lookup table from code lengths */
|
103
|
-
#define BUILD_TABLE(tbl)
|
104
|
-
if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl),
|
105
|
-
|
106
|
-
{
|
107
|
-
D(("failed to build %s table", #tbl))
|
108
|
-
|
103
|
+
#define BUILD_TABLE(tbl) \
|
104
|
+
if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
|
105
|
+
&HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
|
106
|
+
{ \
|
107
|
+
D(("failed to build %s table", #tbl)) \
|
108
|
+
return lzx->error = MSPACK_ERR_DECRUNCH; \
|
109
109
|
}
|
110
110
|
|
111
|
-
#define BUILD_TABLE_MAYBE_EMPTY(tbl) do {
|
112
|
-
lzx->tbl##_empty = 0;
|
113
|
-
if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl),
|
114
|
-
&HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0)))
|
115
|
-
{
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
}
|
111
|
+
#define BUILD_TABLE_MAYBE_EMPTY(tbl) do { \
|
112
|
+
lzx->tbl##_empty = 0; \
|
113
|
+
if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
|
114
|
+
&HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
|
115
|
+
{ \
|
116
|
+
for (i = 0; i < MAXSYMBOLS(tbl); i++) { \
|
117
|
+
if (HUFF_LEN(tbl, i) > 0) { \
|
118
|
+
D(("failed to build %s table", #tbl)) \
|
119
|
+
return lzx->error = MSPACK_ERR_DECRUNCH; \
|
120
|
+
} \
|
121
|
+
} \
|
122
|
+
/* empty tree - allow it, but don't decode symbols with it */ \
|
123
|
+
lzx->tbl##_empty = 1; \
|
124
|
+
} \
|
125
125
|
} while (0)
|
126
126
|
|
127
127
|
/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
|
128
128
|
* first to last in the given table. The code lengths are stored in their
|
129
129
|
* own special LZX way.
|
130
130
|
*/
|
131
|
-
#define READ_LENGTHS(tbl, first, last) do {
|
132
|
-
STORE_BITS;
|
133
|
-
if (lzxd_read_lens(lzx, &HUFF_LEN(tbl, 0), (first),
|
134
|
-
(unsigned int)(last))) return lzx->error;
|
135
|
-
RESTORE_BITS;
|
131
|
+
#define READ_LENGTHS(tbl, first, last) do { \
|
132
|
+
STORE_BITS; \
|
133
|
+
if (lzxd_read_lens(lzx, &HUFF_LEN(tbl, 0), (first), \
|
134
|
+
(unsigned int)(last))) return lzx->error; \
|
135
|
+
RESTORE_BITS; \
|
136
136
|
} while (0)
|
137
137
|
|
138
138
|
static int lzxd_read_lens(struct lzxd_stream *lzx, unsigned char *lens,
|
139
|
-
|
139
|
+
unsigned int first, unsigned int last)
|
140
140
|
{
|
141
141
|
/* bit buffer and huffman symbol decode variables */
|
142
142
|
register unsigned int bit_buffer;
|
@@ -277,13 +277,13 @@ static void lzxd_reset_state(struct lzxd_stream *lzx) {
|
|
277
277
|
/*-------- main LZX code --------*/
|
278
278
|
|
279
279
|
struct lzxd_stream *lzxd_init(struct mspack_system *system,
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
280
|
+
struct mspack_file *input,
|
281
|
+
struct mspack_file *output,
|
282
|
+
int window_bits,
|
283
|
+
int reset_interval,
|
284
|
+
int input_buffer_size,
|
285
|
+
off_t output_length,
|
286
|
+
char is_delta)
|
287
287
|
{
|
288
288
|
unsigned int window_size = 1 << window_bits;
|
289
289
|
struct lzxd_stream *lzx;
|
@@ -300,8 +300,14 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
|
|
300
300
|
if (window_bits < 15 || window_bits > 21) return NULL;
|
301
301
|
}
|
302
302
|
|
303
|
+
if (reset_interval < 0 || output_length < 0) {
|
304
|
+
D(("reset interval or output length < 0"))
|
305
|
+
return NULL;
|
306
|
+
}
|
307
|
+
|
308
|
+
/* round up input buffer size to multiple of two */
|
303
309
|
input_buffer_size = (input_buffer_size + 1) & -2;
|
304
|
-
if (
|
310
|
+
if (input_buffer_size < 2) return NULL;
|
305
311
|
|
306
312
|
/* allocate decompression state */
|
307
313
|
if (!(lzx = (struct lzxd_stream *) system->alloc(system, sizeof(struct lzxd_stream)))) {
|
@@ -346,9 +352,9 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
|
|
346
352
|
}
|
347
353
|
|
348
354
|
int lzxd_set_reference_data(struct lzxd_stream *lzx,
|
349
|
-
|
350
|
-
|
351
|
-
|
355
|
+
struct mspack_system *system,
|
356
|
+
struct mspack_file *input,
|
357
|
+
unsigned int length)
|
352
358
|
{
|
353
359
|
if (!lzx) return MSPACK_ERR_ARGS;
|
354
360
|
|
@@ -357,12 +363,12 @@ int lzxd_set_reference_data(struct lzxd_stream *lzx,
|
|
357
363
|
return MSPACK_ERR_ARGS;
|
358
364
|
}
|
359
365
|
if (lzx->offset) {
|
360
|
-
|
361
|
-
|
366
|
+
D(("too late to set reference data after decoding starts"))
|
367
|
+
return MSPACK_ERR_ARGS;
|
362
368
|
}
|
363
369
|
if (length > lzx->window_size) {
|
364
|
-
|
365
|
-
|
370
|
+
D(("reference length (%u) is longer than the window", length))
|
371
|
+
return MSPACK_ERR_ARGS;
|
366
372
|
}
|
367
373
|
if (length > 0 && (!system || !input)) {
|
368
374
|
D(("length > 0 but no system or input"))
|
@@ -373,16 +379,16 @@ int lzxd_set_reference_data(struct lzxd_stream *lzx,
|
|
373
379
|
if (length > 0) {
|
374
380
|
/* copy reference data */
|
375
381
|
unsigned char *pos = &lzx->window[lzx->window_size - length];
|
376
|
-
|
382
|
+
int bytes = system->read(input, pos, length);
|
377
383
|
/* length can't be more than 2^25, so no signedness problem */
|
378
|
-
|
384
|
+
if (bytes < (int)length) return MSPACK_ERR_READ;
|
379
385
|
}
|
380
386
|
lzx->ref_data_size = length;
|
381
387
|
return MSPACK_ERR_OK;
|
382
388
|
}
|
383
389
|
|
384
390
|
void lzxd_set_output_length(struct lzxd_stream *lzx, off_t out_bytes) {
|
385
|
-
if (lzx) lzx->length = out_bytes;
|
391
|
+
if (lzx && out_bytes > 0) lzx->length = out_bytes;
|
386
392
|
}
|
387
393
|
|
388
394
|
int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
@@ -393,7 +399,7 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
393
399
|
register unsigned short sym;
|
394
400
|
|
395
401
|
int match_length, length_footer, extra, verbatim_bits, bytes_todo;
|
396
|
-
int this_run, main_element, aligned_bits, j;
|
402
|
+
int this_run, main_element, aligned_bits, j, warned = 0;
|
397
403
|
unsigned char *window, *runsrc, *rundest, buf[12];
|
398
404
|
unsigned int frame_size=0, end_frame, match_offset, window_posn;
|
399
405
|
unsigned int R0, R1, R2;
|
@@ -429,8 +435,12 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
429
435
|
/* have we reached the reset interval? (if there is one?) */
|
430
436
|
if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) {
|
431
437
|
if (lzx->block_remaining) {
|
432
|
-
|
433
|
-
|
438
|
+
/* this is a file format error, we can make a best effort to extract what we can */
|
439
|
+
D(("%d bytes remaining at reset interval", lzx->block_remaining))
|
440
|
+
if (!warned) {
|
441
|
+
lzx->sys->message(NULL, "WARNING; invalid reset interval detected during LZX decompression");
|
442
|
+
warned++;
|
443
|
+
}
|
434
444
|
}
|
435
445
|
|
436
446
|
/* re-read the intel header and reset the huffman lengths */
|
@@ -468,62 +478,61 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
468
478
|
while (bytes_todo > 0) {
|
469
479
|
/* initialise new block, if one is needed */
|
470
480
|
if (lzx->block_remaining == 0) {
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
}
|
481
|
+
/* realign if previous block was an odd-sized UNCOMPRESSED block */
|
482
|
+
if ((lzx->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) &&
|
483
|
+
(lzx->block_length & 1))
|
484
|
+
{
|
485
|
+
READ_IF_NEEDED;
|
486
|
+
i_ptr++;
|
487
|
+
}
|
488
|
+
|
489
|
+
/* read block type (3 bits) and block length (24 bits) */
|
490
|
+
READ_BITS(lzx->block_type, 3);
|
491
|
+
READ_BITS(i, 16); READ_BITS(j, 8);
|
492
|
+
lzx->block_remaining = lzx->block_length = (i << 8) | j;
|
493
|
+
/*D(("new block t%d len %u", lzx->block_type, lzx->block_length))*/
|
494
|
+
|
495
|
+
/* read individual block headers */
|
496
|
+
switch (lzx->block_type) {
|
497
|
+
case LZX_BLOCKTYPE_ALIGNED:
|
498
|
+
/* read lengths of and build aligned huffman decoding tree */
|
499
|
+
for (i = 0; i < 8; i++) { READ_BITS(j, 3); lzx->ALIGNED_len[i] = j; }
|
500
|
+
BUILD_TABLE(ALIGNED);
|
501
|
+
/* rest of aligned header is same as verbatim */ /*@fallthrough@*/
|
502
|
+
case LZX_BLOCKTYPE_VERBATIM:
|
503
|
+
/* read lengths of and build main huffman decoding tree */
|
504
|
+
READ_LENGTHS(MAINTREE, 0, 256);
|
505
|
+
READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx->num_offsets);
|
506
|
+
BUILD_TABLE(MAINTREE);
|
507
|
+
/* if the literal 0xE8 is anywhere in the block... */
|
508
|
+
if (lzx->MAINTREE_len[0xE8] != 0) lzx->intel_started = 1;
|
509
|
+
/* read lengths of and build lengths huffman decoding tree */
|
510
|
+
READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS);
|
511
|
+
BUILD_TABLE_MAYBE_EMPTY(LENGTH);
|
512
|
+
break;
|
513
|
+
|
514
|
+
case LZX_BLOCKTYPE_UNCOMPRESSED:
|
515
|
+
/* because we can't assume otherwise */
|
516
|
+
lzx->intel_started = 1;
|
517
|
+
|
518
|
+
/* read 1-16 (not 0-15) bits to align to bytes */
|
519
|
+
if (bits_left == 0) ENSURE_BITS(16);
|
520
|
+
bits_left = 0; bit_buffer = 0;
|
521
|
+
|
522
|
+
/* read 12 bytes of stored R0 / R1 / R2 values */
|
523
|
+
for (rundest = &buf[0], i = 0; i < 12; i++) {
|
524
|
+
READ_IF_NEEDED;
|
525
|
+
*rundest++ = *i_ptr++;
|
526
|
+
}
|
527
|
+
R0 = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
528
|
+
R1 = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
|
529
|
+
R2 = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
|
530
|
+
break;
|
531
|
+
|
532
|
+
default:
|
533
|
+
D(("bad block type"))
|
534
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
535
|
+
}
|
527
536
|
}
|
528
537
|
|
529
538
|
/* decode more of the block:
|
@@ -538,270 +547,270 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
538
547
|
/* decode at least this_run bytes */
|
539
548
|
switch (lzx->block_type) {
|
540
549
|
case LZX_BLOCKTYPE_VERBATIM:
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
550
|
+
while (this_run > 0) {
|
551
|
+
READ_HUFFSYM(MAINTREE, main_element);
|
552
|
+
if (main_element < LZX_NUM_CHARS) {
|
553
|
+
/* literal: 0 to LZX_NUM_CHARS-1 */
|
554
|
+
window[window_posn++] = main_element;
|
555
|
+
this_run--;
|
556
|
+
}
|
557
|
+
else {
|
558
|
+
/* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
|
559
|
+
main_element -= LZX_NUM_CHARS;
|
560
|
+
|
561
|
+
/* get match length */
|
562
|
+
match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
|
563
|
+
if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
|
564
|
+
if (lzx->LENGTH_empty) {
|
556
565
|
D(("LENGTH symbol needed but tree is empty"))
|
557
566
|
return lzx->error = MSPACK_ERR_DECRUNCH;
|
558
567
|
}
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
568
|
+
READ_HUFFSYM(LENGTH, length_footer);
|
569
|
+
match_length += length_footer;
|
570
|
+
}
|
571
|
+
match_length += LZX_MIN_MATCH;
|
572
|
+
|
573
|
+
/* get match offset */
|
574
|
+
switch ((match_offset = (main_element >> 3))) {
|
575
|
+
case 0: match_offset = R0; break;
|
576
|
+
case 1: match_offset = R1; R1=R0; R0 = match_offset; break;
|
577
|
+
case 2: match_offset = R2; R2=R0; R0 = match_offset; break;
|
578
|
+
case 3: match_offset = 1; R2=R1; R1=R0; R0 = match_offset; break;
|
579
|
+
default:
|
580
|
+
extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
|
581
|
+
READ_BITS(verbatim_bits, extra);
|
582
|
+
match_offset = position_base[match_offset] - 2 + verbatim_bits;
|
583
|
+
R2 = R1; R1 = R0; R0 = match_offset;
|
584
|
+
}
|
585
|
+
|
586
|
+
/* LZX DELTA uses max match length to signal even longer match */
|
587
|
+
if (match_length == LZX_MAX_MATCH && lzx->is_delta) {
|
588
|
+
int extra_len = 0;
|
589
|
+
ENSURE_BITS(3); /* 4 entry huffman tree */
|
590
|
+
if (PEEK_BITS(1) == 0) {
|
591
|
+
REMOVE_BITS(1); /* '0' -> 8 extra length bits */
|
592
|
+
READ_BITS(extra_len, 8);
|
593
|
+
}
|
594
|
+
else if (PEEK_BITS(2) == 2) {
|
595
|
+
REMOVE_BITS(2); /* '10' -> 10 extra length bits + 0x100 */
|
596
|
+
READ_BITS(extra_len, 10);
|
597
|
+
extra_len += 0x100;
|
598
|
+
}
|
599
|
+
else if (PEEK_BITS(3) == 6) {
|
600
|
+
REMOVE_BITS(3); /* '110' -> 12 extra length bits + 0x500 */
|
601
|
+
READ_BITS(extra_len, 12);
|
602
|
+
extra_len += 0x500;
|
603
|
+
}
|
604
|
+
else {
|
605
|
+
REMOVE_BITS(3); /* '111' -> 15 extra length bits */
|
606
|
+
READ_BITS(extra_len, 15);
|
607
|
+
}
|
608
|
+
match_length += extra_len;
|
609
|
+
}
|
610
|
+
|
611
|
+
if ((window_posn + match_length) > lzx->window_size) {
|
612
|
+
D(("match ran over window wrap"))
|
613
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
614
|
+
}
|
615
|
+
|
616
|
+
/* copy match */
|
617
|
+
rundest = &window[window_posn];
|
618
|
+
i = match_length;
|
619
|
+
/* does match offset wrap the window? */
|
620
|
+
if (match_offset > window_posn) {
|
621
|
+
if (match_offset > lzx->offset &&
|
622
|
+
(match_offset - window_posn) > lzx->ref_data_size)
|
623
|
+
{
|
624
|
+
D(("match offset beyond LZX stream"))
|
625
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
626
|
+
}
|
627
|
+
/* j = length from match offset to end of window */
|
628
|
+
j = match_offset - window_posn;
|
629
|
+
if (j > (int) lzx->window_size) {
|
630
|
+
D(("match offset beyond window boundaries"))
|
631
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
632
|
+
}
|
633
|
+
runsrc = &window[lzx->window_size - j];
|
634
|
+
if (j < i) {
|
635
|
+
/* if match goes over the window edge, do two copy runs */
|
636
|
+
i -= j; while (j-- > 0) *rundest++ = *runsrc++;
|
637
|
+
runsrc = window;
|
638
|
+
}
|
639
|
+
while (i-- > 0) *rundest++ = *runsrc++;
|
640
|
+
}
|
641
|
+
else {
|
642
|
+
runsrc = rundest - match_offset;
|
643
|
+
while (i-- > 0) *rundest++ = *runsrc++;
|
644
|
+
}
|
645
|
+
|
646
|
+
this_run -= match_length;
|
647
|
+
window_posn += match_length;
|
648
|
+
}
|
649
|
+
} /* while (this_run > 0) */
|
650
|
+
break;
|
642
651
|
|
643
652
|
case LZX_BLOCKTYPE_ALIGNED:
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
653
|
+
while (this_run > 0) {
|
654
|
+
READ_HUFFSYM(MAINTREE, main_element);
|
655
|
+
if (main_element < LZX_NUM_CHARS) {
|
656
|
+
/* literal: 0 to LZX_NUM_CHARS-1 */
|
657
|
+
window[window_posn++] = main_element;
|
658
|
+
this_run--;
|
659
|
+
}
|
660
|
+
else {
|
661
|
+
/* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
|
662
|
+
main_element -= LZX_NUM_CHARS;
|
663
|
+
|
664
|
+
/* get match length */
|
665
|
+
match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
|
666
|
+
if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
|
658
667
|
if (lzx->LENGTH_empty) {
|
659
668
|
D(("LENGTH symbol needed but tree is empty"))
|
660
669
|
return lzx->error = MSPACK_ERR_DECRUNCH;
|
661
670
|
}
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
671
|
+
READ_HUFFSYM(LENGTH, length_footer);
|
672
|
+
match_length += length_footer;
|
673
|
+
}
|
674
|
+
match_length += LZX_MIN_MATCH;
|
675
|
+
|
676
|
+
/* get match offset */
|
677
|
+
switch ((match_offset = (main_element >> 3))) {
|
678
|
+
case 0: match_offset = R0; break;
|
679
|
+
case 1: match_offset = R1; R1 = R0; R0 = match_offset; break;
|
680
|
+
case 2: match_offset = R2; R2 = R0; R0 = match_offset; break;
|
681
|
+
default:
|
682
|
+
extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
|
683
|
+
match_offset = position_base[match_offset] - 2;
|
684
|
+
if (extra > 3) {
|
685
|
+
/* verbatim and aligned bits */
|
686
|
+
extra -= 3;
|
687
|
+
READ_BITS(verbatim_bits, extra);
|
688
|
+
match_offset += (verbatim_bits << 3);
|
689
|
+
READ_HUFFSYM(ALIGNED, aligned_bits);
|
690
|
+
match_offset += aligned_bits;
|
691
|
+
}
|
692
|
+
else if (extra == 3) {
|
693
|
+
/* aligned bits only */
|
694
|
+
READ_HUFFSYM(ALIGNED, aligned_bits);
|
695
|
+
match_offset += aligned_bits;
|
696
|
+
}
|
697
|
+
else if (extra > 0) { /* extra==1, extra==2 */
|
698
|
+
/* verbatim bits only */
|
699
|
+
READ_BITS(verbatim_bits, extra);
|
700
|
+
match_offset += verbatim_bits;
|
701
|
+
}
|
702
|
+
else /* extra == 0 */ {
|
703
|
+
/* ??? not defined in LZX specification! */
|
704
|
+
match_offset = 1;
|
705
|
+
}
|
706
|
+
/* update repeated offset LRU queue */
|
707
|
+
R2 = R1; R1 = R0; R0 = match_offset;
|
708
|
+
}
|
709
|
+
|
710
|
+
/* LZX DELTA uses max match length to signal even longer match */
|
711
|
+
if (match_length == LZX_MAX_MATCH && lzx->is_delta) {
|
712
|
+
int extra_len = 0;
|
713
|
+
ENSURE_BITS(3); /* 4 entry huffman tree */
|
714
|
+
if (PEEK_BITS(1) == 0) {
|
715
|
+
REMOVE_BITS(1); /* '0' -> 8 extra length bits */
|
716
|
+
READ_BITS(extra_len, 8);
|
717
|
+
}
|
718
|
+
else if (PEEK_BITS(2) == 2) {
|
719
|
+
REMOVE_BITS(2); /* '10' -> 10 extra length bits + 0x100 */
|
720
|
+
READ_BITS(extra_len, 10);
|
721
|
+
extra_len += 0x100;
|
722
|
+
}
|
723
|
+
else if (PEEK_BITS(3) == 6) {
|
724
|
+
REMOVE_BITS(3); /* '110' -> 12 extra length bits + 0x500 */
|
725
|
+
READ_BITS(extra_len, 12);
|
726
|
+
extra_len += 0x500;
|
727
|
+
}
|
728
|
+
else {
|
729
|
+
REMOVE_BITS(3); /* '111' -> 15 extra length bits */
|
730
|
+
READ_BITS(extra_len, 15);
|
731
|
+
}
|
732
|
+
match_length += extra_len;
|
733
|
+
}
|
734
|
+
|
735
|
+
if ((window_posn + match_length) > lzx->window_size) {
|
736
|
+
D(("match ran over window wrap"))
|
737
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
738
|
+
}
|
739
|
+
|
740
|
+
/* copy match */
|
741
|
+
rundest = &window[window_posn];
|
742
|
+
i = match_length;
|
743
|
+
/* does match offset wrap the window? */
|
744
|
+
if (match_offset > window_posn) {
|
745
|
+
if (match_offset > lzx->offset &&
|
746
|
+
(match_offset - window_posn) > lzx->ref_data_size)
|
747
|
+
{
|
748
|
+
D(("match offset beyond LZX stream"))
|
749
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
750
|
+
}
|
751
|
+
/* j = length from match offset to end of window */
|
752
|
+
j = match_offset - window_posn;
|
753
|
+
if (j > (int) lzx->window_size) {
|
754
|
+
D(("match offset beyond window boundaries"))
|
755
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
756
|
+
}
|
757
|
+
runsrc = &window[lzx->window_size - j];
|
758
|
+
if (j < i) {
|
759
|
+
/* if match goes over the window edge, do two copy runs */
|
760
|
+
i -= j; while (j-- > 0) *rundest++ = *runsrc++;
|
761
|
+
runsrc = window;
|
762
|
+
}
|
763
|
+
while (i-- > 0) *rundest++ = *runsrc++;
|
764
|
+
}
|
765
|
+
else {
|
766
|
+
runsrc = rundest - match_offset;
|
767
|
+
while (i-- > 0) *rundest++ = *runsrc++;
|
768
|
+
}
|
769
|
+
|
770
|
+
this_run -= match_length;
|
771
|
+
window_posn += match_length;
|
772
|
+
}
|
773
|
+
} /* while (this_run > 0) */
|
774
|
+
break;
|
766
775
|
|
767
776
|
case LZX_BLOCKTYPE_UNCOMPRESSED:
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
777
|
+
/* as this_run is limited not to wrap a frame, this also means it
|
778
|
+
* won't wrap the window (as the window is a multiple of 32k) */
|
779
|
+
rundest = &window[window_posn];
|
780
|
+
window_posn += this_run;
|
781
|
+
while (this_run > 0) {
|
782
|
+
if ((i = i_end - i_ptr) == 0) {
|
783
|
+
READ_IF_NEEDED;
|
784
|
+
}
|
785
|
+
else {
|
786
|
+
if (i > this_run) i = this_run;
|
787
|
+
lzx->sys->copy(i_ptr, rundest, (size_t) i);
|
788
|
+
rundest += i;
|
789
|
+
i_ptr += i;
|
790
|
+
this_run -= i;
|
791
|
+
}
|
792
|
+
}
|
793
|
+
break;
|
785
794
|
|
786
795
|
default:
|
787
|
-
|
796
|
+
return lzx->error = MSPACK_ERR_DECRUNCH; /* might as well */
|
788
797
|
}
|
789
798
|
|
790
799
|
/* did the final match overrun our desired this_run length? */
|
791
800
|
if (this_run < 0) {
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
801
|
+
if ((unsigned int)(-this_run) > lzx->block_remaining) {
|
802
|
+
D(("overrun went past end of block by %d (%d remaining)",
|
803
|
+
-this_run, lzx->block_remaining ))
|
804
|
+
return lzx->error = MSPACK_ERR_DECRUNCH;
|
805
|
+
}
|
806
|
+
lzx->block_remaining -= -this_run;
|
798
807
|
}
|
799
808
|
} /* while (bytes_todo > 0) */
|
800
809
|
|
801
810
|
/* streams don't extend over frame boundaries */
|
802
811
|
if ((window_posn - lzx->frame_posn) != frame_size) {
|
803
812
|
D(("decode beyond output frame limits! %d != %d",
|
804
|
-
|
813
|
+
window_posn - lzx->frame_posn, frame_size))
|
805
814
|
return lzx->error = MSPACK_ERR_DECRUNCH;
|
806
815
|
}
|
807
816
|
|
@@ -818,7 +827,7 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
818
827
|
|
819
828
|
/* does this intel block _really_ need decoding? */
|
820
829
|
if (lzx->intel_started && lzx->intel_filesize &&
|
821
|
-
|
830
|
+
(lzx->frame <= 32768) && (frame_size > 10))
|
822
831
|
{
|
823
832
|
unsigned char *data = &lzx->e8_buf[0];
|
824
833
|
unsigned char *dataend = &lzx->e8_buf[frame_size - 10];
|
@@ -831,17 +840,17 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
|
|
831
840
|
lzx->sys->copy(&lzx->window[lzx->frame_posn], data, frame_size);
|
832
841
|
|
833
842
|
while (data < dataend) {
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
843
|
+
if (*data++ != 0xE8) { curpos++; continue; }
|
844
|
+
abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
|
845
|
+
if ((abs_off >= -curpos) && (abs_off < filesize)) {
|
846
|
+
rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
|
847
|
+
data[0] = (unsigned char) rel_off;
|
848
|
+
data[1] = (unsigned char) (rel_off >> 8);
|
849
|
+
data[2] = (unsigned char) (rel_off >> 16);
|
850
|
+
data[3] = (unsigned char) (rel_off >> 24);
|
851
|
+
}
|
852
|
+
data += 4;
|
853
|
+
curpos += 5;
|
845
854
|
}
|
846
855
|
lzx->intel_curpos += frame_size;
|
847
856
|
}
|