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 #include <stdint.h> 31 #include <stdio.h> 32 #include <zlib.h> 33 #include "inflate.h" 34 #include "huff_codes.h" 35 36 /*Don't use file larger memory can support because compression and decompression 37 * are done in a stateless manner. */ 38 #define MAX_INPUT_FILE_SIZE 2L*1024L*1024L*1024L 39 40 int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len, 41 uint8_t * uncompress_buf, uint32_t * uncompress_len) 42 { 43 struct inflate_state *state = NULL; 44 int ret = 0; 45 uint8_t *comp_tmp = NULL, *uncomp_tmp = NULL; 46 uint32_t comp_tmp_size = 0, uncomp_tmp_size = 0; 47 uint32_t comp_processed = 0, uncomp_processed = 0; 48 49 state = malloc(sizeof(struct inflate_state)); 50 if (state == NULL) { 51 printf("Failed to allocate memory\n"); 52 exit(0); 53 } 54 55 isal_inflate_init(state); 56 57 state->next_in = NULL; 58 state->next_out = NULL; 59 state->avail_in = 0; 60 state->avail_out = 0; 61 62 while (1) { 63 if (state->avail_in == 0) { 64 comp_tmp_size = rand() % (compress_len + 1); 65 66 if (comp_tmp_size >= compress_len - comp_processed) 67 comp_tmp_size = compress_len - comp_processed; 68 69 if (comp_tmp_size != 0) { 70 if (comp_tmp != NULL) { 71 free(comp_tmp); 72 comp_tmp = NULL; 73 } 74 75 comp_tmp = malloc(comp_tmp_size); 76 77 if (comp_tmp == NULL) { 78 printf("Failed to allocate memory\n"); 79 exit(0); 80 } 81 82 memcpy(comp_tmp, compress_buf + comp_processed, comp_tmp_size); 83 comp_processed += comp_tmp_size; 84 85 state->next_in = comp_tmp; 86 state->avail_in = comp_tmp_size; 87 } 88 } 89 90 if (state->avail_out == 0) { 91 /* Save uncompressed data into uncompress_buf */ 92 if (uncomp_tmp != NULL) { 93 memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, 94 uncomp_tmp_size); 95 uncomp_processed += uncomp_tmp_size; 96 } 97 98 uncomp_tmp_size = rand() % (*uncompress_len + 1); 99 100 /* Limit size of buffer to be smaller than maximum */ 101 if (uncomp_tmp_size > *uncompress_len - uncomp_processed) 102 uncomp_tmp_size = *uncompress_len - uncomp_processed; 103 104 if (uncomp_tmp_size != 0) { 105 106 if (uncomp_tmp != NULL) { 107 fflush(0); 108 free(uncomp_tmp); 109 uncomp_tmp = NULL; 110 } 111 112 uncomp_tmp = malloc(uncomp_tmp_size); 113 if (uncomp_tmp == NULL) { 114 printf("Failed to allocate memory\n"); 115 exit(0); 116 } 117 118 state->avail_out = uncomp_tmp_size; 119 state->next_out = uncomp_tmp; 120 } 121 } 122 123 ret = isal_inflate(state); 124 125 if (state->block_state == ISAL_BLOCK_FINISH || ret != 0) { 126 memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, uncomp_tmp_size); 127 *uncompress_len = state->total_out; 128 break; 129 } 130 } 131 132 if (comp_tmp != NULL) { 133 free(comp_tmp); 134 comp_tmp = NULL; 135 } 136 if (uncomp_tmp != NULL) { 137 free(uncomp_tmp); 138 uncomp_tmp = NULL; 139 } 140 141 free(state); 142 return ret; 143 } 144 145 int test(uint8_t * compressed_stream, 146 uint64_t * compressed_length, 147 uint8_t * uncompressed_stream, uint32_t uncompressed_length, 148 uint8_t * uncompressed_test_stream, uint32_t uncompressed_test_stream_length) 149 { 150 int ret; 151 ret = 152 compress2(compressed_stream, compressed_length, 153 uncompressed_stream, uncompressed_length, 6); 154 if (ret) { 155 printf("Failed compressing input with exit code %d", ret); 156 return ret; 157 } 158 159 ret = 160 inflate_multi_pass(compressed_stream + 2, 161 *compressed_length - 2 - 4, 162 uncompressed_test_stream, &uncompressed_test_stream_length); 163 switch (ret) { 164 case 0: 165 break; 166 case END_OF_INPUT: 167 printf(" did not decompress all input\n"); 168 return END_OF_INPUT; 169 break; 170 case INVALID_BLOCK_HEADER: 171 printf(" invalid header\n"); 172 return INVALID_BLOCK_HEADER; 173 break; 174 case INVALID_SYMBOL: 175 printf(" invalid symbol\n"); 176 return INVALID_SYMBOL; 177 break; 178 case OUT_BUFFER_OVERFLOW: 179 printf(" out buffer overflow\n"); 180 return OUT_BUFFER_OVERFLOW; 181 break; 182 case INVALID_NON_COMPRESSED_BLOCK_LENGTH: 183 printf("Invalid length bits in non-compressed block\n"); 184 return INVALID_NON_COMPRESSED_BLOCK_LENGTH; 185 break; 186 case INVALID_LOOK_BACK_DISTANCE: 187 printf("Invalid lookback distance"); 188 return INVALID_LOOK_BACK_DISTANCE; 189 break; 190 default: 191 printf(" error\n"); 192 return -1; 193 break; 194 } 195 196 if (uncompressed_test_stream_length != uncompressed_length) { 197 printf("incorrect amount of data was decompressed from compressed data\n"); 198 printf("%d decompressed of %d compressed", 199 uncompressed_test_stream_length, uncompressed_length); 200 return -1; 201 } 202 if (memcmp(uncompressed_stream, uncompressed_test_stream, uncompressed_length)) { 203 int i; 204 for (i = 0; i < uncompressed_length; i++) { 205 if (uncompressed_stream[i] != uncompressed_test_stream[i]) { 206 printf("first error at %d, 0x%x != 0x%x\n", i, 207 uncompressed_stream[i], uncompressed_test_stream[i]); 208 } 209 } 210 printf(" decompressed data is not the same as the compressed data\n"); 211 return -1; 212 } 213 214 return 0; 215 } 216 217 int main(int argc, char **argv) 218 { 219 int i, j, ret = 0, fin_ret = 0; 220 FILE *file = NULL; 221 uint64_t compressed_length, file_length; 222 uint64_t uncompressed_length, uncompressed_test_stream_length; 223 uint8_t *uncompressed_stream = NULL; 224 uint8_t *compressed_stream = NULL; 225 uint8_t *uncompressed_test_stream = NULL; 226 227 if (argc == 1) 228 printf("Error, no input file\n"); 229 for (i = 1; i < argc; i++) { 230 file = fopen(argv[i], "r"); 231 if (file == NULL) { 232 printf("Error opening file %s\n", argv[i]); 233 return 1; 234 } else 235 printf("Starting file %s", argv[i]); 236 fflush(0); 237 fseek(file, 0, SEEK_END); 238 file_length = ftell(file); 239 fseek(file, 0, SEEK_SET); 240 file_length -= ftell(file); 241 if (file_length > MAX_INPUT_FILE_SIZE) { 242 printf("File too large to run on this test\n"); 243 fclose(file); 244 continue; 245 } 246 247 compressed_length = compressBound(file_length); 248 if (file_length != 0) { 249 uncompressed_stream = malloc(file_length); 250 uncompressed_test_stream = malloc(file_length); 251 } 252 compressed_stream = malloc(compressed_length); 253 if (uncompressed_stream == NULL && file_length != 0) { 254 printf("Failed to allocate memory\n"); 255 exit(0); 256 } 257 258 if (compressed_stream == NULL) { 259 printf("Failed to allocate memory\n"); 260 exit(0); 261 } 262 263 if (uncompressed_test_stream == NULL) { 264 printf("Failed to allocate memory\n"); 265 exit(0); 266 } 267 268 uncompressed_length = fread(uncompressed_stream, 1, file_length, file); 269 uncompressed_test_stream_length = uncompressed_length; 270 ret = 271 test(compressed_stream, &compressed_length, uncompressed_stream, 272 uncompressed_length, uncompressed_test_stream, 273 uncompressed_test_stream_length); 274 if (ret) { 275 for (j = 0; j < compressed_length; j++) { 276 if ((j & 31) == 0) 277 printf("\n"); 278 else 279 printf(" "); 280 printf("0x%02x,", compressed_stream[j]); 281 } 282 printf("\n"); 283 } 284 285 fflush(0); 286 fclose(file); 287 free(compressed_stream); 288 if (uncompressed_stream != NULL) 289 free(uncompressed_stream); 290 if (uncompressed_test_stream != NULL) 291 free(uncompressed_test_stream); 292 if (ret) { 293 printf(" ... Fail with exit code %d\n", ret); 294 return ret; 295 } else 296 printf(" ... Pass\n"); 297 fin_ret |= ret; 298 } 299 return fin_ret; 300 } 301