1 /* infcover.c -- test zlib's inflate routines with full code coverage 2 * Copyright (C) 2011, 2016 Mark Adler 3 * For conditions of distribution and use, see copyright notice in zlib.h 4 */ 5 6 /* to use, do: ./configure --cover && make cover */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <assert.h> 12 #include "zlib.h" 13 14 /* get definition of internal structure so we can mess with it (see pull()), 15 and so we can call inflate_trees() (see cover5()) */ 16 #define ZLIB_INTERNAL 17 #include "inftrees.h" 18 #include "inflate.h" 19 20 #define local static 21 22 /* -- memory tracking routines -- */ 23 24 /* 25 These memory tracking routines are provided to zlib and track all of zlib's 26 allocations and deallocations, check for LIFO operations, keep a current 27 and high water mark of total bytes requested, optionally set a limit on the 28 total memory that can be allocated, and when done check for memory leaks. 29 30 They are used as follows: 31 32 z_stream strm; 33 mem_setup(&strm) initializes the memory tracking and sets the 34 zalloc, zfree, and opaque members of strm to use 35 memory tracking for all zlib operations on strm 36 mem_limit(&strm, limit) sets a limit on the total bytes requested -- a 37 request that exceeds this limit will result in an 38 allocation failure (returns NULL) -- setting the 39 limit to zero means no limit, which is the default 40 after mem_setup() 41 mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used 42 mem_high(&strm, "msg") prints to stderr "msg" and the high water mark 43 mem_done(&strm, "msg") ends memory tracking, releases all allocations 44 for the tracking as well as leaked zlib blocks, if 45 any. If there was anything unusual, such as leaked 46 blocks, non-FIFO frees, or frees of addresses not 47 allocated, then "msg" and information about the 48 problem is printed to stderr. If everything is 49 normal, nothing is printed. mem_done resets the 50 strm members to Z_NULL to use the default memory 51 allocation routines on the next zlib initialization 52 using strm. 53 */ 54 55 /* these items are strung together in a linked list, one for each allocation */ 56 struct mem_item { 57 void *ptr; /* pointer to allocated memory */ 58 size_t size; /* requested size of allocation */ 59 struct mem_item *next; /* pointer to next item in list, or NULL */ 60 }; 61 62 /* this structure is at the root of the linked list, and tracks statistics */ 63 struct mem_zone { 64 struct mem_item *first; /* pointer to first item in list, or NULL */ 65 size_t total, highwater; /* total allocations, and largest total */ 66 size_t limit; /* memory allocation limit, or 0 if no limit */ 67 int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ 68 }; 69 70 /* memory allocation routine to pass to zlib */ 71 local void *mem_alloc(void *mem, unsigned count, unsigned size) 72 { 73 void *ptr; 74 struct mem_item *item; 75 struct mem_zone *zone = mem; 76 size_t len = count * (size_t)size; 77 78 /* induced allocation failure */ 79 if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) 80 return NULL; 81 82 /* perform allocation using the standard library, fill memory with a 83 non-zero value to make sure that the code isn't depending on zeros */ 84 ptr = malloc(len); 85 if (ptr == NULL) 86 return NULL; 87 memset(ptr, 0xa5, len); 88 89 /* create a new item for the list */ 90 item = malloc(sizeof(struct mem_item)); 91 if (item == NULL) { 92 free(ptr); 93 return NULL; 94 } 95 item->ptr = ptr; 96 item->size = len; 97 98 /* insert item at the beginning of the list */ 99 item->next = zone->first; 100 zone->first = item; 101 102 /* update the statistics */ 103 zone->total += item->size; 104 if (zone->total > zone->highwater) 105 zone->highwater = zone->total; 106 107 /* return the allocated memory */ 108 return ptr; 109 } 110 111 /* memory free routine to pass to zlib */ 112 local void mem_free(void *mem, void *ptr) 113 { 114 struct mem_item *item, *next; 115 struct mem_zone *zone = mem; 116 117 /* if no zone, just do a free */ 118 if (zone == NULL) { 119 free(ptr); 120 return; 121 } 122 123 /* point next to the item that matches ptr, or NULL if not found -- remove 124 the item from the linked list if found */ 125 next = zone->first; 126 if (next) { 127 if (next->ptr == ptr) 128 zone->first = next->next; /* first one is it, remove from list */ 129 else { 130 do { /* search the linked list */ 131 item = next; 132 next = item->next; 133 } while (next != NULL && next->ptr != ptr); 134 if (next) { /* if found, remove from linked list */ 135 item->next = next->next; 136 zone->notlifo++; /* not a LIFO free */ 137 } 138 139 } 140 } 141 142 /* if found, update the statistics and free the item */ 143 if (next) { 144 zone->total -= next->size; 145 free(next); 146 } 147 148 /* if not found, update the rogue count */ 149 else 150 zone->rogue++; 151 152 /* in any case, do the requested free with the standard library function */ 153 free(ptr); 154 } 155 156 /* set up a controlled memory allocation space for monitoring, set the stream 157 parameters to the controlled routines, with opaque pointing to the space */ 158 local void mem_setup(z_stream *strm) 159 { 160 struct mem_zone *zone; 161 162 zone = malloc(sizeof(struct mem_zone)); 163 assert(zone != NULL); 164 zone->first = NULL; 165 zone->total = 0; 166 zone->highwater = 0; 167 zone->limit = 0; 168 zone->notlifo = 0; 169 zone->rogue = 0; 170 strm->opaque = zone; 171 strm->zalloc = mem_alloc; 172 strm->zfree = mem_free; 173 } 174 175 /* set a limit on the total memory allocation, or 0 to remove the limit */ 176 local void mem_limit(z_stream *strm, size_t limit) 177 { 178 struct mem_zone *zone = strm->opaque; 179 180 zone->limit = limit; 181 } 182 183 /* show the current total requested allocations in bytes */ 184 local void mem_used(z_stream *strm, char *prefix) 185 { 186 struct mem_zone *zone = strm->opaque; 187 188 fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); 189 } 190 191 /* show the high water allocation in bytes */ 192 local void mem_high(z_stream *strm, char *prefix) 193 { 194 struct mem_zone *zone = strm->opaque; 195 196 fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); 197 } 198 199 /* release the memory allocation zone -- if there are any surprises, notify */ 200 local void mem_done(z_stream *strm, char *prefix) 201 { 202 int count = 0; 203 struct mem_item *item, *next; 204 struct mem_zone *zone = strm->opaque; 205 206 /* show high water mark */ 207 mem_high(strm, prefix); 208 209 /* free leftover allocations and item structures, if any */ 210 item = zone->first; 211 while (item != NULL) { 212 free(item->ptr); 213 next = item->next; 214 free(item); 215 item = next; 216 count++; 217 } 218 219 /* issue alerts about anything unexpected */ 220 if (count || zone->total) 221 fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", 222 prefix, zone->total, count); 223 if (zone->notlifo) 224 fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); 225 if (zone->rogue) 226 fprintf(stderr, "** %s: %d frees not recognized\n", 227 prefix, zone->rogue); 228 229 /* free the zone and delete from the stream */ 230 free(zone); 231 strm->opaque = Z_NULL; 232 strm->zalloc = Z_NULL; 233 strm->zfree = Z_NULL; 234 } 235 236 /* -- inflate test routines -- */ 237 238 /* Decode a hexadecimal string, set *len to length, in[] to the bytes. This 239 decodes liberally, in that hex digits can be adjacent, in which case two in 240 a row writes a byte. Or they can be delimited by any non-hex character, 241 where the delimiters are ignored except when a single hex digit is followed 242 by a delimiter, where that single digit writes a byte. The returned data is 243 allocated and must eventually be freed. NULL is returned if out of memory. 244 If the length is not needed, then len can be NULL. */ 245 local unsigned char *h2b(const char *hex, unsigned *len) 246 { 247 unsigned char *in, *re; 248 unsigned next, val; 249 250 in = malloc((strlen(hex) + 1) >> 1); 251 if (in == NULL) 252 return NULL; 253 next = 0; 254 val = 1; 255 do { 256 if (*hex >= '0' && *hex <= '9') 257 val = (val << 4) + *hex - '0'; 258 else if (*hex >= 'A' && *hex <= 'F') 259 val = (val << 4) + *hex - 'A' + 10; 260 else if (*hex >= 'a' && *hex <= 'f') 261 val = (val << 4) + *hex - 'a' + 10; 262 else if (val != 1 && val < 32) /* one digit followed by delimiter */ 263 val += 240; /* make it look like two digits */ 264 if (val > 255) { /* have two digits */ 265 in[next++] = val & 0xff; /* save the decoded byte */ 266 val = 1; /* start over */ 267 } 268 } while (*hex++); /* go through the loop with the terminating null */ 269 if (len != NULL) 270 *len = next; 271 re = realloc(in, next); 272 return re == NULL ? in : re; 273 } 274 275 /* generic inflate() run, where hex is the hexadecimal input data, what is the 276 text to include in an error message, step is how much input data to feed 277 inflate() on each call, or zero to feed it all, win is the window bits 278 parameter to inflateInit2(), len is the size of the output buffer, and err 279 is the error code expected from the first inflate() call (the second 280 inflate() call is expected to return Z_STREAM_END). If win is 47, then 281 header information is collected with inflateGetHeader(). If a zlib stream 282 is looking for a dictionary, then an empty dictionary is provided. 283 inflate() is run until all of the input data is consumed. */ 284 local void inf(char *hex, char *what, unsigned step, int win, unsigned len, 285 int err) 286 { 287 int ret; 288 unsigned have; 289 unsigned char *in, *out; 290 z_stream strm, copy; 291 gz_header head; 292 293 mem_setup(&strm); 294 strm.avail_in = 0; 295 strm.next_in = Z_NULL; 296 ret = inflateInit2(&strm, win); 297 if (ret != Z_OK) { 298 mem_done(&strm, what); 299 return; 300 } 301 out = malloc(len); assert(out != NULL); 302 if (win == 47) { 303 head.extra = out; 304 head.extra_max = len; 305 head.name = out; 306 head.name_max = len; 307 head.comment = out; 308 head.comm_max = len; 309 ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); 310 } 311 in = h2b(hex, &have); assert(in != NULL); 312 if (step == 0 || step > have) 313 step = have; 314 strm.avail_in = step; 315 have -= step; 316 strm.next_in = in; 317 do { 318 strm.avail_out = len; 319 strm.next_out = out; 320 ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); 321 if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) 322 break; 323 if (ret == Z_NEED_DICT) { 324 ret = inflateSetDictionary(&strm, in, 1); 325 assert(ret == Z_DATA_ERROR); 326 mem_limit(&strm, 1); 327 ret = inflateSetDictionary(&strm, out, 0); 328 assert(ret == Z_MEM_ERROR); 329 mem_limit(&strm, 0); 330 ((struct inflate_state *)strm.state)->mode = DICT; 331 ret = inflateSetDictionary(&strm, out, 0); 332 assert(ret == Z_OK); 333 ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); 334 } 335 ret = inflateCopy(©, &strm); assert(ret == Z_OK); 336 ret = inflateEnd(©); assert(ret == Z_OK); 337 err = 9; /* don't care next time around */ 338 have += strm.avail_in; 339 strm.avail_in = step > have ? have : step; 340 have -= strm.avail_in; 341 } while (strm.avail_in); 342 free(in); 343 free(out); 344 ret = inflateReset2(&strm, -8); assert(ret == Z_OK); 345 ret = inflateEnd(&strm); assert(ret == Z_OK); 346 mem_done(&strm, what); 347 } 348 349 /* cover all of the lines in inflate.c up to inflate() */ 350 local void cover_support(void) 351 { 352 int ret; 353 z_stream strm; 354 355 mem_setup(&strm); 356 strm.avail_in = 0; 357 strm.next_in = Z_NULL; 358 ret = inflateInit(&strm); assert(ret == Z_OK); 359 mem_used(&strm, "inflate init"); 360 ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); 361 ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); 362 ret = inflateSetDictionary(&strm, Z_NULL, 0); 363 assert(ret == Z_STREAM_ERROR); 364 ret = inflateEnd(&strm); assert(ret == Z_OK); 365 mem_done(&strm, "prime"); 366 367 inf("63 0", "force window allocation", 0, -15, 1, Z_OK); 368 inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); 369 inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); 370 inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); 371 inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); 372 373 mem_setup(&strm); 374 strm.avail_in = 0; 375 strm.next_in = Z_NULL; 376 ret = inflateInit_(&strm, "!", (int)sizeof(z_stream)); 377 assert(ret == Z_VERSION_ERROR); 378 mem_done(&strm, "wrong version"); 379 380 strm.avail_in = 0; 381 strm.next_in = Z_NULL; 382 ret = inflateInit(&strm); assert(ret == Z_OK); 383 ret = inflateEnd(&strm); assert(ret == Z_OK); 384 fputs("inflate built-in memory routines\n", stderr); 385 } 386 387 /* cover all inflate() header and trailer cases and code after inflate() */ 388 local void cover_wrap(void) 389 { 390 int ret; 391 z_stream strm, copy; 392 unsigned char dict[257]; 393 394 ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); 395 ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 396 ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); 397 fputs("inflate bad parameters\n", stderr); 398 399 inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); 400 inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); 401 inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); 402 inf("8 99", "set window size from header", 0, 0, 0, Z_OK); 403 inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); 404 inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); 405 inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, 406 Z_DATA_ERROR); 407 inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", 408 0, 47, 0, Z_STREAM_END); 409 inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); 410 inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); 411 inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); 412 413 mem_setup(&strm); 414 strm.avail_in = 0; 415 strm.next_in = Z_NULL; 416 ret = inflateInit2(&strm, -8); 417 strm.avail_in = 2; 418 strm.next_in = (void *)"\x63"; 419 strm.avail_out = 1; 420 strm.next_out = (void *)&ret; 421 mem_limit(&strm, 1); 422 ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 423 ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 424 mem_limit(&strm, 0); 425 memset(dict, 0, 257); 426 ret = inflateSetDictionary(&strm, dict, 257); 427 assert(ret == Z_OK); 428 mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); 429 ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); 430 strm.avail_in = 2; 431 strm.next_in = (void *)"\x80"; 432 ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); 433 ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); 434 strm.avail_in = 4; 435 strm.next_in = (void *)"\0\0\xff\xff"; 436 ret = inflateSync(&strm); assert(ret == Z_OK); 437 (void)inflateSyncPoint(&strm); 438 ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); 439 mem_limit(&strm, 0); 440 ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); 441 (void)inflateMark(&strm); 442 ret = inflateEnd(&strm); assert(ret == Z_OK); 443 mem_done(&strm, "miscellaneous, force memory errors"); 444 } 445 446 /* input and output functions for inflateBack() */ 447 local unsigned pull(void *desc, unsigned char **buf) 448 { 449 static unsigned int next = 0; 450 static unsigned char dat[] = {0x63, 0, 2, 0}; 451 struct inflate_state *state; 452 453 if (desc == Z_NULL) { 454 next = 0; 455 return 0; /* no input (already provided at next_in) */ 456 } 457 state = (void *)((z_stream *)desc)->state; 458 if (state != Z_NULL) 459 state->mode = SYNC; /* force an otherwise impossible situation */ 460 return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; 461 } 462 463 local int push(void *desc, unsigned char *buf, unsigned len) 464 { 465 (void)buf; 466 (void)len; 467 return desc != Z_NULL; /* force error if desc not null */ 468 } 469 470 /* cover inflateBack() up to common deflate data cases and after those */ 471 local void cover_back(void) 472 { 473 int ret; 474 z_stream strm; 475 unsigned char win[32768]; 476 477 ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); 478 assert(ret == Z_VERSION_ERROR); 479 ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); 480 ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); 481 assert(ret == Z_STREAM_ERROR); 482 ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 483 fputs("inflateBack bad parameters\n", stderr); 484 485 mem_setup(&strm); 486 ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 487 strm.avail_in = 2; 488 strm.next_in = (void *)"\x03"; 489 ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 490 assert(ret == Z_STREAM_END); 491 /* force output error */ 492 strm.avail_in = 3; 493 strm.next_in = (void *)"\x63\x00"; 494 ret = inflateBack(&strm, pull, Z_NULL, push, &strm); 495 assert(ret == Z_BUF_ERROR); 496 /* force mode error by mucking with state */ 497 ret = inflateBack(&strm, pull, &strm, push, Z_NULL); 498 assert(ret == Z_STREAM_ERROR); 499 ret = inflateBackEnd(&strm); assert(ret == Z_OK); 500 mem_done(&strm, "inflateBack bad state"); 501 502 ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 503 ret = inflateBackEnd(&strm); assert(ret == Z_OK); 504 fputs("inflateBack built-in memory routines\n", stderr); 505 } 506 507 /* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ 508 local int try(char *hex, char *id, int err) 509 { 510 int ret; 511 unsigned len, size; 512 unsigned char *in, *out, *win; 513 char *prefix; 514 z_stream strm; 515 516 /* convert to hex */ 517 in = h2b(hex, &len); 518 assert(in != NULL); 519 520 /* allocate work areas */ 521 size = len << 3; 522 out = malloc(size); 523 assert(out != NULL); 524 win = malloc(32768); 525 assert(win != NULL); 526 prefix = malloc(strlen(id) + 6); 527 assert(prefix != NULL); 528 529 /* first with inflate */ 530 strcpy(prefix, id); 531 strcat(prefix, "-late"); 532 mem_setup(&strm); 533 strm.avail_in = 0; 534 strm.next_in = Z_NULL; 535 ret = inflateInit2(&strm, err < 0 ? 47 : -15); 536 assert(ret == Z_OK); 537 strm.avail_in = len; 538 strm.next_in = in; 539 do { 540 strm.avail_out = size; 541 strm.next_out = out; 542 ret = inflate(&strm, Z_TREES); 543 assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); 544 if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) 545 break; 546 } while (strm.avail_in || strm.avail_out == 0); 547 if (err) { 548 assert(ret == Z_DATA_ERROR); 549 assert(strcmp(id, strm.msg) == 0); 550 } 551 inflateEnd(&strm); 552 mem_done(&strm, prefix); 553 554 /* then with inflateBack */ 555 if (err >= 0) { 556 strcpy(prefix, id); 557 strcat(prefix, "-back"); 558 mem_setup(&strm); 559 ret = inflateBackInit(&strm, 15, win); 560 assert(ret == Z_OK); 561 strm.avail_in = len; 562 strm.next_in = in; 563 ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 564 assert(ret != Z_STREAM_ERROR); 565 if (err) { 566 assert(ret == Z_DATA_ERROR); 567 assert(strcmp(id, strm.msg) == 0); 568 } 569 inflateBackEnd(&strm); 570 mem_done(&strm, prefix); 571 } 572 573 /* clean up */ 574 free(prefix); 575 free(win); 576 free(out); 577 free(in); 578 return ret; 579 } 580 581 /* cover deflate data cases in both inflate() and inflateBack() */ 582 local void cover_inflate(void) 583 { 584 try("0 0 0 0 0", "invalid stored block lengths", 1); 585 try("3 0", "fixed", 0); 586 try("6", "invalid block type", 1); 587 try("1 1 0 fe ff 0", "stored", 0); 588 try("fc 0 0", "too many length or distance symbols", 1); 589 try("4 0 fe ff", "invalid code lengths set", 1); 590 try("4 0 24 49 0", "invalid bit length repeat", 1); 591 try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); 592 try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); 593 try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", 594 "invalid literal/lengths set", 1); 595 try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); 596 try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); 597 try("2 7e ff ff", "invalid distance code", 1); 598 try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); 599 600 /* also trailer mismatch just in inflate() */ 601 try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); 602 try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", 603 "incorrect length check", -1); 604 try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); 605 try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", 606 "long code", 0); 607 try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); 608 try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", 609 "long distance and extra", 0); 610 try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " 611 "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); 612 inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, 613 Z_STREAM_END); 614 inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); 615 } 616 617 /* cover remaining lines in inftrees.c */ 618 local void cover_trees(void) 619 { 620 int ret; 621 unsigned bits; 622 unsigned short lens[16], work[16]; 623 code *next, table[ENOUGH_DISTS]; 624 625 /* we need to call inflate_table() directly in order to manifest not- 626 enough errors, since zlib insures that enough is always enough */ 627 for (bits = 0; bits < 15; bits++) 628 lens[bits] = (unsigned short)(bits + 1); 629 lens[15] = 15; 630 next = table; 631 bits = 15; 632 ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 633 assert(ret == 1); 634 next = table; 635 bits = 1; 636 ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 637 assert(ret == 1); 638 fputs("inflate_table not enough errors\n", stderr); 639 } 640 641 /* cover remaining inffast.c decoding and window copying */ 642 local void cover_fast(void) 643 { 644 inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" 645 " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); 646 inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" 647 " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, 648 Z_DATA_ERROR); 649 inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, 650 Z_DATA_ERROR); 651 inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, 652 Z_DATA_ERROR); 653 inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", 654 "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); 655 inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); 656 inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", 657 "contiguous and wrap around window", 6, -8, 259, Z_OK); 658 inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, 659 Z_STREAM_END); 660 } 661 662 int main(void) 663 { 664 fprintf(stderr, "%s\n", zlibVersion()); 665 cover_support(); 666 cover_wrap(); 667 cover_back(); 668 cover_inflate(); 669 cover_trees(); 670 cover_fast(); 671 return 0; 672 } 673