1 /**********************************************************************
2 Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #define _FILE_OFFSET_BITS 64
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <stdarg.h>
36 #include "igzip_lib.h"
37 #include "checksum_test_ref.h"
38 #include "inflate_std_vects.h"
39 #include <math.h>
40 #include "test.h"
41 #include "unaligned.h"
42
43 #ifdef HAVE_GETOPT
44 #include <getopt.h>
45 #endif
46
47 #ifndef RANDOMS
48 # define RANDOMS 0x40
49 #endif
50 #ifndef TEST_SEED
51 # define TEST_SEED 0x1234
52 #endif
53
54 #define MAX_BITS_COUNT 20
55 #define MIN_BITS_COUNT 8
56
57 #define IBUF_SIZE (1024*1024)
58
59 #define MAX_LARGE_COMP_BUF_SIZE (1024*1024)
60
61 #define PAGE_SIZE 4*1024
62
63 #define MAX_FILE_SIZE 0x7fff8fff
64
65 #define str1 "Short test string"
66 #define str2 "one two three four five six seven eight nine ten eleven twelve " \
67 "thirteen fourteen fifteen sixteen"
68
69 #define TYPE0_HDR_SIZE 5 /* Size of a type 0 blocks header in bytes */
70 #define TYPE0_MAX_SIZE 65535 /* Max length of a type 0 block in bytes (excludes the header) */
71
72 #define MAX_LOOPS 20
73 /* Defines for the possible error conditions */
74 enum IGZIP_TEST_ERROR_CODES {
75 IGZIP_COMP_OK = 0,
76
77 MALLOC_FAILED,
78 FILE_READ_FAILED,
79
80 COMPRESS_INCORRECT_STATE,
81 COMPRESS_INPUT_STREAM_INTEGRITY_ERROR,
82 COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR,
83 COMPRESS_END_OF_STREAM_NOT_SET,
84 COMPRESS_ALL_INPUT_FAIL,
85 COMPRESS_OUT_BUFFER_OVERFLOW,
86 COMPRESS_LOOP_COUNT_OVERFLOW,
87 COMPRESS_GENERAL_ERROR,
88
89 INFLATE_END_OF_INPUT,
90 INFLATE_INVALID_BLOCK_HEADER,
91 INFLATE_INVALID_SYMBOL,
92 INFLATE_OUT_BUFFER_OVERFLOW,
93 INFLATE_LEFTOVER_INPUT,
94 INFLATE_INCORRECT_OUTPUT_SIZE,
95 INFLATE_INVALID_LOOK_BACK_DISTANCE,
96 INFLATE_INPUT_STREAM_INTEGRITY_ERROR,
97 INFLATE_OUTPUT_STREAM_INTEGRITY_ERROR,
98 INVALID_GZIP_HEADER,
99 INCORRECT_GZIP_TRAILER,
100 INVALID_ZLIB_HEADER,
101 INCORRECT_ZLIB_TRAILER,
102
103 UNSUPPORTED_METHOD,
104
105 INFLATE_GENERAL_ERROR,
106
107 INVALID_FLUSH_ERROR,
108
109 OVERFLOW_TEST_ERROR,
110 RESULT_ERROR
111 };
112
113 static const int hdr_bytes = 300;
114
115 static const uint32_t gzip_trl_bytes = 8;
116 static const uint32_t zlib_trl_bytes = 4;
117 static const int gzip_extra_bytes = 18; /* gzip_hdr_bytes + gzip_trl_bytes */
118 static const int zlib_extra_bytes = 6; /* zlib_hdr_bytes + zlib_trl_bytes */
119
120 int inflate_type = 0;
121
122 struct isal_hufftables *hufftables = NULL;
123 struct isal_hufftables *hufftables_subset = NULL;
124
125 #define HISTORY_SIZE 32*1024
126 #define MIN_LENGTH 3
127 #define MIN_DIST 1
128
129 struct test_options {
130 int test_seed;
131 int randoms;
132 int do_large_test;
133 int verbose;
134
135 };
136
137 struct test_options options;
138
init_options(void)139 void init_options(void)
140 {
141 options.test_seed = TEST_SEED;
142 options.randoms = RANDOMS;
143 options.do_large_test = 1;
144 #ifdef VERBOSE
145 options.verbose = 1;
146 #else
147 options.verbose = 0;
148 #endif
149 }
150
usage(void)151 void usage(void)
152 {
153 fprintf(stderr,
154 "Usage: igzip_rand_test [options] [FILES]\n"
155 " -h help, print this message\n"
156 " -l turn off large input test\n"
157 " -r <iter> number of randoms for each test\n"
158 " -s <seed> set rand() test seed\n"
159 " -v enable verbose test log\n");
160 exit(0);
161 }
162
parse_options(int argc,char * argv[])163 size_t parse_options(int argc, char *argv[])
164 {
165 init_options();
166 #ifdef HAVE_GETOPT
167 int c;
168 char optstring[] = "hlr:s:v";
169 while ((c = getopt(argc, argv, optstring)) != -1) {
170 switch (c) {
171 case 'l':
172 options.do_large_test = 0;
173 break;
174 case 'r':
175 options.randoms = atoi(optarg);
176 break;
177 case 's':
178 options.test_seed = atoi(optarg);
179 break;
180 case 'v':
181 options.verbose = 1;
182 break;
183 case 'h':
184 default:
185 usage();
186 break;
187 }
188 }
189 return optind;
190 #else
191 return 1;
192 #endif
193 }
194
195 /* Create random compressible data. This is achieved by randomly choosing a
196 * random character, or to repeat previous data in the stream for a random
197 * length and look back distance. The probability of a random character or a
198 * repeat being chosen is semi-randomly chosen by setting max_repeat_data to be
199 * differing values */
create_rand_repeat_data(uint8_t * data,int size)200 void create_rand_repeat_data(uint8_t * data, int size)
201 {
202 uint32_t next_data;
203 uint8_t *data_start = data;
204 uint32_t length, distance;
205 uint32_t symbol_count = rand() % 255 + 1, swaps_left, tmp;
206 uint32_t max_repeat_data = symbol_count;
207 uint8_t symbols[256], *symbols_next, swap_val;
208
209 /* An array of the powers of 2 (except the final element which is 0) */
210 const uint32_t power_of_2_array[] = {
211 0x00000001, 0x00000002, 0x00000004, 0x00000008,
212 0x00000010, 0x00000020, 0x00000040, 0x00000080,
213 0x00000100, 0x00000200, 0x00000400, 0x00000800,
214 0x00001000, 0x00002000, 0x00004000, 0x00008000,
215 0x00010000, 0x00020000, 0x00040000, 0x00080000,
216 0x00100000, 0x00200000, 0x00400000, 0x00800000,
217 0x01000000, 0x02000000, 0x04000000, 0x08000000,
218 0x10000000, 0x20000000, 0x40000000, 0x00000000
219 };
220
221 uint32_t power = rand() % sizeof(power_of_2_array) / sizeof(uint32_t);
222
223 if (symbol_count > 128) {
224 memset(symbols, 1, sizeof(symbols));
225 swap_val = 0;
226 swaps_left = 256 - symbol_count;
227 } else {
228 memset(symbols, 0, sizeof(symbols));
229 swap_val = 1;
230 swaps_left = symbol_count;
231 }
232
233 while (swaps_left > 0) {
234 tmp = rand() % 256;
235 if (symbols[tmp] != swap_val) {
236 symbols[tmp] = swap_val;
237 swaps_left--;
238 }
239 }
240
241 symbols_next = symbols;
242 for (tmp = 0; tmp < 256; tmp++) {
243 if (symbols[tmp]) {
244 *symbols_next = tmp;
245 symbols_next++;
246 }
247 }
248
249 max_repeat_data += power_of_2_array[power];
250
251 if (size > 0) {
252 size--;
253 *data++ = rand();
254 }
255
256 while (size > 0) {
257 next_data = rand() % max_repeat_data;
258 if (next_data < symbol_count) {
259 *data++ = symbols[next_data];
260 size--;
261 } else if (size < 3) {
262 *data++ = symbols[rand() % symbol_count];
263 size--;
264 } else {
265 length = (rand() % 256) + MIN_LENGTH;
266 if (length > size)
267 length = (rand() % (size - 2)) + MIN_LENGTH;
268
269 distance = (rand() % HISTORY_SIZE) + MIN_DIST;
270 if (distance > data - data_start)
271 distance = (rand() % (data - data_start)) + MIN_DIST;
272
273 size -= length;
274 if (distance <= length) {
275 while (length-- > 0) {
276 *data = *(data - distance);
277 data++;
278 }
279 } else {
280 memcpy(data, data - distance, length);
281 data += length;
282 }
283 }
284 }
285 }
286
create_rand_dict(uint8_t * dict,uint32_t dict_len,uint8_t * buf,uint32_t buf_len)287 void create_rand_dict(uint8_t * dict, uint32_t dict_len, uint8_t * buf, uint32_t buf_len)
288 {
289 uint32_t dict_chunk_size, buf_chunk_size;
290 while (dict_len > 0) {
291 dict_chunk_size = rand() % IGZIP_K;
292 dict_chunk_size = (dict_len >= dict_chunk_size) ? dict_chunk_size : dict_len;
293
294 buf_chunk_size = rand() % IGZIP_K;
295 buf_chunk_size = (buf_len >= buf_chunk_size) ? buf_chunk_size : buf_len;
296
297 if (rand() % 3 == 0 && buf_len >= dict_len)
298 memcpy(dict, buf, dict_chunk_size);
299 else
300 create_rand_repeat_data(dict, dict_chunk_size);
301
302 dict_len -= dict_chunk_size;
303 dict += dict_chunk_size;
304 buf_len -= buf_chunk_size;
305 buf += buf_chunk_size;
306 }
307
308 }
309
get_rand_data_length(void)310 int get_rand_data_length(void)
311 {
312 int max_mask =
313 (1 << ((rand() % (MAX_BITS_COUNT - MIN_BITS_COUNT)) + MIN_BITS_COUNT)) - 1;
314 return rand() & max_mask;
315 }
316
get_rand_level(void)317 int get_rand_level(void)
318 {
319 return ISAL_DEF_MIN_LEVEL + rand() % (ISAL_DEF_MAX_LEVEL - ISAL_DEF_MIN_LEVEL + 1);
320
321 }
322
get_rand_level_buf_size(int level)323 int get_rand_level_buf_size(int level)
324 {
325 int size;
326 switch (level) {
327 case 3:
328 size = rand() % IBUF_SIZE + ISAL_DEF_LVL3_MIN;
329 break;
330 case 2:
331 size = rand() % IBUF_SIZE + ISAL_DEF_LVL2_MIN;
332 break;
333 case 1:
334 default:
335 size = rand() % IBUF_SIZE + ISAL_DEF_LVL1_MIN;
336 }
337 return size;
338 }
339
print_error(int error_code)340 void print_error(int error_code)
341 {
342 switch (error_code) {
343 case IGZIP_COMP_OK:
344 break;
345 case MALLOC_FAILED:
346 printf("error: failed to allocate memory\n");
347 break;
348 case FILE_READ_FAILED:
349 printf("error: failed to read in file\n");
350 break;
351 case COMPRESS_INCORRECT_STATE:
352 printf("error: incorrect stream internal state\n");
353 break;
354 case COMPRESS_INPUT_STREAM_INTEGRITY_ERROR:
355 printf("error: inconsistent stream input buffer\n");
356 break;
357 case COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR:
358 printf("error: inconsistent stream output buffer\n");
359 break;
360 case COMPRESS_END_OF_STREAM_NOT_SET:
361 printf("error: end of stream not set\n");
362 break;
363 case COMPRESS_ALL_INPUT_FAIL:
364 printf("error: not all input data compressed\n");
365 break;
366 case COMPRESS_OUT_BUFFER_OVERFLOW:
367 printf("error: output buffer overflow while compressing data\n");
368 break;
369 case COMPRESS_GENERAL_ERROR:
370 printf("error: compression failed\n");
371 break;
372 case INFLATE_END_OF_INPUT:
373 printf("error: did not decompress all input\n");
374 break;
375 case INFLATE_INVALID_BLOCK_HEADER:
376 printf("error: invalid header\n");
377 break;
378 case INFLATE_INVALID_SYMBOL:
379 printf("error: invalid symbol found when decompressing input\n");
380 break;
381 case INFLATE_OUT_BUFFER_OVERFLOW:
382 printf("error: output buffer overflow while decompressing data\n");
383 break;
384 case INFLATE_GENERAL_ERROR:
385 printf("error: decompression failed\n");
386 break;
387 case INFLATE_LEFTOVER_INPUT:
388 printf("error: the trailer of igzip output contains junk\n");
389 break;
390 case INFLATE_INCORRECT_OUTPUT_SIZE:
391 printf("error: incorrect amount of data was decompressed\n");
392 break;
393 case INFLATE_INVALID_LOOK_BACK_DISTANCE:
394 printf("error: invalid look back distance found while decompressing\n");
395 break;
396 case INFLATE_INPUT_STREAM_INTEGRITY_ERROR:
397 printf("error: inconsistent input buffer\n");
398 break;
399 case INFLATE_OUTPUT_STREAM_INTEGRITY_ERROR:
400 printf("error: inconsistent output buffer\n");
401 break;
402 case INVALID_GZIP_HEADER:
403 printf("error: incorrect gzip header found when inflating data\n");
404 break;
405 case INCORRECT_GZIP_TRAILER:
406 printf("error: incorrect gzip trailer found when inflating data\n");
407 break;
408 case INVALID_ZLIB_HEADER:
409 printf("error: incorrect zlib header found when inflating data\n");
410 break;
411 case INCORRECT_ZLIB_TRAILER:
412 printf("error: incorrect zlib trailer found when inflating data\n");
413 break;
414 case UNSUPPORTED_METHOD:
415 printf("error: invalid compression method in wrapper header\n");
416 break;
417 case INVALID_FLUSH_ERROR:
418 printf("error: invalid flush did not cause compression to error\n");
419 break;
420 case RESULT_ERROR:
421 printf("error: decompressed data is not the same as the compressed data\n");
422 break;
423 case OVERFLOW_TEST_ERROR:
424 printf("error: overflow undetected\n");
425 break;
426 default:
427 printf("error: unknown error code\n");
428 }
429 }
430
print_uint8_t(uint8_t * array,uint64_t length)431 void print_uint8_t(uint8_t * array, uint64_t length)
432 {
433 const int line_size = 16;
434 int i;
435
436 printf("Length = %lu", length);
437 for (i = 0; i < length; i++) {
438 if ((i % line_size) == 0)
439 printf("\n0x%08x\t", i);
440 else
441 printf(" ");
442 printf("0x%02x,", array[i]);
443 }
444 printf("\n");
445 }
446
log_print(char * format,...)447 void log_print(char *format, ...)
448 {
449 va_list args;
450 va_start(args, format);
451
452 if (options.verbose)
453 vfprintf(stdout, format, args);
454
455 va_end(args);
456 }
457
log_uint8_t(uint8_t * array,uint64_t length)458 void log_uint8_t(uint8_t * array, uint64_t length)
459 {
460 if (options.verbose)
461 print_uint8_t(array, length);
462 }
463
log_error(int error_code)464 void log_error(int error_code)
465 {
466 if (options.verbose)
467 print_error(error_code);
468 }
469
check_gzip_trl(uint64_t gzip_trl,uint32_t inflate_crc,uint8_t * uncompress_buf,uint32_t uncompress_len)470 uint32_t check_gzip_trl(uint64_t gzip_trl, uint32_t inflate_crc, uint8_t * uncompress_buf,
471 uint32_t uncompress_len)
472 {
473 uint64_t trl, ret = 0;
474 uint32_t crc;
475
476 crc = crc32_gzip_refl_ref(0, uncompress_buf, uncompress_len);
477 trl = ((uint64_t) uncompress_len << 32) | crc;
478
479 if (crc != inflate_crc || trl != gzip_trl)
480 ret = INCORRECT_GZIP_TRAILER;
481
482 return ret;
483 }
484
check_zlib_trl(uint32_t zlib_trl,uint32_t inflate_adler,uint8_t * uncompress_buf,uint32_t uncompress_len)485 uint32_t check_zlib_trl(uint32_t zlib_trl, uint32_t inflate_adler, uint8_t * uncompress_buf,
486 uint32_t uncompress_len)
487 {
488 uint32_t trl, ret = 0;
489 uint32_t adler;
490
491 adler = adler_ref(1, uncompress_buf, uncompress_len);
492
493 trl =
494 (adler >> 24) | ((adler >> 8) & 0xFF00) | (adler << 24) | ((adler & 0xFF00) << 8);
495
496 if (adler != inflate_adler || trl != zlib_trl) {
497 ret = INCORRECT_ZLIB_TRAILER;
498 }
499
500 return ret;
501 }
502
inflate_stateless_pass(uint8_t * compress_buf,uint64_t compress_len,uint8_t * uncompress_buf,uint32_t * uncompress_len,uint32_t gzip_flag)503 int inflate_stateless_pass(uint8_t * compress_buf, uint64_t compress_len,
504 uint8_t * uncompress_buf, uint32_t * uncompress_len,
505 uint32_t gzip_flag)
506 {
507 struct inflate_state state;
508 int ret = 0, offset = 0;
509 struct isal_gzip_header gz_hdr;
510 struct isal_zlib_header z_hdr;
511
512 state.next_in = compress_buf;
513 state.avail_in = compress_len;
514 state.next_out = uncompress_buf;
515 state.avail_out = *uncompress_len;
516
517 if (gzip_flag == IGZIP_GZIP) {
518 if (rand() % 2 == 0) {
519 memset(&gz_hdr, 0, sizeof(gz_hdr));
520 isal_inflate_reset(&state);
521 state.tmp_in_size = 0;
522 gzip_flag = ISAL_GZIP_NO_HDR_VER;
523
524 isal_read_gzip_header(&state, &gz_hdr);
525 }
526 } else if (gzip_flag == IGZIP_ZLIB) {
527 if (rand() % 2 == 0) {
528 memset(&z_hdr, 0, sizeof(z_hdr));
529 isal_inflate_reset(&state);
530 gzip_flag = ISAL_ZLIB_NO_HDR_VER;
531 isal_read_zlib_header(&state, &z_hdr);
532 }
533 }
534
535 state.crc_flag = gzip_flag;
536
537 ret = isal_inflate_stateless(&state);
538
539 *uncompress_len = state.total_out;
540
541 if (gzip_flag) {
542 if (gzip_flag == IGZIP_GZIP || gzip_flag == IGZIP_GZIP_NO_HDR
543 || gzip_flag == ISAL_GZIP_NO_HDR_VER) {
544 if (gzip_flag == IGZIP_GZIP || gzip_flag == ISAL_GZIP_NO_HDR_VER)
545 offset = gzip_trl_bytes;
546
547 if (!ret)
548 ret =
549 check_gzip_trl(load_u64(state.next_in - offset),
550 state.crc, uncompress_buf, *uncompress_len);
551 else if (ret == ISAL_INCORRECT_CHECKSUM)
552 ret = INCORRECT_GZIP_TRAILER;
553 state.avail_in -= (gzip_trl_bytes - offset);
554 } else if (gzip_flag == IGZIP_ZLIB || gzip_flag == IGZIP_ZLIB_NO_HDR
555 || gzip_flag == ISAL_ZLIB_NO_HDR_VER) {
556 if (gzip_flag == IGZIP_ZLIB || gzip_flag == ISAL_ZLIB_NO_HDR_VER)
557 offset = zlib_trl_bytes;
558
559 if (!ret)
560 ret =
561 check_zlib_trl(load_u32(state.next_in - offset),
562 state.crc, uncompress_buf, *uncompress_len);
563 else if (ret == ISAL_INCORRECT_CHECKSUM)
564 ret = INCORRECT_ZLIB_TRAILER;
565 state.avail_in -= (zlib_trl_bytes - offset);
566
567 }
568
569 }
570
571 if (ret == 0 && state.avail_in != 0)
572 ret = INFLATE_LEFTOVER_INPUT;
573
574 return ret;
575 }
576
577 /* Check if that the state of the data stream is consistent */
inflate_state_valid_check(struct inflate_state * state,uint8_t * in_buf,uint32_t in_size,uint8_t * out_buf,uint32_t out_size,uint32_t in_processed,uint32_t out_processed,uint32_t data_size)578 int inflate_state_valid_check(struct inflate_state *state, uint8_t * in_buf, uint32_t in_size,
579 uint8_t * out_buf, uint32_t out_size, uint32_t in_processed,
580 uint32_t out_processed, uint32_t data_size)
581 {
582 uint32_t in_buffer_size, total_out, out_buffer_size;
583
584 in_buffer_size = (in_size == 0) ? 0 : state->next_in - in_buf + state->avail_in;
585
586 /* Check for a consistent amount of data processed */
587 if (in_buffer_size != in_size)
588 return INFLATE_INPUT_STREAM_INTEGRITY_ERROR;
589
590 total_out =
591 (out_size == 0) ? out_processed : out_processed + (state->next_out - out_buf);
592 out_buffer_size = (out_size == 0) ? 0 : state->next_out - out_buf + state->avail_out;
593
594 /* Check for a consistent amount of data compressed */
595 if (total_out != state->total_out || out_buffer_size != out_size)
596 return INFLATE_OUTPUT_STREAM_INTEGRITY_ERROR;
597
598 return 0;
599 }
600
601 /* Performs compression with checks to discover and verify the state of the
602 * stream
603 * state: inflate data structure which has been initialized to use
604 * in_buf and out_buf as the buffers
605 * compress_len: size of all input compressed data
606 * data_size: size of all available output buffers
607 * in_buf: next buffer of data to be inflated
608 * in_size: size of in_buf
609 * out_buf: next out put buffer where data is stored
610 * out_size: size of out_buf
611 * in_processed: the amount of input data which has been loaded into buffers
612 * to be inflated, this includes the data in in_buf
613 * out_processed: the amount of output data which has been decompressed and stored,
614 * this does not include the data in the current out_buf
615 */
isal_inflate_with_checks(struct inflate_state * state,uint32_t compress_len,uint32_t data_size,uint8_t * in_buf,uint32_t in_size,uint32_t in_processed,uint8_t * out_buf,uint32_t out_size,uint32_t out_processed)616 int isal_inflate_with_checks(struct inflate_state *state, uint32_t compress_len,
617 uint32_t data_size, uint8_t * in_buf, uint32_t in_size,
618 uint32_t in_processed, uint8_t * out_buf, uint32_t out_size,
619 uint32_t out_processed)
620 {
621 int ret, stream_check = 0;
622
623 ret = isal_inflate(state);
624
625 /* Verify the stream is in a valid state when no errors occured */
626 if (ret >= 0) {
627 stream_check =
628 inflate_state_valid_check(state, in_buf, in_size, out_buf, out_size,
629 in_processed, out_processed, data_size);
630 }
631
632 if (stream_check != 0)
633 return stream_check;
634
635 return ret;
636
637 }
638
inflate_multi_pass(uint8_t * compress_buf,uint64_t compress_len,uint8_t * uncompress_buf,uint32_t * uncompress_len,uint32_t gzip_flag,uint8_t * dict,uint32_t dict_len,uint32_t hist_bits)639 int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
640 uint8_t * uncompress_buf, uint32_t * uncompress_len, uint32_t gzip_flag,
641 uint8_t * dict, uint32_t dict_len, uint32_t hist_bits)
642 {
643 struct inflate_state *state = NULL;
644 int ret = 0;
645 uint8_t *comp_tmp = NULL, *uncomp_tmp = NULL;
646 uint32_t comp_tmp_size = 0, uncomp_tmp_size = 0;
647 uint32_t comp_processed = 0, uncomp_processed = 0;
648 int32_t read_in_old = 0;
649 uint32_t reset_test_flag = 0;
650
651 state = malloc(sizeof(struct inflate_state));
652 if (state == NULL) {
653 printf("Failed to allocate memory\n");
654 exit(0);
655 }
656
657 create_rand_repeat_data((uint8_t *) state, sizeof(state));
658 isal_inflate_init(state);
659
660 if (rand() % 4 == 0) {
661 /* Test reset */
662 reset_test_flag = 1;
663 create_rand_repeat_data((uint8_t *) state, sizeof(state));
664 }
665
666 if (gzip_flag == IGZIP_GZIP_NO_HDR) {
667 if (rand() % 2 == 0)
668 compress_len -= gzip_trl_bytes;
669 else
670 gzip_flag = ISAL_GZIP_NO_HDR_VER;
671 } else if (gzip_flag == IGZIP_ZLIB_NO_HDR) {
672 if (rand() % 2 == 0)
673 compress_len -= zlib_trl_bytes;
674 else
675 gzip_flag = ISAL_ZLIB_NO_HDR_VER;
676 }
677
678 state->next_in = NULL;
679 state->next_out = NULL;
680 state->avail_in = 0;
681 state->avail_out = 0;
682 state->crc_flag = gzip_flag;
683 state->hist_bits = hist_bits;
684
685 if (reset_test_flag)
686 isal_inflate_reset(state);
687
688 if (dict != NULL)
689 isal_inflate_set_dict(state, dict, dict_len);
690
691 while (1) {
692 if (state->avail_in == 0) {
693 comp_tmp_size = rand() % (compress_len + 1);
694
695 if (comp_tmp_size >= compress_len - comp_processed)
696 comp_tmp_size = compress_len - comp_processed;
697
698 if (comp_tmp_size != 0) {
699 if (comp_tmp != NULL) {
700 free(comp_tmp);
701 comp_tmp = NULL;
702 }
703
704 comp_tmp = malloc(comp_tmp_size);
705
706 if (comp_tmp == NULL) {
707 printf("Failed to allocate memory\n");
708 return MALLOC_FAILED;
709 }
710
711 memcpy(comp_tmp, compress_buf + comp_processed, comp_tmp_size);
712 comp_processed += comp_tmp_size;
713
714 state->next_in = comp_tmp;
715 state->avail_in = comp_tmp_size;
716 }
717 }
718
719 if (state->avail_out == 0) {
720 /* Save uncompressed data into uncompress_buf */
721 if (uncomp_tmp != NULL) {
722 memcpy(uncompress_buf + uncomp_processed, uncomp_tmp,
723 uncomp_tmp_size);
724 uncomp_processed += uncomp_tmp_size;
725 }
726
727 uncomp_tmp_size = rand() % (*uncompress_len + 1);
728
729 /* Limit size of buffer to be smaller than maximum */
730 if (uncomp_tmp_size > *uncompress_len - uncomp_processed)
731 uncomp_tmp_size = *uncompress_len - uncomp_processed;
732
733 if (uncomp_tmp_size != 0) {
734
735 if (uncomp_tmp != NULL) {
736 fflush(0);
737 free(uncomp_tmp);
738 uncomp_tmp = NULL;
739 }
740
741 uncomp_tmp = malloc(uncomp_tmp_size);
742 if (uncomp_tmp == NULL) {
743 printf("Failed to allocate memory\n");
744 return MALLOC_FAILED;
745 }
746
747 state->avail_out = uncomp_tmp_size;
748 state->next_out = uncomp_tmp;
749 }
750 }
751
752 log_print("Pre inflate\n");
753 log_print
754 ("compressed_size = 0x%05lx, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x\n",
755 compress_len, comp_processed, comp_tmp_size, state->avail_in);
756 log_print
757 ("data_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
758 *uncompress_len, uncomp_processed, uncomp_tmp_size, state->avail_out,
759 state->total_out);
760
761 ret = isal_inflate_with_checks(state, compress_len, *uncompress_len, comp_tmp,
762 comp_tmp_size, comp_processed, uncomp_tmp,
763 uncomp_tmp_size, uncomp_processed);
764
765 log_print("Post inflate\n");
766 log_print
767 ("compressed_size = 0x%05lx, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x\n",
768 compress_len, comp_processed, comp_tmp_size, state->avail_in);
769 log_print
770 ("data_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
771 *uncompress_len, uncomp_processed, uncomp_tmp_size, state->avail_out,
772 state->total_out);
773
774 if (state->block_state == ISAL_BLOCK_FINISH || ret != 0) {
775 memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, uncomp_tmp_size);
776 *uncompress_len = state->total_out;
777 break;
778 }
779
780 if (*uncompress_len - uncomp_processed == 0 && state->avail_out == 0
781 && state->tmp_out_valid - state->tmp_out_processed > 0) {
782 ret = ISAL_OUT_OVERFLOW;
783 break;
784 }
785
786 if (compress_len - comp_processed == 0 && state->avail_in == 0
787 && (state->block_state != ISAL_BLOCK_INPUT_DONE)
788 && state->tmp_out_valid - state->tmp_out_processed == 0) {
789 if (state->read_in_length == read_in_old) {
790 ret = ISAL_END_INPUT;
791 break;
792 }
793 read_in_old = state->read_in_length;
794 }
795 }
796
797 if (gzip_flag) {
798 if (!ret) {
799 if (gzip_flag == IGZIP_GZIP || gzip_flag == IGZIP_GZIP_NO_HDR
800 || gzip_flag == ISAL_GZIP_NO_HDR_VER) {
801 if (gzip_flag == ISAL_GZIP_NO_HDR_VER
802 || gzip_flag == IGZIP_GZIP)
803 compress_len -= gzip_trl_bytes;
804 ret =
805 check_gzip_trl(load_u64(compress_buf + compress_len),
806 state->crc, uncompress_buf,
807 *uncompress_len);
808 } else if (gzip_flag == IGZIP_ZLIB_NO_HDR) {
809 if (gzip_flag == IGZIP_ZLIB
810 || gzip_flag == ISAL_ZLIB_NO_HDR_VER)
811 compress_len -= zlib_trl_bytes;
812 ret =
813 check_zlib_trl(load_u32(compress_buf + compress_len),
814 state->crc, uncompress_buf,
815 *uncompress_len);
816 }
817 }
818 }
819 if (ret == 0 && state->avail_in != 0)
820 ret = INFLATE_LEFTOVER_INPUT;
821
822 if (comp_tmp != NULL) {
823 free(comp_tmp);
824 comp_tmp = NULL;
825 }
826
827 if (uncomp_tmp != NULL) {
828 free(uncomp_tmp);
829 uncomp_tmp = NULL;
830 }
831
832 free(state);
833 return ret;
834 }
835
inflate_ret_to_code(int ret)836 int inflate_ret_to_code(int ret)
837 {
838 switch (ret) {
839 case ISAL_DECOMP_OK:
840 return 0;
841 case ISAL_END_INPUT:
842 return INFLATE_END_OF_INPUT;
843 case ISAL_OUT_OVERFLOW:
844 return INFLATE_OUT_BUFFER_OVERFLOW;
845 case ISAL_INVALID_BLOCK:
846 return INFLATE_INVALID_BLOCK_HEADER;
847 case ISAL_INVALID_SYMBOL:
848 return INFLATE_INVALID_SYMBOL;
849 case ISAL_INVALID_LOOKBACK:
850 return INFLATE_INVALID_LOOK_BACK_DISTANCE;
851 default:
852 return INFLATE_GENERAL_ERROR;
853 }
854 }
855
856 /* Inflate the compressed data and check that the decompressed data agrees with the input data */
inflate_check(uint8_t * z_buf,uint32_t z_size,uint8_t * in_buf,uint32_t in_size,uint32_t gzip_flag,uint8_t * dict,uint32_t dict_len,uint32_t hist_bits)857 int inflate_check(uint8_t * z_buf, uint32_t z_size, uint8_t * in_buf, uint32_t in_size,
858 uint32_t gzip_flag, uint8_t * dict, uint32_t dict_len, uint32_t hist_bits)
859 {
860 /* Test inflate with reference inflate */
861
862 int ret = 0;
863 uint32_t test_size = in_size;
864 uint8_t *test_buf = NULL;
865 int mem_result = 0;
866 int gzip_hdr_result = 0, gzip_trl_result = 0;
867
868 if (in_size > 0) {
869 assert(in_buf != NULL);
870 test_buf = malloc(test_size);
871 if (test_buf == NULL)
872 return MALLOC_FAILED;
873 }
874
875 if (test_buf != NULL)
876 memset(test_buf, 0xff, test_size);
877
878 if (inflate_type == 0 && dict == NULL) {
879 ret = inflate_stateless_pass(z_buf, z_size, test_buf, &test_size, gzip_flag);
880 inflate_type = 1;
881 } else {
882 ret =
883 inflate_multi_pass(z_buf, z_size, test_buf, &test_size, gzip_flag, dict,
884 dict_len, hist_bits);
885 inflate_type = 0;
886 }
887
888 if (test_buf != NULL)
889 mem_result = memcmp(in_buf, test_buf, in_size);
890
891 if (options.verbose && mem_result) {
892 int i;
893 for (i = 0; i < in_size; i++) {
894 if (in_buf[i] != test_buf[i]) {
895 log_print
896 ("First incorrect data at 0x%x of 0x%x, 0x%x != 0x%x\n", i,
897 in_size, in_buf[i], test_buf[i]);
898 break;
899 }
900 }
901 }
902
903 if (test_buf != NULL)
904 free(test_buf);
905 switch (ret) {
906 case 0:
907 break;
908 case ISAL_END_INPUT:
909 return INFLATE_END_OF_INPUT;
910 break;
911 case ISAL_INVALID_BLOCK:
912 return INFLATE_INVALID_BLOCK_HEADER;
913 break;
914 case ISAL_INVALID_SYMBOL:
915 return INFLATE_INVALID_SYMBOL;
916 break;
917 case ISAL_OUT_OVERFLOW:
918 return INFLATE_OUT_BUFFER_OVERFLOW;
919 break;
920 case ISAL_INVALID_LOOKBACK:
921 return INFLATE_INVALID_LOOK_BACK_DISTANCE;
922 break;
923 case INFLATE_LEFTOVER_INPUT:
924 return INFLATE_LEFTOVER_INPUT;
925 break;
926 case INCORRECT_GZIP_TRAILER:
927 gzip_trl_result = INCORRECT_GZIP_TRAILER;
928 break;
929 case INCORRECT_ZLIB_TRAILER:
930 gzip_trl_result = INCORRECT_ZLIB_TRAILER;
931 break;
932 case ISAL_INCORRECT_CHECKSUM:
933 if (gzip_flag == IGZIP_GZIP || gzip_flag == IGZIP_GZIP_NO_HDR
934 || gzip_flag == ISAL_GZIP_NO_HDR_VER)
935 gzip_trl_result = INCORRECT_GZIP_TRAILER;
936 else if (gzip_flag == IGZIP_ZLIB || gzip_flag == IGZIP_ZLIB_NO_HDR
937 || gzip_flag == ISAL_ZLIB_NO_HDR_VER)
938 gzip_trl_result = INCORRECT_GZIP_TRAILER;
939 break;
940 case ISAL_UNSUPPORTED_METHOD:
941 return UNSUPPORTED_METHOD;
942 case INFLATE_INPUT_STREAM_INTEGRITY_ERROR:
943 return INFLATE_INPUT_STREAM_INTEGRITY_ERROR;
944 break;
945 case INFLATE_OUTPUT_STREAM_INTEGRITY_ERROR:
946 return INFLATE_OUTPUT_STREAM_INTEGRITY_ERROR;
947 break;
948 default:
949 return INFLATE_GENERAL_ERROR;
950 break;
951 }
952
953 if (test_size != in_size)
954 return INFLATE_INCORRECT_OUTPUT_SIZE;
955
956 if (mem_result)
957 return RESULT_ERROR;
958
959 if (gzip_hdr_result == INVALID_GZIP_HEADER)
960 return INVALID_GZIP_HEADER;
961
962 else if (gzip_hdr_result == INVALID_ZLIB_HEADER)
963 return INVALID_ZLIB_HEADER;
964
965 if (gzip_trl_result == INCORRECT_GZIP_TRAILER)
966 return INCORRECT_GZIP_TRAILER;
967
968 else if (gzip_trl_result == INCORRECT_ZLIB_TRAILER)
969 return INCORRECT_ZLIB_TRAILER;
970
971 return 0;
972 }
973
974 /* Check if that the state of the data stream is consistent */
stream_valid_check(struct isal_zstream * stream,uint8_t * in_buf,uint32_t in_size,uint8_t * out_buf,uint32_t out_size,uint32_t in_processed,uint32_t out_processed,uint32_t data_size)975 int stream_valid_check(struct isal_zstream *stream, uint8_t * in_buf, uint32_t in_size,
976 uint8_t * out_buf, uint32_t out_size, uint32_t in_processed,
977 uint32_t out_processed, uint32_t data_size)
978 {
979 uint32_t total_in, in_buffer_size, total_out, out_buffer_size;
980
981 total_in =
982 (in_size ==
983 0) ? in_processed : (in_processed - in_size) + (stream->next_in - in_buf);
984 in_buffer_size = (in_size == 0) ? 0 : stream->next_in - in_buf + stream->avail_in;
985
986 /* Check for a consistent amount of data processed */
987 if (total_in != stream->total_in || in_buffer_size != in_size)
988 return COMPRESS_INPUT_STREAM_INTEGRITY_ERROR;
989
990 total_out =
991 (out_size == 0) ? out_processed : out_processed + (stream->next_out - out_buf);
992 out_buffer_size = (out_size == 0) ? 0 : stream->next_out - out_buf + stream->avail_out;
993
994 /* Check for a consistent amount of data compressed */
995 if (total_out != stream->total_out || out_buffer_size != out_size) {
996 return COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR;
997 }
998
999 return 0;
1000 }
1001
1002 /* Performs compression with checks to discover and verify the state of the
1003 * stream
1004 * stream: compress data structure which has been initialized to use
1005 * in_buf and out_buf as the buffers
1006 * data_size: size of all input data
1007 * compressed_size: size of all available output buffers
1008 * in_buf: next buffer of data to be compressed
1009 * in_size: size of in_buf
1010 * out_buf: next out put buffer where data is stored
1011 * out_size: size of out_buf
1012 * in_processed: the amount of input data which has been loaded into buffers
1013 * to be compressed, this includes the data in in_buf
1014 * out_processed: the amount of output data which has been compressed and stored,
1015 * this does not include the data in the current out_buf
1016 */
isal_deflate_with_checks(struct isal_zstream * stream,uint32_t data_size,uint32_t compressed_size,uint8_t * in_buf,uint32_t in_size,uint32_t in_processed,uint8_t * out_buf,uint32_t out_size,uint32_t out_processed)1017 int isal_deflate_with_checks(struct isal_zstream *stream, uint32_t data_size,
1018 uint32_t compressed_size, uint8_t * in_buf, uint32_t in_size,
1019 uint32_t in_processed, uint8_t * out_buf, uint32_t out_size,
1020 uint32_t out_processed)
1021 {
1022 int ret, stream_check;
1023 struct isal_zstate *state = &stream->internal_state;
1024
1025 log_print("Pre compression\n");
1026 log_print
1027 ("data_size = 0x%05x, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x, total_in = 0x%05x\n",
1028 data_size, in_processed, in_size, stream->avail_in, stream->total_in);
1029 log_print
1030 ("compressed_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
1031 compressed_size, out_processed, out_size, stream->avail_out, stream->total_out);
1032
1033 ret = isal_deflate(stream);
1034
1035 log_print("Post compression\n");
1036 log_print
1037 ("data_size = 0x%05x, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x, total_in = 0x%05x\n",
1038 data_size, in_processed, in_size, stream->avail_in, stream->total_in);
1039 log_print
1040 ("compressed_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
1041 compressed_size, out_processed, out_size, stream->avail_out, stream->total_out);
1042 log_print("\n\n");
1043
1044 /* Verify the stream is in a valid state */
1045 stream_check = stream_valid_check(stream, in_buf, in_size, out_buf, out_size,
1046 in_processed, out_processed, data_size);
1047
1048 if (stream_check != 0)
1049 return stream_check;
1050
1051 if (ret != IGZIP_COMP_OK)
1052 return COMPRESS_GENERAL_ERROR;
1053
1054 /* Check if the compression is completed */
1055 if (state->state != ZSTATE_END)
1056 if (compressed_size - out_processed - (out_size - stream->avail_out) <= 0)
1057 return COMPRESS_OUT_BUFFER_OVERFLOW;
1058
1059 return ret;
1060
1061 }
1062
set_random_hufftable(struct isal_zstream * stream,int level,uint8_t * data,uint32_t data_size)1063 void set_random_hufftable(struct isal_zstream *stream, int level, uint8_t * data,
1064 uint32_t data_size)
1065 {
1066 struct isal_hufftables *huff = hufftables;
1067 struct isal_huff_histogram hist;
1068 if (level == 0 || rand() % 16 == 0) {
1069 if (rand() % 8 == 0) {
1070 huff = hufftables_subset;
1071 memset(&hist, 0, sizeof(hist));
1072 isal_update_histogram(data, data_size, &hist);
1073 isal_create_hufftables_subset(huff, &hist);
1074 }
1075
1076 isal_deflate_set_hufftables(stream, huff, rand() % 4);
1077 }
1078 }
1079
1080 /* Compress the input data into the output buffer where the input buffer and
1081 * output buffer are randomly segmented to test state information for the
1082 * compression*/
compress_multi_pass(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t flush_type,uint32_t gzip_flag,uint32_t level,uint8_t * dict,uint32_t dict_len,uint32_t hist_bits)1083 int compress_multi_pass(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1084 uint32_t * compressed_size, uint32_t flush_type, uint32_t gzip_flag,
1085 uint32_t level, uint8_t * dict, uint32_t dict_len, uint32_t hist_bits)
1086 {
1087 int ret = IGZIP_COMP_OK;
1088 uint8_t *in_buf = NULL, *out_buf = NULL;
1089 uint32_t in_size = 0, out_size = 0;
1090 uint32_t in_processed = 0, out_processed = 0;
1091 struct isal_zstream *stream;
1092 struct isal_zstate *state;
1093 uint32_t loop_count = 0;
1094 uint32_t level_buf_size;
1095 uint8_t *level_buf = NULL;
1096 struct isal_hufftables *huff_tmp;
1097 uint32_t reset_test_flag = 0;
1098 uint8_t tmp_symbol;
1099 int no_mod = 0;
1100 struct isal_dict dict_str;
1101
1102 log_print("Starting Compress Multi Pass\n");
1103
1104 stream = malloc(sizeof(*stream));
1105 if (stream == NULL)
1106 return MALLOC_FAILED;
1107 state = &stream->internal_state;
1108
1109 create_rand_repeat_data((uint8_t *) stream, sizeof(*stream));
1110
1111 isal_deflate_init(stream);
1112
1113 if (state->state != ZSTATE_NEW_HDR)
1114 return COMPRESS_INCORRECT_STATE;
1115
1116 if (rand() % 4 == 0) {
1117 /* Test reset */
1118 reset_test_flag = 1;
1119 huff_tmp = stream->hufftables;
1120 create_rand_repeat_data((uint8_t *) stream, sizeof(*stream));
1121
1122 /* Restore variables not necessarily set by user */
1123 stream->hufftables = huff_tmp;
1124 stream->end_of_stream = 0;
1125 stream->level = 0;
1126 stream->level_buf = NULL;
1127 stream->level_buf_size = 0;
1128 }
1129
1130 stream->flush = flush_type;
1131 stream->end_of_stream = 0;
1132
1133 /* These are set here to allow the loop to run correctly */
1134 stream->avail_in = 0;
1135 stream->avail_out = 0;
1136 stream->gzip_flag = gzip_flag;
1137 stream->level = level;
1138 stream->hist_bits = hist_bits;
1139
1140 if (level >= 1) {
1141 level_buf_size = get_rand_level_buf_size(stream->level);
1142 level_buf = malloc(level_buf_size);
1143 create_rand_repeat_data(level_buf, level_buf_size);
1144 stream->level_buf = level_buf;
1145 stream->level_buf_size = level_buf_size;
1146 }
1147
1148 if (reset_test_flag)
1149 isal_deflate_reset(stream);
1150
1151 if (dict != NULL) {
1152 if (rand() % 2 == 0)
1153 isal_deflate_set_dict(stream, dict, dict_len);
1154 else {
1155 isal_deflate_process_dict(stream, &dict_str, dict, dict_len);
1156 isal_deflate_reset_dict(stream, &dict_str);
1157 }
1158 }
1159
1160 while (1) {
1161 loop_count++;
1162
1163 /* Setup in buffer for next round of compression */
1164 if (stream->avail_in == 0) {
1165 if (flush_type == NO_FLUSH || state->state == ZSTATE_NEW_HDR) {
1166 /* Randomly choose size of the next out buffer */
1167 in_size = rand() % (data_size + 1);
1168
1169 /* Limit size of buffer to be smaller than maximum */
1170 if (in_size >= data_size - in_processed) {
1171 in_size = data_size - in_processed;
1172 stream->end_of_stream = 1;
1173 }
1174
1175 if (in_size != 0) {
1176 if (in_buf != NULL) {
1177 free(in_buf);
1178 in_buf = NULL;
1179 }
1180
1181 in_buf = malloc(in_size);
1182 if (in_buf == NULL) {
1183 ret = MALLOC_FAILED;
1184 break;
1185 }
1186 memcpy(in_buf, data + in_processed, in_size);
1187 in_processed += in_size;
1188
1189 stream->avail_in = in_size;
1190 stream->next_in = in_buf;
1191 }
1192 }
1193 } else {
1194 /* Randomly modify data after next in */
1195 if (rand() % 4 == 0 && !no_mod) {
1196
1197 tmp_symbol = rand();
1198 log_print
1199 ("Modifying data at index 0x%x from 0x%x to 0x%x before recalling isal_deflate\n",
1200 in_processed - stream->avail_in,
1201 data[in_processed - stream->avail_in], tmp_symbol);
1202 *stream->next_in = tmp_symbol;
1203 data[in_processed - stream->avail_in] = tmp_symbol;
1204 }
1205 }
1206
1207 /* Setup out buffer for next round of compression */
1208 if (stream->avail_out == 0) {
1209 /* Save compressed data inot compressed_buf */
1210 if (out_buf != NULL) {
1211 memcpy(compressed_buf + out_processed, out_buf,
1212 out_size - stream->avail_out);
1213 out_processed += out_size - stream->avail_out;
1214 }
1215
1216 /* Randomly choose size of the next out buffer */
1217 out_size = rand() % (*compressed_size + 1);
1218
1219 /* Limit size of buffer to be smaller than maximum */
1220 if (out_size > *compressed_size - out_processed)
1221 out_size = *compressed_size - out_processed;
1222
1223 if (out_size != 0) {
1224 if (out_buf != NULL) {
1225 free(out_buf);
1226 out_buf = NULL;
1227 }
1228
1229 out_buf = malloc(out_size);
1230 if (out_buf == NULL) {
1231 ret = MALLOC_FAILED;
1232 break;
1233 }
1234
1235 stream->avail_out = out_size;
1236 stream->next_out = out_buf;
1237 }
1238 }
1239
1240 if (state->state == ZSTATE_NEW_HDR) {
1241 set_random_hufftable(stream, level, data, data_size);
1242 if (stream->hufftables == hufftables_subset)
1243 no_mod = 1;
1244 else
1245 no_mod = 0;
1246 }
1247
1248 ret =
1249 isal_deflate_with_checks(stream, data_size, *compressed_size, in_buf,
1250 in_size, in_processed, out_buf, out_size,
1251 out_processed);
1252
1253 if (ret) {
1254 if (ret == COMPRESS_OUT_BUFFER_OVERFLOW
1255 || ret == COMPRESS_INCORRECT_STATE)
1256 memcpy(compressed_buf + out_processed, out_buf, out_size);
1257 break;
1258 }
1259
1260 /* Check if the compression is completed */
1261 if (state->state == ZSTATE_END) {
1262 memcpy(compressed_buf + out_processed, out_buf, out_size);
1263 *compressed_size = stream->total_out;
1264 break;
1265 }
1266
1267 }
1268
1269 if (stream != NULL)
1270 free(stream);
1271 if (level_buf != NULL)
1272 free(level_buf);
1273 if (in_buf != NULL)
1274 free(in_buf);
1275 if (out_buf != NULL)
1276 free(out_buf);
1277
1278 if (ret == COMPRESS_OUT_BUFFER_OVERFLOW && flush_type == SYNC_FLUSH
1279 && loop_count >= MAX_LOOPS)
1280 ret = COMPRESS_LOOP_COUNT_OVERFLOW;
1281
1282 return ret;
1283
1284 }
1285
1286 /* Compress the input data into the outbuffer in one call to isal_deflate */
compress_single_pass(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t flush_type,uint32_t gzip_flag,uint32_t level,uint8_t * dict,uint32_t dict_len,uint32_t hist_bits)1287 int compress_single_pass(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1288 uint32_t * compressed_size, uint32_t flush_type, uint32_t gzip_flag,
1289 uint32_t level, uint8_t * dict, uint32_t dict_len, uint32_t hist_bits)
1290 {
1291 int ret = IGZIP_COMP_OK;
1292 struct isal_zstream stream;
1293 struct isal_zstate *state = &stream.internal_state;
1294 uint32_t level_buf_size;
1295 uint8_t *level_buf = NULL;
1296 struct isal_hufftables *huff_tmp;
1297 uint32_t reset_test_flag = 0;
1298 struct isal_dict dict_str;
1299
1300 log_print("Starting Compress Single Pass\n");
1301
1302 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1303
1304 isal_deflate_init(&stream);
1305
1306 set_random_hufftable(&stream, level, data, data_size);
1307
1308 if (state->state != ZSTATE_NEW_HDR)
1309 return COMPRESS_INCORRECT_STATE;
1310
1311 if (rand() % 4 == 0) {
1312 /* Test reset */
1313 reset_test_flag = 1;
1314 huff_tmp = stream.hufftables;
1315 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1316
1317 /* Restore variables not necessarily set by user */
1318 stream.hufftables = huff_tmp;
1319 stream.end_of_stream = 0;
1320 stream.level = 0;
1321 stream.level_buf = NULL;
1322 stream.level_buf_size = 0;
1323 }
1324
1325 stream.flush = flush_type;
1326 stream.avail_in = data_size;
1327 stream.next_in = data;
1328 stream.avail_out = *compressed_size;
1329 stream.next_out = compressed_buf;
1330 stream.end_of_stream = 1;
1331 stream.gzip_flag = gzip_flag;
1332 stream.level = level;
1333 stream.hist_bits = hist_bits;
1334
1335 if (level >= 1) {
1336 level_buf_size = get_rand_level_buf_size(stream.level);
1337 level_buf = malloc(level_buf_size);
1338 create_rand_repeat_data(level_buf, level_buf_size);
1339 stream.level_buf = level_buf;
1340 stream.level_buf_size = level_buf_size;
1341 }
1342
1343 if (reset_test_flag)
1344 isal_deflate_reset(&stream);
1345
1346 if (dict != NULL) {
1347 if (rand() % 2 == 0)
1348 isal_deflate_set_dict(&stream, dict, dict_len);
1349 else {
1350 isal_deflate_process_dict(&stream, &dict_str, dict, dict_len);
1351 isal_deflate_reset_dict(&stream, &dict_str);
1352 }
1353 }
1354
1355 ret =
1356 isal_deflate_with_checks(&stream, data_size, *compressed_size, data, data_size,
1357 data_size, compressed_buf, *compressed_size, 0);
1358
1359 if (level_buf != NULL)
1360 free(level_buf);
1361
1362 /* Check if the compression is completed */
1363 if (state->state == ZSTATE_END)
1364 *compressed_size = stream.total_out;
1365 else if (flush_type == SYNC_FLUSH && stream.avail_out < 16)
1366 ret = COMPRESS_OUT_BUFFER_OVERFLOW;
1367
1368 return ret;
1369
1370 }
1371
1372 /* Compress the input data repeatedly into the outbuffer
1373 * Compresses and verifies in place to decrease memory usage
1374 */
compress_ver_rep_buf(uint8_t * data,uint32_t data_size,uint64_t data_rep_size,uint8_t * compressed_buf,uint32_t compressed_size,uint8_t * decomp_buf,uint32_t decomp_buf_size,uint32_t flush_type,uint32_t gzip_flag,uint32_t level)1375 int compress_ver_rep_buf(uint8_t * data, uint32_t data_size, uint64_t data_rep_size,
1376 uint8_t * compressed_buf, uint32_t compressed_size,
1377 uint8_t * decomp_buf, uint32_t decomp_buf_size, uint32_t flush_type,
1378 uint32_t gzip_flag, uint32_t level)
1379 {
1380 int ret = IGZIP_COMP_OK;
1381 struct isal_zstream stream;
1382 struct inflate_state state;
1383 uint32_t level_buf_size;
1384 uint8_t *level_buf = NULL;
1385 uint64_t data_remaining = data_rep_size;
1386 uint64_t data_verified = 0;
1387 uint32_t index;
1388 uint32_t out_size, cmp_size;
1389 uint32_t avail_out_start;
1390
1391 log_print("Starting Compress and Verify Repeated Buffer\n");
1392
1393 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1394
1395 /* Setup compression stream */
1396 isal_deflate_init(&stream);
1397 stream.avail_in = 0;
1398 stream.next_in = NULL;
1399 stream.avail_out = 0;
1400 stream.next_out = NULL;
1401
1402 set_random_hufftable(&stream, level, data, data_size);
1403 stream.flush = flush_type;
1404 stream.end_of_stream = 0;
1405 stream.gzip_flag = gzip_flag;
1406 stream.level = level;
1407
1408 if (level >= 1) {
1409 level_buf_size = get_rand_level_buf_size(stream.level);
1410 level_buf = malloc(level_buf_size);
1411 create_rand_repeat_data(level_buf, level_buf_size);
1412 stream.level_buf = level_buf;
1413 stream.level_buf_size = level_buf_size;
1414 }
1415
1416 /* Setup decompression stream */
1417 create_rand_repeat_data((uint8_t *) & state, sizeof(state));
1418 isal_inflate_init(&state);
1419 state.crc_flag = gzip_flag;
1420
1421 while (data_remaining || stream.avail_in) {
1422 /* Compress the input buffer */
1423 if (stream.next_out == NULL) {
1424 stream.avail_out = compressed_size;
1425 stream.next_out = compressed_buf;
1426 }
1427
1428 while (stream.avail_out > 0 && (data_remaining || stream.avail_in)) {
1429 if (stream.avail_in == 0) {
1430 stream.avail_in = data_size;
1431 if (data_size >= data_remaining) {
1432 stream.avail_in = data_remaining;
1433 stream.end_of_stream = 1;
1434 }
1435
1436 stream.next_in = data;
1437 data_remaining -= stream.avail_in;
1438 }
1439
1440 ret = isal_deflate(&stream);
1441
1442 if (ret)
1443 return COMPRESS_GENERAL_ERROR;
1444 }
1445
1446 /* Verfiy the compressed buffer */
1447 state.next_in = compressed_buf;
1448 state.avail_in = compressed_size;
1449 state.next_out = NULL;
1450 state.avail_out = 0;
1451 create_rand_repeat_data(decomp_buf, decomp_buf_size);
1452
1453 while (state.avail_out == 0) {
1454 state.next_out = decomp_buf;
1455 state.avail_out = decomp_buf_size;
1456
1457 /* Force decoding to stop when avail_out rolls over */
1458 if ((1ULL << 32) - state.total_out < decomp_buf_size)
1459 state.avail_out = (1ULL << 32) - state.total_out;
1460
1461 avail_out_start = state.avail_out;
1462
1463 ret = isal_inflate(&state);
1464 if (ret)
1465 return inflate_ret_to_code(ret);
1466
1467 /* Check data accuracy */
1468 index = data_verified % data_size;
1469 out_size = avail_out_start - state.avail_out;
1470 cmp_size =
1471 (out_size > data_size - index) ? data_size - index : out_size;
1472 ret |= memcmp(decomp_buf, data + index, cmp_size);
1473 out_size -= cmp_size;
1474 cmp_size = (out_size > index) ? index : out_size;
1475 ret |= memcmp(decomp_buf + data_size - index, data, cmp_size);
1476 out_size -= cmp_size;
1477 cmp_size = out_size;
1478 ret |= memcmp(decomp_buf, decomp_buf + data_size, out_size);
1479 if (ret)
1480 return RESULT_ERROR;
1481
1482 data_verified += avail_out_start - state.avail_out;
1483 }
1484 stream.next_out = NULL;
1485 }
1486
1487 if (level_buf != NULL)
1488 free(level_buf);
1489
1490 return ret;
1491
1492 }
1493
1494 /* Statelessly compress the input buffer into the output buffer */
compress_stateless(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t flush_type,uint32_t gzip_flag,uint32_t level,uint32_t hist_bits)1495 int compress_stateless(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1496 uint32_t * compressed_size, uint32_t flush_type, uint32_t gzip_flag,
1497 uint32_t level, uint32_t hist_bits)
1498 {
1499 int ret = IGZIP_COMP_OK;
1500 struct isal_zstream stream;
1501 uint32_t level_buf_size;
1502 uint8_t *level_buf = NULL;
1503 struct isal_hufftables *huff_tmp;
1504 uint32_t reset_test_flag = 0;
1505
1506 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1507
1508 isal_deflate_stateless_init(&stream);
1509
1510 set_random_hufftable(&stream, level, data, data_size);
1511
1512 if (rand() % 4 == 0) {
1513 /* Test reset */
1514 reset_test_flag = 1;
1515 huff_tmp = stream.hufftables;
1516 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1517
1518 /* Restore variables not necessarily set by user */
1519 stream.hufftables = huff_tmp;
1520 stream.end_of_stream = 0;
1521 stream.level = 0;
1522 stream.level_buf = NULL;
1523 stream.level_buf_size = 0;
1524 }
1525
1526 stream.avail_in = data_size;
1527 stream.next_in = data;
1528 stream.flush = flush_type;
1529 if (flush_type != NO_FLUSH)
1530 stream.end_of_stream = 1;
1531 stream.avail_out = *compressed_size;
1532 stream.next_out = compressed_buf;
1533 stream.gzip_flag = gzip_flag;
1534 stream.level = level;
1535 stream.hist_bits = hist_bits;
1536
1537 if (level == 1) {
1538 /* This is to test case where level buf uses already existing
1539 * internal buffers */
1540 level_buf_size = rand() % IBUF_SIZE;
1541
1542 if (level_buf_size >= ISAL_DEF_LVL1_MIN) {
1543 level_buf = malloc(level_buf_size);
1544 create_rand_repeat_data(level_buf, level_buf_size);
1545 stream.level_buf = level_buf;
1546 stream.level_buf_size = level_buf_size;
1547 }
1548 } else if (level > 1) {
1549 level_buf_size = get_rand_level_buf_size(level);
1550 level_buf = malloc(level_buf_size);
1551 create_rand_repeat_data(level_buf, level_buf_size);
1552 stream.level_buf = level_buf;
1553 stream.level_buf_size = level_buf_size;
1554 }
1555
1556 if (reset_test_flag)
1557 isal_deflate_reset(&stream);
1558
1559 ret = isal_deflate_stateless(&stream);
1560
1561 if (level_buf != NULL)
1562 free(level_buf);
1563
1564 /* verify the stream */
1565 if (stream.next_in - data != stream.total_in ||
1566 stream.total_in + stream.avail_in != data_size)
1567 return COMPRESS_INPUT_STREAM_INTEGRITY_ERROR;
1568
1569 if (stream.next_out - compressed_buf != stream.total_out ||
1570 stream.total_out + stream.avail_out != *compressed_size) {
1571 return COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR;
1572 }
1573
1574 if (ret != IGZIP_COMP_OK) {
1575 if (ret == STATELESS_OVERFLOW)
1576 return COMPRESS_OUT_BUFFER_OVERFLOW;
1577 else if (ret == INVALID_FLUSH)
1578 return INVALID_FLUSH_ERROR;
1579 else {
1580 printf("Return due to ret = %d with level = %d or %d\n", ret, level,
1581 stream.level);
1582 return COMPRESS_GENERAL_ERROR;
1583 }
1584 }
1585
1586 if (!stream.end_of_stream) {
1587 return COMPRESS_END_OF_STREAM_NOT_SET;
1588 }
1589
1590 if (stream.avail_in != 0)
1591 return COMPRESS_ALL_INPUT_FAIL;
1592
1593 *compressed_size = stream.total_out;
1594
1595 return ret;
1596
1597 }
1598
1599 /* Statelessly compress the input buffer into the output buffer */
compress_stateless_full_flush(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t level,uint32_t hist_bits)1600 int compress_stateless_full_flush(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1601 uint32_t * compressed_size, uint32_t level,
1602 uint32_t hist_bits)
1603 {
1604 int ret = IGZIP_COMP_OK;
1605 uint8_t *in_buf = NULL, *level_buf = NULL, *out_buf = compressed_buf;
1606 uint32_t in_size = 0, level_buf_size;
1607 uint32_t in_processed = 00;
1608 struct isal_zstream stream;
1609 uint32_t loop_count = 0;
1610 struct isal_hufftables *huff_tmp;
1611 uint32_t reset_test_flag = 0;
1612
1613 log_print("Starting Stateless Compress Full Flush\n");
1614
1615 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1616
1617 isal_deflate_stateless_init(&stream);
1618
1619 if (rand() % 4 == 0) {
1620 /* Test reset */
1621 reset_test_flag = 1;
1622 huff_tmp = stream.hufftables;
1623 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1624
1625 /* Restore variables not necessarily set by user */
1626 stream.hufftables = huff_tmp;
1627 stream.end_of_stream = 0;
1628 stream.level = 0;
1629 stream.level_buf = NULL;
1630 stream.level_buf_size = 0;
1631 stream.gzip_flag = 0;
1632 }
1633
1634 stream.flush = FULL_FLUSH;
1635 stream.end_of_stream = 0;
1636 stream.avail_out = *compressed_size;
1637 stream.next_out = compressed_buf;
1638 stream.level = level;
1639 stream.hist_bits = hist_bits;
1640
1641 if (level == 1) {
1642 /* This is to test case where level_buf uses already existing
1643 * internal buffers */
1644 level_buf_size = rand() % IBUF_SIZE;
1645
1646 if (level_buf_size >= ISAL_DEF_LVL1_MIN) {
1647 level_buf = malloc(level_buf_size);
1648 create_rand_repeat_data(level_buf, level_buf_size);
1649 stream.level_buf = level_buf;
1650 stream.level_buf_size = level_buf_size;
1651 }
1652 } else if (level > 1) {
1653 level_buf_size = get_rand_level_buf_size(level);
1654 level_buf = malloc(level_buf_size);
1655 create_rand_repeat_data(level_buf, level_buf_size);
1656 stream.level_buf = level_buf;
1657 stream.level_buf_size = level_buf_size;
1658 }
1659
1660 if (reset_test_flag)
1661 isal_deflate_reset(&stream);
1662
1663 while (1) {
1664 loop_count++;
1665
1666 /* Randomly choose size of the next out buffer */
1667 in_size = rand() % (data_size + 1);
1668
1669 /* Limit size of buffer to be smaller than maximum */
1670 if (in_size >= data_size - in_processed) {
1671 in_size = data_size - in_processed;
1672 stream.end_of_stream = 1;
1673 }
1674
1675 stream.avail_in = in_size;
1676
1677 if (in_size != 0) {
1678 if (in_buf != NULL) {
1679 free(in_buf);
1680 in_buf = NULL;
1681 }
1682
1683 in_buf = malloc(in_size);
1684 if (in_buf == NULL) {
1685 ret = MALLOC_FAILED;
1686 break;
1687 }
1688 memcpy(in_buf, data + in_processed, in_size);
1689 in_processed += in_size;
1690
1691 stream.next_in = in_buf;
1692 }
1693
1694 out_buf = stream.next_out;
1695
1696 if (stream.internal_state.state == ZSTATE_NEW_HDR)
1697 set_random_hufftable(&stream, level, data, data_size);
1698
1699 ret = isal_deflate_stateless(&stream);
1700
1701 assert(stream.internal_state.bitbuf.m_bit_count == 0);
1702
1703 assert(compressed_buf == stream.next_out - stream.total_out);
1704 if (ret)
1705 break;
1706
1707 /* Verify that blocks are independent */
1708 ret =
1709 inflate_check(out_buf, stream.next_out - out_buf, in_buf, in_size, 0, NULL,
1710 0, hist_bits);
1711
1712 if (ret == INFLATE_INVALID_LOOK_BACK_DISTANCE) {
1713 break;
1714 } else
1715 ret = 0;
1716
1717 /* Check if the compression is completed */
1718 if (in_processed == data_size) {
1719 *compressed_size = stream.total_out;
1720 break;
1721 }
1722
1723 }
1724
1725 if (level_buf != NULL)
1726 free(level_buf);
1727
1728 if (in_buf != NULL)
1729 free(in_buf);
1730
1731 if (ret == STATELESS_OVERFLOW && loop_count >= MAX_LOOPS)
1732 ret = COMPRESS_LOOP_COUNT_OVERFLOW;
1733
1734 return ret;
1735
1736 }
1737
1738 /* Compress the input data into the output buffer where the input buffer and
1739 * is randomly segmented to test for independence of blocks in full flush
1740 * compression*/
compress_full_flush(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t gzip_flag,uint32_t level)1741 int compress_full_flush(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1742 uint32_t * compressed_size, uint32_t gzip_flag, uint32_t level)
1743 {
1744 int ret = IGZIP_COMP_OK;
1745 uint8_t *in_buf = NULL, *out_buf = compressed_buf, *level_buf = NULL;
1746 uint32_t in_size = 0, level_buf_size;
1747 uint32_t in_processed = 00;
1748 struct isal_zstream stream;
1749 struct isal_zstate *state = &stream.internal_state;
1750 uint32_t loop_count = 0;
1751 struct isal_hufftables *huff_tmp;
1752 uint32_t reset_test_flag = 0;
1753
1754 log_print("Starting Compress Full Flush\n");
1755
1756 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1757
1758 isal_deflate_init(&stream);
1759
1760 if (state->state != ZSTATE_NEW_HDR)
1761 return COMPRESS_INCORRECT_STATE;
1762
1763 if (rand() % 4 == 0) {
1764 /* Test reset */
1765 reset_test_flag = 1;
1766 huff_tmp = stream.hufftables;
1767 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1768
1769 /* Restore variables not necessarily set by user */
1770 stream.hufftables = huff_tmp;
1771 stream.end_of_stream = 0;
1772 stream.level = 0;
1773 stream.level_buf = NULL;
1774 stream.level_buf_size = 0;
1775 stream.hist_bits = 0;
1776 }
1777
1778 stream.flush = FULL_FLUSH;
1779 stream.end_of_stream = 0;
1780 stream.avail_out = *compressed_size;
1781 stream.next_out = compressed_buf;
1782 stream.total_out = 0;
1783 stream.gzip_flag = gzip_flag;
1784 stream.level = level;
1785
1786 if (level >= 1) {
1787 level_buf_size = get_rand_level_buf_size(stream.level);
1788 if (level_buf_size >= ISAL_DEF_LVL1_MIN) {
1789 level_buf = malloc(level_buf_size);
1790 create_rand_repeat_data(level_buf, level_buf_size);
1791 stream.level_buf = level_buf;
1792 stream.level_buf_size = level_buf_size;
1793 }
1794 }
1795
1796 if (reset_test_flag)
1797 isal_deflate_reset(&stream);
1798
1799 while (1) {
1800 loop_count++;
1801
1802 /* Setup in buffer for next round of compression */
1803 if (state->state == ZSTATE_NEW_HDR) {
1804 /* Randomly choose size of the next out buffer */
1805 in_size = rand() % (data_size + 1);
1806
1807 /* Limit size of buffer to be smaller than maximum */
1808 if (in_size >= data_size - in_processed) {
1809 in_size = data_size - in_processed;
1810 stream.end_of_stream = 1;
1811 }
1812
1813 stream.avail_in = in_size;
1814
1815 if (in_size != 0) {
1816 if (in_buf != NULL) {
1817 free(in_buf);
1818 in_buf = NULL;
1819 }
1820
1821 in_buf = malloc(in_size);
1822 if (in_buf == NULL) {
1823 ret = MALLOC_FAILED;
1824 break;
1825 }
1826 memcpy(in_buf, data + in_processed, in_size);
1827 in_processed += in_size;
1828
1829 stream.next_in = in_buf;
1830 }
1831
1832 out_buf = stream.next_out;
1833 }
1834
1835 if (state->state == ZSTATE_NEW_HDR)
1836 set_random_hufftable(&stream, level, data, data_size);
1837
1838 ret = isal_deflate(&stream);
1839
1840 if (ret)
1841 break;
1842
1843 /* Verify that blocks are independent */
1844 if (state->state == ZSTATE_NEW_HDR || state->state == ZSTATE_END) {
1845 ret =
1846 inflate_check(out_buf, stream.next_out - out_buf, in_buf, in_size,
1847 0, NULL, 0, 0);
1848
1849 if (ret == INFLATE_INVALID_LOOK_BACK_DISTANCE)
1850 break;
1851 else
1852 ret = 0;
1853 }
1854
1855 /* Check if the compression is completed */
1856 if (state->state == ZSTATE_END) {
1857 *compressed_size = stream.total_out;
1858 break;
1859 }
1860
1861 }
1862
1863 if (level_buf != NULL)
1864 free(level_buf);
1865
1866 if (in_buf != NULL)
1867 free(in_buf);
1868
1869 if (ret == COMPRESS_OUT_BUFFER_OVERFLOW && loop_count >= MAX_LOOPS)
1870 ret = COMPRESS_LOOP_COUNT_OVERFLOW;
1871
1872 return ret;
1873
1874 }
1875
1876 /*Compress the input buffer into the output buffer, but switch the flush type in
1877 * the middle of the compression to test what happens*/
compress_swap_flush(uint8_t * data,uint32_t data_size,uint8_t * compressed_buf,uint32_t * compressed_size,uint32_t flush_type,int level,uint32_t gzip_flag)1878 int compress_swap_flush(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
1879 uint32_t * compressed_size, uint32_t flush_type, int level,
1880 uint32_t gzip_flag)
1881 {
1882 int ret = IGZIP_COMP_OK;
1883 struct isal_zstream stream;
1884 struct isal_zstate *state = &stream.internal_state;
1885 uint32_t partial_size;
1886 struct isal_hufftables *huff_tmp;
1887 uint32_t reset_test_flag = 0;
1888 uint32_t level_buf_size;
1889 uint8_t *level_buf = NULL;
1890
1891 log_print("Starting Compress Swap Flush\n");
1892
1893 isal_deflate_init(&stream);
1894
1895 set_random_hufftable(&stream, 0, data, data_size);
1896
1897 if (state->state != ZSTATE_NEW_HDR)
1898 return COMPRESS_INCORRECT_STATE;
1899
1900 if (rand() % 4 == 0) {
1901 /* Test reset */
1902 reset_test_flag = 1;
1903 huff_tmp = stream.hufftables;
1904 create_rand_repeat_data((uint8_t *) & stream, sizeof(stream));
1905
1906 /* Restore variables not necessarily set by user */
1907 stream.hufftables = huff_tmp;
1908 stream.end_of_stream = 0;
1909 stream.level = 0;
1910 stream.level_buf = NULL;
1911 stream.level_buf_size = 0;
1912 }
1913
1914 partial_size = rand() % (data_size + 1);
1915
1916 stream.flush = flush_type;
1917 stream.avail_in = partial_size;
1918 stream.next_in = data;
1919 stream.avail_out = *compressed_size;
1920 stream.next_out = compressed_buf;
1921 stream.end_of_stream = 0;
1922 stream.gzip_flag = gzip_flag;
1923 if (level) {
1924 stream.level = level;
1925 level_buf_size = get_rand_level_buf_size(stream.level);
1926 level_buf = malloc(level_buf_size);
1927 create_rand_repeat_data(level_buf, level_buf_size);
1928 stream.level_buf = level_buf;
1929 stream.level_buf_size = level_buf_size;
1930 }
1931
1932 if (reset_test_flag)
1933 isal_deflate_reset(&stream);
1934
1935 ret =
1936 isal_deflate_with_checks(&stream, data_size, *compressed_size, data, partial_size,
1937 partial_size, compressed_buf, *compressed_size, 0);
1938
1939 if (ret)
1940 return ret;
1941
1942 if (state->state == ZSTATE_NEW_HDR)
1943 set_random_hufftable(&stream, 0, data, data_size);
1944
1945 flush_type = rand() % 3;
1946
1947 stream.flush = flush_type;
1948 stream.avail_in = data_size - partial_size;
1949 stream.next_in = data + partial_size;
1950 stream.end_of_stream = 1;
1951
1952 ret =
1953 isal_deflate_with_checks(&stream, data_size, *compressed_size, data + partial_size,
1954 data_size - partial_size, data_size, compressed_buf,
1955 *compressed_size, 0);
1956
1957 if (ret == COMPRESS_GENERAL_ERROR)
1958 return INVALID_FLUSH_ERROR;
1959
1960 *compressed_size = stream.total_out;
1961
1962 if (stream.level_buf != NULL)
1963 free(stream.level_buf);
1964
1965 return ret;
1966 }
1967
1968 /* Test deflate_stateless */
test_compress_stateless(uint8_t * in_data,uint32_t in_size,uint32_t flush_type)1969 int test_compress_stateless(uint8_t * in_data, uint32_t in_size, uint32_t flush_type)
1970 {
1971 int ret = IGZIP_COMP_OK;
1972 uint32_t z_size, overflow, gzip_flag, level, hist_bits;
1973 uint8_t *z_buf = NULL;
1974 uint8_t *in_buf = NULL;
1975
1976 gzip_flag = rand() % 5;
1977 hist_bits = rand() % 16;
1978 level = get_rand_level();
1979
1980 if (in_size != 0) {
1981 in_buf = malloc(in_size);
1982
1983 if (in_buf == NULL)
1984 return MALLOC_FAILED;
1985
1986 memcpy(in_buf, in_data, in_size);
1987 }
1988
1989 /* Test non-overflow case where a type 0 block is not written */
1990 z_size = 2 * in_size + hdr_bytes;
1991 if (gzip_flag == IGZIP_GZIP)
1992 z_size += gzip_extra_bytes;
1993 else if (gzip_flag == IGZIP_GZIP_NO_HDR)
1994 z_size += gzip_trl_bytes;
1995 else if (gzip_flag == IGZIP_ZLIB)
1996 z_size += zlib_extra_bytes;
1997 else if (gzip_flag == IGZIP_ZLIB_NO_HDR)
1998 z_size += zlib_trl_bytes;
1999
2000 z_buf = malloc(z_size);
2001
2002 if (z_buf == NULL)
2003 return MALLOC_FAILED;
2004
2005 create_rand_repeat_data(z_buf, z_size);
2006
2007 /* If flush type is invalid */
2008 if (flush_type != NO_FLUSH && flush_type != FULL_FLUSH) {
2009 ret =
2010 compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag,
2011 level, hist_bits);
2012
2013 if (ret != INVALID_FLUSH_ERROR)
2014 print_error(ret);
2015 else
2016 ret = 0;
2017
2018 if (z_buf != NULL)
2019 free(z_buf);
2020
2021 if (in_buf != NULL)
2022 free(in_buf);
2023
2024 return ret;
2025 }
2026
2027 /* Else test valid flush type */
2028 ret = compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level,
2029 hist_bits);
2030
2031 if (!ret)
2032 ret =
2033 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0,
2034 hist_bits);
2035
2036 if (options.verbose && ret) {
2037 log_print
2038 ("Compressed array at level %d with gzip flag %d, flush type %d, and window bits %d: ",
2039 level, gzip_flag, flush_type, hist_bits);
2040 log_uint8_t(z_buf, z_size);
2041 log_print("\n");
2042 log_print("Data: ");
2043 log_uint8_t(in_buf, in_size);
2044 }
2045
2046 if (z_buf != NULL) {
2047 free(z_buf);
2048 z_buf = NULL;
2049 }
2050
2051 print_error(ret);
2052 if (ret)
2053 return ret;
2054
2055 /*Test non-overflow case where a type 0 block is possible to be written */
2056 z_size = TYPE0_HDR_SIZE * ((in_size + TYPE0_MAX_SIZE - 1) / TYPE0_MAX_SIZE) + in_size;
2057
2058 if (gzip_flag == IGZIP_GZIP)
2059 z_size += gzip_extra_bytes;
2060 else if (gzip_flag == IGZIP_GZIP_NO_HDR)
2061 z_size += gzip_trl_bytes;
2062 else if (gzip_flag == IGZIP_ZLIB)
2063 z_size += zlib_extra_bytes;
2064 else if (gzip_flag == IGZIP_ZLIB_NO_HDR)
2065 z_size += zlib_trl_bytes;
2066
2067 if (z_size <= gzip_extra_bytes)
2068 z_size += TYPE0_HDR_SIZE;
2069
2070 if (z_size < 8)
2071 z_size = 8;
2072
2073 z_buf = malloc(z_size);
2074
2075 if (z_buf == NULL)
2076 return MALLOC_FAILED;
2077
2078 create_rand_repeat_data(z_buf, z_size);
2079
2080 ret = compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level,
2081 hist_bits);
2082 if (!ret)
2083 ret =
2084 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0,
2085 hist_bits);
2086 if (ret) {
2087 log_print
2088 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2089 level, gzip_flag, flush_type, hist_bits);
2090 log_uint8_t(z_buf, z_size);
2091 log_print("\n");
2092 log_print("Data: ");
2093 log_uint8_t(in_buf, in_size);
2094 }
2095
2096 if (!ret) {
2097 free(z_buf);
2098 z_buf = NULL;
2099
2100 /* Test random overflow case */
2101 z_size = rand() % z_size;
2102
2103 if (z_size > in_size)
2104 z_size = rand() & in_size;
2105
2106 if (z_size > 0) {
2107 z_buf = malloc(z_size);
2108
2109 if (z_buf == NULL)
2110 return MALLOC_FAILED;
2111 }
2112
2113 overflow = compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type,
2114 gzip_flag, level, hist_bits);
2115
2116 if (overflow != COMPRESS_OUT_BUFFER_OVERFLOW) {
2117 if (overflow == 0)
2118 ret =
2119 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag,
2120 NULL, 0, hist_bits);
2121
2122 if (overflow != 0 || ret != 0) {
2123 log_print("overflow error = %d\n", overflow);
2124 log_error(overflow);
2125 log_print("inflate ret = %d\n", ret);
2126 log_error(ret);
2127
2128 log_print
2129 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2130 level, gzip_flag, flush_type, hist_bits);
2131
2132 log_uint8_t(z_buf, z_size);
2133 log_print("\n");
2134 log_print("Data: ");
2135 log_uint8_t(in_buf, in_size);
2136
2137 printf("Failed on compress single pass overflow\n");
2138 print_error(ret);
2139 ret = OVERFLOW_TEST_ERROR;
2140 }
2141 }
2142 }
2143
2144 print_error(ret);
2145 if (ret) {
2146 if (z_buf != NULL) {
2147 free(z_buf);
2148 z_buf = NULL;
2149 }
2150 if (in_buf != NULL)
2151 free(in_buf);
2152 return ret;
2153 }
2154
2155 if (flush_type == FULL_FLUSH) {
2156 if (z_buf != NULL)
2157 free(z_buf);
2158
2159 z_size = 2 * in_size + MAX_LOOPS * (hdr_bytes + 5);
2160
2161 z_buf = malloc(z_size);
2162
2163 if (z_buf == NULL)
2164 return MALLOC_FAILED;
2165
2166 create_rand_repeat_data(z_buf, z_size);
2167
2168 /* Else test valid flush type */
2169 ret = compress_stateless_full_flush(in_buf, in_size, z_buf, &z_size,
2170 level, hist_bits);
2171
2172 if (!ret)
2173 ret =
2174 inflate_check(z_buf, z_size, in_buf, in_size, 0, NULL, 0,
2175 hist_bits);
2176 else if (ret == COMPRESS_LOOP_COUNT_OVERFLOW)
2177 ret = 0;
2178
2179 print_error(ret);
2180
2181 if (ret) {
2182 log_print
2183 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2184 level, gzip_flag, FULL_FLUSH, hist_bits);
2185 log_uint8_t(z_buf, z_size);
2186 log_print("\n");
2187 log_print("Data: ");
2188 log_uint8_t(in_buf, in_size);
2189 }
2190 }
2191 if (z_buf != NULL)
2192 free(z_buf);
2193
2194 if (in_buf != NULL)
2195 free(in_buf);
2196
2197 return ret;
2198 }
2199
2200 /* Test deflate */
test_compress(uint8_t * in_buf,uint32_t in_size,uint32_t flush_type)2201 int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
2202 {
2203 int ret = IGZIP_COMP_OK, fin_ret = IGZIP_COMP_OK;
2204 uint32_t overflow = 0, gzip_flag, level, hist_bits;
2205 uint32_t z_size = 0, z_size_max = 0, z_compressed_size, dict_len = 0;
2206 uint8_t *z_buf = NULL, *dict = NULL;
2207
2208 /* Test a non overflow case */
2209 if (flush_type == NO_FLUSH)
2210 z_size_max = 2 * in_size + hdr_bytes + 2;
2211 else if (flush_type == SYNC_FLUSH || flush_type == FULL_FLUSH)
2212 z_size_max = 2 * in_size + MAX_LOOPS * (hdr_bytes + 5);
2213 else {
2214 printf("Invalid Flush Parameter\n");
2215 return COMPRESS_GENERAL_ERROR;
2216 }
2217
2218 gzip_flag = rand() % 5;
2219 hist_bits = rand() % 16;
2220 level = get_rand_level();
2221
2222 z_size = z_size_max;
2223
2224 if (gzip_flag == IGZIP_GZIP)
2225 z_size += gzip_extra_bytes;
2226 else if (gzip_flag == IGZIP_GZIP_NO_HDR)
2227 z_size += gzip_trl_bytes;
2228 else if (gzip_flag == IGZIP_ZLIB)
2229 z_size += zlib_extra_bytes;
2230 else if (gzip_flag == IGZIP_ZLIB_NO_HDR)
2231 z_size += zlib_trl_bytes;
2232
2233 z_buf = malloc(z_size);
2234 if (z_buf == NULL) {
2235 print_error(MALLOC_FAILED);
2236 return MALLOC_FAILED;
2237 }
2238 create_rand_repeat_data(z_buf, z_size);
2239
2240 if (rand() % 8 == 0) {
2241 dict_len = (rand() % IGZIP_HIST_SIZE) + 1;
2242 dict = malloc(dict_len);
2243 if (dict == NULL) {
2244 print_error(MALLOC_FAILED);
2245 return MALLOC_FAILED;
2246 }
2247 create_rand_dict(dict, dict_len, z_buf, z_size);
2248 }
2249
2250 ret = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
2251 gzip_flag, level, dict, dict_len, hist_bits);
2252
2253 if (!ret)
2254 ret =
2255 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict, dict_len,
2256 hist_bits);
2257
2258 if (ret) {
2259 log_print
2260 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2261 level, gzip_flag, flush_type, hist_bits);
2262 log_uint8_t(z_buf, z_size);
2263 log_print("\n");
2264 if (dict != NULL) {
2265 log_print("Using Dictionary: ");
2266 log_uint8_t(dict, dict_len);
2267 log_print("\n");
2268 }
2269 log_print("Data: ");
2270 log_uint8_t(in_buf, in_size);
2271
2272 printf("Failed on compress single pass\n");
2273 print_error(ret);
2274 }
2275
2276 if (dict != NULL) {
2277 free(dict);
2278 dict = NULL;
2279 dict_len = 0;
2280 }
2281
2282 fin_ret |= ret;
2283 if (ret)
2284 goto test_compress_cleanup;
2285
2286 z_compressed_size = z_size;
2287 z_size = z_size_max;
2288 create_rand_repeat_data(z_buf, z_size_max);
2289
2290 if (rand() % 8 == 0) {
2291 dict_len = (rand() % IGZIP_HIST_SIZE) + 1;
2292 dict = malloc(dict_len);
2293 if (dict == NULL) {
2294 print_error(MALLOC_FAILED);
2295 return MALLOC_FAILED;
2296 }
2297 create_rand_dict(dict, dict_len, z_buf, z_size);
2298 }
2299
2300 ret =
2301 compress_multi_pass(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level,
2302 dict, dict_len, hist_bits);
2303
2304 if (!ret)
2305 ret =
2306 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict, dict_len,
2307 hist_bits);
2308
2309 if (ret) {
2310 log_print
2311 ("Compressed array at level %d with gzip flag %d, flush type %d and hist_bits %d: ",
2312 level, gzip_flag, flush_type, hist_bits);
2313 log_uint8_t(z_buf, z_size);
2314 log_print("\n");
2315 if (dict != NULL) {
2316 log_print("Using Dictionary: ");
2317 log_uint8_t(dict, dict_len);
2318 log_print("\n");
2319 }
2320 log_print("Data: ");
2321 log_uint8_t(in_buf, in_size);
2322
2323 printf("Failed on compress multi pass\n");
2324 print_error(ret);
2325 }
2326
2327 if (dict != NULL) {
2328 free(dict);
2329 dict = NULL;
2330 dict_len = 0;
2331 }
2332
2333 fin_ret |= ret;
2334 if (ret)
2335 goto test_compress_cleanup;
2336
2337 ret = 0;
2338
2339 /* Test random overflow case */
2340 if (flush_type == SYNC_FLUSH && z_compressed_size > in_size)
2341 z_compressed_size = in_size + 1;
2342
2343 z_size = rand() % z_compressed_size;
2344 create_rand_repeat_data(z_buf, z_size);
2345
2346 overflow = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
2347 gzip_flag, level, dict, dict_len, hist_bits);
2348
2349 if (overflow != COMPRESS_OUT_BUFFER_OVERFLOW) {
2350 if (overflow == 0)
2351 ret =
2352 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict,
2353 dict_len, hist_bits);
2354
2355 /* Rarely single pass overflow will compresses data
2356 * better than the initial run. This is to stop that
2357 * case from erroring. */
2358 if (overflow != 0 || ret != 0) {
2359 log_print("overflow error = %d\n", overflow);
2360 log_error(overflow);
2361 log_print("inflate ret = %d\n", ret);
2362 log_error(ret);
2363
2364 log_print
2365 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2366 level, gzip_flag, flush_type, hist_bits);
2367 log_uint8_t(z_buf, z_size);
2368 log_print("\n");
2369 log_print("Data: ");
2370 log_uint8_t(in_buf, in_size);
2371
2372 printf("Failed on compress single pass overflow\n");
2373 print_error(ret);
2374 ret = OVERFLOW_TEST_ERROR;
2375 }
2376 }
2377
2378 fin_ret |= ret;
2379 if (ret)
2380 goto test_compress_cleanup;
2381
2382 if (flush_type == NO_FLUSH) {
2383 create_rand_repeat_data(z_buf, z_size);
2384
2385 overflow =
2386 compress_multi_pass(in_buf, in_size, z_buf, &z_size, flush_type,
2387 gzip_flag, level, dict, dict_len, hist_bits);
2388
2389 if (overflow != COMPRESS_OUT_BUFFER_OVERFLOW) {
2390 if (overflow == 0)
2391 ret =
2392 inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag,
2393 dict, dict_len, hist_bits);
2394
2395 /* Rarely multi pass overflow will compresses data
2396 * better than the initial run. This is to stop that
2397 * case from erroring */
2398 if (overflow != 0 || ret != 0) {
2399 log_print("overflow error = %d\n", overflow);
2400 log_error(overflow);
2401 log_print("inflate ret = %d\n", ret);
2402 log_error(ret);
2403 log_print
2404 ("Compressed array at level %d with gzip flag %d, flush type %d, and hist_bits %d: ",
2405 level, gzip_flag, flush_type, hist_bits);
2406 log_uint8_t(z_buf, z_size);
2407 log_print("\n");
2408 log_print("Data: ");
2409 log_uint8_t(in_buf, in_size);
2410
2411 printf("Failed on compress multi pass overflow\n");
2412 print_error(ret);
2413 ret = OVERFLOW_TEST_ERROR;
2414 }
2415 }
2416 fin_ret |= ret;
2417 }
2418
2419 test_compress_cleanup:
2420 free(z_buf);
2421
2422 return fin_ret;
2423 }
2424
2425 /* Test swapping flush types in the middle of compression */
test_flush(uint8_t * in_buf,uint32_t in_size)2426 int test_flush(uint8_t * in_buf, uint32_t in_size)
2427 {
2428 int fin_ret = IGZIP_COMP_OK, ret;
2429 uint32_t z_size, flush_type = 0, gzip_flag, level;
2430 uint8_t *z_buf = NULL;
2431
2432 gzip_flag = rand() % 5;
2433 level = get_rand_level();
2434
2435 z_size = 2 * in_size + 2 * hdr_bytes + 8;
2436 if (gzip_flag == IGZIP_GZIP)
2437 z_size += gzip_extra_bytes;
2438 else if (gzip_flag == IGZIP_GZIP_NO_HDR)
2439 z_size += gzip_trl_bytes;
2440 else if (gzip_flag == IGZIP_ZLIB)
2441 z_size += zlib_extra_bytes;
2442 else if (gzip_flag == IGZIP_ZLIB_NO_HDR)
2443 z_size += zlib_trl_bytes;
2444
2445 z_buf = malloc(z_size);
2446
2447 if (z_buf == NULL)
2448 return MALLOC_FAILED;
2449
2450 create_rand_repeat_data(z_buf, z_size);
2451
2452 while (flush_type < 3)
2453 flush_type = rand() & 0xFFFF;
2454
2455 /* Test invalid flush */
2456 ret = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
2457 gzip_flag, level, NULL, 0, 0);
2458
2459 if (ret == COMPRESS_GENERAL_ERROR)
2460 ret = 0;
2461 else {
2462 printf("Failed when passing invalid flush parameter\n");
2463 ret = INVALID_FLUSH_ERROR;
2464 }
2465
2466 fin_ret |= ret;
2467 print_error(ret);
2468
2469 create_rand_repeat_data(z_buf, z_size);
2470
2471 /* Test swapping flush type */
2472 ret =
2473 compress_swap_flush(in_buf, in_size, z_buf, &z_size, rand() % 3, level, gzip_flag);
2474
2475 if (!ret)
2476 ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0, 0);
2477
2478 if (ret) {
2479 log_print("Compressed array at level %d with gzip flag %d: ", level,
2480 gzip_flag);
2481 log_uint8_t(z_buf, z_size);
2482 log_print("\n");
2483 log_print("Data: ");
2484 log_uint8_t(in_buf, in_size);
2485
2486 printf("Failed on swapping flush type\n");
2487 print_error(ret);
2488 }
2489
2490 fin_ret |= ret;
2491 print_error(ret);
2492
2493 return fin_ret;
2494 }
2495
2496 /* Test there are no length distance pairs across full flushes */
test_full_flush(uint8_t * in_buf,uint32_t in_size)2497 int test_full_flush(uint8_t * in_buf, uint32_t in_size)
2498 {
2499 int ret = IGZIP_COMP_OK;
2500 uint32_t z_size, gzip_flag, level;
2501 uint8_t *z_buf = NULL;
2502
2503 gzip_flag = rand() % 5;
2504 level = get_rand_level();
2505 z_size = 2 * in_size + MAX_LOOPS * (hdr_bytes + 5);
2506
2507 if (gzip_flag == IGZIP_GZIP)
2508 z_size += gzip_extra_bytes;
2509 else if (gzip_flag == IGZIP_GZIP_NO_HDR)
2510 z_size += gzip_trl_bytes;
2511 else if (gzip_flag == IGZIP_ZLIB)
2512 z_size += zlib_extra_bytes;
2513 else if (gzip_flag == IGZIP_ZLIB_NO_HDR)
2514 z_size += zlib_trl_bytes;
2515
2516 z_buf = malloc(z_size);
2517 if (z_buf == NULL) {
2518 print_error(MALLOC_FAILED);
2519 return MALLOC_FAILED;
2520 }
2521
2522 create_rand_repeat_data(z_buf, z_size);
2523
2524 ret = compress_full_flush(in_buf, in_size, z_buf, &z_size, gzip_flag, level);
2525
2526 if (!ret)
2527 ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0, 0);
2528
2529 if (ret) {
2530 log_print("Compressed array at level %d with gzip flag %d and flush type %d: ",
2531 level, gzip_flag, FULL_FLUSH);
2532 log_uint8_t(z_buf, z_size);
2533 log_print("\n");
2534 log_print("Data: ");
2535 log_uint8_t(in_buf, in_size);
2536
2537 printf("Failed on compress multi pass\n");
2538 print_error(ret);
2539 }
2540
2541 free(z_buf);
2542
2543 return ret;
2544 }
2545
test_inflate(struct vect_result * in_vector)2546 int test_inflate(struct vect_result *in_vector)
2547 {
2548 int ret = IGZIP_COMP_OK;
2549 uint8_t *compress_buf = in_vector->vector, *out_buf = NULL;
2550 uint64_t compress_len = in_vector->vector_length;
2551 uint32_t out_size = 0;
2552
2553 out_size = 10 * in_vector->vector_length;
2554 out_buf = malloc(out_size);
2555 if (out_buf == NULL)
2556 return MALLOC_FAILED;
2557
2558 ret = inflate_stateless_pass(compress_buf, compress_len, out_buf, &out_size, 0);
2559
2560 if (ret == INFLATE_LEFTOVER_INPUT)
2561 ret = ISAL_DECOMP_OK;
2562
2563 if (ret != in_vector->expected_error)
2564 printf("Inflate return value incorrect, %d != %d\n", ret,
2565 in_vector->expected_error);
2566 else
2567 ret = IGZIP_COMP_OK;
2568
2569 if (!ret) {
2570 ret = inflate_multi_pass(compress_buf, compress_len, out_buf, &out_size,
2571 0, NULL, 0, 0);
2572
2573 if (ret == INFLATE_LEFTOVER_INPUT)
2574 ret = ISAL_DECOMP_OK;
2575
2576 if (ret != in_vector->expected_error)
2577 printf("Inflate return value incorrect, %d != %d\n", ret,
2578 in_vector->expected_error);
2579 else
2580 ret = IGZIP_COMP_OK;
2581 }
2582
2583 return ret;
2584
2585 }
2586
test_large(uint8_t * in_buf,uint32_t in_size,uint64_t large_size)2587 int test_large(uint8_t * in_buf, uint32_t in_size, uint64_t large_size)
2588 {
2589
2590 int ret = IGZIP_COMP_OK;
2591 uint32_t gzip_flag, level;
2592 uint32_t z_size = 0, z_size_max = 0, tmp_buf_size;
2593 uint8_t *z_buf = NULL, *tmp_buf = NULL;
2594 int flush_type = NO_FLUSH;
2595
2596 /* Test a non overflow case */
2597 z_size_max = MAX_LARGE_COMP_BUF_SIZE;
2598
2599 gzip_flag = rand() % 5;
2600 level = get_rand_level();
2601
2602 z_size = z_size_max;
2603 z_buf = malloc(z_size);
2604 if (z_buf == NULL) {
2605 print_error(MALLOC_FAILED);
2606 return MALLOC_FAILED;
2607 }
2608 create_rand_repeat_data(z_buf, z_size);
2609
2610 tmp_buf_size = IBUF_SIZE;
2611 tmp_buf = malloc(tmp_buf_size);
2612 if (tmp_buf == NULL) {
2613 print_error(MALLOC_FAILED);
2614 return MALLOC_FAILED;
2615 }
2616
2617 ret =
2618 compress_ver_rep_buf(in_buf, in_size, large_size, z_buf, z_size, tmp_buf,
2619 tmp_buf_size, flush_type, gzip_flag, level);
2620
2621 if (ret)
2622 print_error(ret);
2623
2624 if (z_buf != NULL) {
2625 free(z_buf);
2626 z_buf = NULL;
2627 }
2628
2629 if (tmp_buf != NULL) {
2630 free(tmp_buf);
2631 tmp_buf = NULL;
2632 }
2633
2634 return ret;
2635 }
2636
2637 /* Run multiple compression tests on data stored in a file */
test_compress_file(char * file_name)2638 int test_compress_file(char *file_name)
2639 {
2640 int ret = IGZIP_COMP_OK;
2641 uint64_t in_size;
2642 uint8_t *in_buf = NULL;
2643 FILE *in_file = NULL;
2644
2645 in_file = fopen(file_name, "rb");
2646 if (!in_file) {
2647 printf("Failed to open file %s\n", file_name);
2648 return FILE_READ_FAILED;
2649 }
2650
2651 in_size = get_filesize(in_file);
2652 if (in_size > MAX_FILE_SIZE)
2653 in_size = MAX_FILE_SIZE;
2654
2655 if (in_size != 0) {
2656 in_buf = malloc(in_size);
2657 if (in_buf == NULL) {
2658 printf("Failed to allocate in_buf for test_compress_file\n");
2659 return MALLOC_FAILED;
2660 }
2661 if (fread(in_buf, 1, in_size, in_file) != in_size) {
2662 printf("Failed to read in_buf from test_compress_file\n");
2663 free(in_buf);
2664 return FILE_READ_FAILED;
2665 }
2666 }
2667
2668 ret |= test_compress_stateless(in_buf, in_size, NO_FLUSH);
2669 if (!ret)
2670 ret |= test_compress_stateless(in_buf, in_size, SYNC_FLUSH);
2671 if (!ret)
2672 ret |= test_compress_stateless(in_buf, in_size, FULL_FLUSH);
2673 if (!ret)
2674 ret |= test_compress(in_buf, in_size, NO_FLUSH);
2675 if (!ret)
2676 ret |= test_compress(in_buf, in_size, SYNC_FLUSH);
2677 if (!ret)
2678 ret |= test_compress(in_buf, in_size, FULL_FLUSH);
2679 if (!ret)
2680 ret |= test_flush(in_buf, in_size);
2681
2682 if (ret)
2683 printf("Failed on file %s\n", file_name);
2684
2685 if (in_buf != NULL)
2686 free(in_buf);
2687
2688 return ret;
2689 }
2690
create_custom_hufftables(struct isal_hufftables * hufftables_custom,int file_count,char * files[])2691 int create_custom_hufftables(struct isal_hufftables *hufftables_custom, int file_count,
2692 char *files[])
2693 {
2694 long int file_length;
2695 uint8_t *stream = NULL;
2696 struct isal_huff_histogram histogram;
2697 FILE *file;
2698 int i;
2699
2700 memset(&histogram, 0, sizeof(histogram));
2701
2702 for (i = 0; i < file_count; i++) {
2703 printf("Processing %s\n", files[i]);
2704 file = fopen(files[i], "r");
2705 if (file == NULL) {
2706 printf("Error opening file\n");
2707 return 1;
2708 }
2709 fseek(file, 0, SEEK_END);
2710 file_length = ftell(file);
2711 fseek(file, 0, SEEK_SET);
2712 file_length -= ftell(file);
2713
2714 if (file_length > 0) {
2715 stream = malloc(file_length);
2716 if (stream == NULL) {
2717 printf("Failed to allocate memory to read in file\n");
2718 fclose(file);
2719 return 1;
2720 }
2721 }
2722
2723 if (fread(stream, 1, file_length, file) != file_length) {
2724 printf("Error occurred when reading file\n");
2725 fclose(file);
2726 free(stream);
2727 stream = NULL;
2728 return 1;
2729 }
2730
2731 /* Create a histogram of frequency of symbols found in stream to
2732 * generate the huffman tree.*/
2733 isal_update_histogram(stream, file_length, &histogram);
2734
2735 fclose(file);
2736 if (stream != NULL) {
2737 free(stream);
2738 stream = NULL;
2739 }
2740 }
2741
2742 return isal_create_hufftables(hufftables_custom, &histogram);
2743
2744 }
2745
main(int argc,char * argv[])2746 int main(int argc, char *argv[])
2747 {
2748 int i = 0, j = 0, ret = 0, fin_ret = 0;
2749 uint32_t in_size = 0, offset = 0;
2750 uint8_t *in_buf;
2751 struct isal_hufftables hufftables_custom, hufftables_sub;
2752 uint64_t iterations, large_buf_size;
2753 size_t argv_index;
2754 char **input_files;
2755 size_t file_count;
2756
2757 argv_index = parse_options(argc, argv);
2758
2759 input_files = &argv[argv_index];
2760 file_count = argc - argv_index;
2761
2762 if (options.verbose)
2763 setbuf(stdout, NULL);
2764
2765 printf("Window Size: %d K\n", IGZIP_HIST_SIZE / 1024);
2766 printf("Test Seed : %d\n", options.test_seed);
2767 printf("Randoms : %d\n", options.randoms);
2768 srand(options.test_seed);
2769
2770 hufftables_subset = &hufftables_sub;
2771 if (file_count > 0) {
2772 ret = create_custom_hufftables(&hufftables_custom, file_count, input_files);
2773 if (ret == 0)
2774 hufftables = &hufftables_custom;
2775 else {
2776 printf("Failed to generate custom hufftable");
2777 return -1;
2778 }
2779 }
2780
2781 in_buf = malloc(IBUF_SIZE);
2782 memset(in_buf, 0, IBUF_SIZE);
2783
2784 if (in_buf == NULL) {
2785 fprintf(stderr, "Can't allocate in_buf memory\n");
2786 return -1;
2787 }
2788
2789 if (file_count > 0) {
2790 printf("igzip_rand_test files: ");
2791
2792 for (i = 0; i < file_count; i++) {
2793 ret |= test_compress_file(input_files[i]);
2794 if (ret)
2795 return ret;
2796 }
2797
2798 printf("................");
2799 printf("%s\n", ret ? "Fail" : "Pass");
2800 fin_ret |= ret;
2801 }
2802
2803 printf("igzip_rand_test stateless: ");
2804
2805 ret = test_compress_stateless((uint8_t *) str1, sizeof(str1), NO_FLUSH);
2806 if (ret)
2807 return ret;
2808
2809 ret |= test_compress_stateless((uint8_t *) str2, sizeof(str2), NO_FLUSH);
2810 if (ret)
2811 return ret;
2812
2813 for (i = 0; i < options.randoms; i++) {
2814 in_size = get_rand_data_length();
2815 offset = rand() % (IBUF_SIZE + 1 - in_size);
2816 in_buf += offset;
2817
2818 create_rand_repeat_data(in_buf, in_size);
2819
2820 ret |= test_compress_stateless(in_buf, in_size, NO_FLUSH);
2821
2822 in_buf -= offset;
2823
2824 if (i % (options.randoms / 16) == 0)
2825 printf(".");
2826
2827 if (ret)
2828 return ret;
2829 }
2830
2831 for (i = 0; i < options.randoms / 16; i++) {
2832 create_rand_repeat_data(in_buf, PAGE_SIZE);
2833 ret |= test_compress_stateless(in_buf, PAGE_SIZE, NO_FLUSH); // good for efence
2834 if (ret)
2835 return ret;
2836 }
2837
2838 fin_ret |= ret;
2839
2840 ret = test_compress_stateless((uint8_t *) str1, sizeof(str1), SYNC_FLUSH);
2841 if (ret)
2842 return ret;
2843
2844 ret |= test_compress_stateless((uint8_t *) str2, sizeof(str2), SYNC_FLUSH);
2845 if (ret)
2846 return ret;
2847
2848 for (i = 0; i < 16; i++) {
2849 in_size = get_rand_data_length();
2850 offset = rand() % (IBUF_SIZE + 1 - in_size);
2851 in_buf += offset;
2852
2853 create_rand_repeat_data(in_buf, in_size);
2854
2855 ret |= test_compress_stateless(in_buf, in_size, SYNC_FLUSH);
2856
2857 in_buf -= offset;
2858
2859 if (ret)
2860 return ret;
2861 }
2862
2863 fin_ret |= ret;
2864
2865 printf("%s\n", ret ? "Fail" : "Pass");
2866
2867 printf("igzip_rand_test stateless FULL_FLUSH: ");
2868
2869 ret = test_compress_stateless((uint8_t *) str1, sizeof(str1), FULL_FLUSH);
2870 if (ret)
2871 return ret;
2872
2873 ret |= test_compress_stateless((uint8_t *) str2, sizeof(str2), FULL_FLUSH);
2874 if (ret)
2875 return ret;
2876
2877 for (i = 0; i < options.randoms; i++) {
2878 in_size = get_rand_data_length();
2879 offset = rand() % (IBUF_SIZE + 1 - in_size);
2880 in_buf += offset;
2881
2882 create_rand_repeat_data(in_buf, in_size);
2883
2884 ret |= test_compress_stateless(in_buf, in_size, FULL_FLUSH);
2885
2886 in_buf -= offset;
2887
2888 if (i % (options.randoms / 16) == 0)
2889 printf(".");
2890
2891 if (ret)
2892 return ret;
2893 }
2894
2895 for (i = 0; i < options.randoms / 16; i++) {
2896 create_rand_repeat_data(in_buf, PAGE_SIZE);
2897 ret |= test_compress_stateless(in_buf, PAGE_SIZE, FULL_FLUSH); // good for efence
2898 if (ret)
2899 return ret;
2900 }
2901 fin_ret |= ret;
2902
2903 printf("%s\n", ret ? "Fail" : "Pass");
2904
2905 printf("igzip_rand_test stateful NO_FLUSH: ");
2906
2907 memcpy(in_buf, str1, sizeof(str1));
2908 ret = test_compress(in_buf, sizeof(str1), NO_FLUSH);
2909 if (ret)
2910 return ret;
2911
2912 memcpy(in_buf, str2, sizeof(str2));
2913 ret |= test_compress(in_buf, sizeof(str2), NO_FLUSH);
2914 if (ret)
2915 return ret;
2916
2917 for (i = 0; i < options.randoms; i++) {
2918 in_size = get_rand_data_length();
2919 offset = rand() % (IBUF_SIZE + 1 - in_size);
2920 in_buf += offset;
2921
2922 create_rand_repeat_data(in_buf, in_size);
2923
2924 ret |= test_compress(in_buf, in_size, NO_FLUSH);
2925
2926 in_buf -= offset;
2927
2928 if (i % (options.randoms / 16) == 0)
2929 printf(".");
2930 if (ret)
2931 return ret;
2932 }
2933
2934 fin_ret |= ret;
2935
2936 printf("%s\n", ret ? "Fail" : "Pass");
2937
2938 printf("igzip_rand_test stateful SYNC_FLUSH: ");
2939
2940 memcpy(in_buf, str1, sizeof(str1));
2941 ret = test_compress(in_buf, sizeof(str1), SYNC_FLUSH);
2942 if (ret)
2943 return ret;
2944
2945 memcpy(in_buf, str2, sizeof(str2));
2946 ret |= test_compress(in_buf, sizeof(str2), SYNC_FLUSH);
2947 if (ret)
2948 return ret;
2949
2950 for (i = 0; i < options.randoms; i++) {
2951 in_size = get_rand_data_length();
2952 offset = rand() % (IBUF_SIZE + 1 - in_size);
2953 in_buf += offset;
2954
2955 create_rand_repeat_data(in_buf, in_size);
2956
2957 ret |= test_compress(in_buf, in_size, SYNC_FLUSH);
2958
2959 in_buf -= offset;
2960
2961 if (i % (options.randoms / 16) == 0)
2962 printf(".");
2963 if (ret)
2964 return ret;
2965 }
2966
2967 fin_ret |= ret;
2968
2969 printf("%s\n", ret ? "Fail" : "Pass");
2970
2971 printf("igzip_rand_test stateful FULL_FLUSH: ");
2972
2973 memcpy(in_buf, str1, sizeof(str1));
2974 ret = test_compress(in_buf, sizeof(str1), FULL_FLUSH);
2975 if (ret)
2976 return ret;
2977
2978 memcpy(in_buf, str2, sizeof(str2));
2979 ret |= test_compress(in_buf, sizeof(str2), FULL_FLUSH);
2980 if (ret)
2981 return ret;
2982
2983 for (i = 0; i < options.randoms; i++) {
2984 in_size = get_rand_data_length();
2985 offset = rand() % (IBUF_SIZE + 1 - in_size);
2986 in_buf += offset;
2987
2988 create_rand_repeat_data(in_buf, in_size);
2989
2990 ret |= test_compress(in_buf, in_size, FULL_FLUSH);
2991
2992 in_buf -= offset;
2993
2994 if (i % (options.randoms / 16) == 0)
2995 printf(".");
2996 if (ret)
2997 return ret;
2998 }
2999
3000 for (i = 0; i < options.randoms / 8; i++) {
3001 in_size = get_rand_data_length();
3002 offset = rand() % (IBUF_SIZE + 1 - in_size);
3003 in_buf += offset;
3004
3005 create_rand_repeat_data(in_buf, in_size);
3006
3007 ret |= test_full_flush(in_buf, in_size);
3008
3009 in_buf -= offset;
3010
3011 if (ret)
3012 return ret;
3013 }
3014
3015 fin_ret |= ret;
3016
3017 printf("%s\n", ret ? "Fail" : "Pass");
3018
3019 printf("igzip_rand_test stateful Change Flush: ");
3020
3021 ret = test_flush((uint8_t *) str1, sizeof(str1));
3022 if (ret)
3023 return ret;
3024
3025 ret |= test_flush((uint8_t *) str2, sizeof(str2));
3026 if (ret)
3027 return ret;
3028
3029 for (i = 0; i < options.randoms / 4; i++) {
3030 in_size = get_rand_data_length();
3031 offset = rand() % (IBUF_SIZE + 1 - in_size);
3032 in_buf += offset;
3033
3034 create_rand_repeat_data(in_buf, in_size);
3035
3036 ret |= test_flush(in_buf, in_size);
3037
3038 in_buf -= offset;
3039
3040 if (i % ((options.randoms / 4) / 16) == 0)
3041 printf(".");
3042 if (ret)
3043 return ret;
3044 }
3045
3046 fin_ret |= ret;
3047
3048 printf("%s\n", ret ? "Fail" : "Pass");
3049
3050 if (options.do_large_test) {
3051 printf("igzip_rand_test large input ");
3052
3053 iterations = options.randoms / 256 + 1;
3054 for (i = 0; i < iterations; i++) {
3055 in_size = rand() % (32 * 1024) + 16 * 1024;
3056 offset = rand() % (IBUF_SIZE + 1 - in_size);
3057 in_buf += offset;
3058
3059 large_buf_size = 1;
3060 large_buf_size <<= 32;
3061 large_buf_size += rand() % (1024 * 1024) + 1;
3062 create_rand_repeat_data(in_buf, in_size);
3063
3064 ret |= test_large(in_buf, in_size, large_buf_size);
3065
3066 if (ret)
3067 return ret;
3068
3069 in_buf -= offset;
3070
3071 if (iterations < 16) {
3072 for (j = 0; j < 16 / iterations; j++)
3073 printf(".");
3074 } else if (i % (iterations / 16) == 0)
3075 printf(".");
3076
3077 }
3078
3079 if (iterations < 16) {
3080 for (j = (16 / iterations) * iterations; j < 16; j++)
3081 printf(".");
3082 }
3083
3084 printf("%s\n", ret ? "Fail" : "Pass");
3085 }
3086
3087 printf("igzip_rand_test inflate Std Vectors: ");
3088
3089 for (i = 0; i < sizeof(std_vect_array) / sizeof(struct vect_result); i++) {
3090 ret = test_inflate(&std_vect_array[i]);
3091 if (ret)
3092 return ret;
3093 }
3094 printf("................");
3095 printf("%s\n", ret ? "Fail" : "Pass");
3096
3097 printf("igzip rand test finished: %s\n",
3098 fin_ret ? "Some tests failed" : "All tests passed");
3099
3100 return fin_ret != IGZIP_COMP_OK;
3101 }
3102