1 /* infcover.c -- test zlib's inflate routines with full code coverage
2 * Copyright (C) 2011 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 */
mem_alloc(void * mem,unsigned count,unsigned size)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 */
mem_free(void * mem,void * ptr)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 */
mem_setup(z_stream * strm)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 */
mem_limit(z_stream * strm,size_t 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 */
mem_used(z_stream * strm,char * prefix)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 */
mem_high(z_stream * strm,char * prefix)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 */
mem_done(z_stream * strm,char * prefix)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 delimited by any non-hex character, where
241 the delimiters are ignored except when a single hex digit is followed by a
242 delimiter in which case that single digit writes a byte. The returned
243 data is allocated and must eventually be freed. NULL is returned if out of
244 memory. If the length is not needed, then len can be NULL. */
h2b(const char * hex,unsigned * len)245 local unsigned char *h2b(const char *hex, unsigned *len)
246 {
247 unsigned char *in;
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 in = reallocf(in, next);
272 return in;
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. */
inf(char * hex,char * what,unsigned step,int win,unsigned len,int err)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() */
cover_support(void)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, ZLIB_VERSION - 1, (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() */
cover_wrap(void)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() */
pull(void * desc,unsigned char ** buf)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
push(void * desc,unsigned char * buf,unsigned len)463 local int push(void *desc, unsigned char *buf, unsigned len)
464 {
465 buf += len;
466 return desc != Z_NULL; /* force error if desc not null */
467 }
468
469 /* cover inflateBack() up to common deflate data cases and after those */
cover_back(void)470 local void cover_back(void)
471 {
472 int ret;
473 z_stream strm;
474 unsigned char win[32768];
475
476 ret = inflateBackInit_(Z_NULL, 0, win, 0, 0);
477 assert(ret == Z_VERSION_ERROR);
478 ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR);
479 ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL);
480 assert(ret == Z_STREAM_ERROR);
481 ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
482 fputs("inflateBack bad parameters\n", stderr);
483
484 mem_setup(&strm);
485 ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
486 strm.avail_in = 2;
487 strm.next_in = (void *)"\x03";
488 ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
489 assert(ret == Z_STREAM_END);
490 /* force output error */
491 strm.avail_in = 3;
492 strm.next_in = (void *)"\x63\x00";
493 ret = inflateBack(&strm, pull, Z_NULL, push, &strm);
494 assert(ret == Z_BUF_ERROR);
495 /* force mode error by mucking with state */
496 ret = inflateBack(&strm, pull, &strm, push, Z_NULL);
497 assert(ret == Z_STREAM_ERROR);
498 ret = inflateBackEnd(&strm); assert(ret == Z_OK);
499 mem_done(&strm, "inflateBack bad state");
500
501 ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
502 ret = inflateBackEnd(&strm); assert(ret == Z_OK);
503 fputs("inflateBack built-in memory routines\n", stderr);
504 }
505
506 /* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
try(char * hex,char * id,int err)507 local int try(char *hex, char *id, int err)
508 {
509 int ret;
510 unsigned len, size;
511 unsigned char *in, *out, *win;
512 char *prefix;
513 z_stream strm;
514
515 /* convert to hex */
516 in = h2b(hex, &len);
517 assert(in != NULL);
518
519 /* allocate work areas */
520 size = len << 3;
521 out = malloc(size);
522 assert(out != NULL);
523 win = malloc(32768);
524 assert(win != NULL);
525 prefix = malloc(strlen(id) + 6);
526 assert(prefix != NULL);
527
528 /* first with inflate */
529 strcpy(prefix, id);
530 strcat(prefix, "-late");
531 mem_setup(&strm);
532 strm.avail_in = 0;
533 strm.next_in = Z_NULL;
534 ret = inflateInit2(&strm, err < 0 ? 47 : -15);
535 assert(ret == Z_OK);
536 strm.avail_in = len;
537 strm.next_in = in;
538 do {
539 strm.avail_out = size;
540 strm.next_out = out;
541 ret = inflate(&strm, Z_TREES);
542 assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR);
543 if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT)
544 break;
545 } while (strm.avail_in || strm.avail_out == 0);
546 if (err) {
547 assert(ret == Z_DATA_ERROR);
548 assert(strcmp(id, strm.msg) == 0);
549 }
550 inflateEnd(&strm);
551 mem_done(&strm, prefix);
552
553 /* then with inflateBack */
554 if (err >= 0) {
555 strcpy(prefix, id);
556 strcat(prefix, "-back");
557 mem_setup(&strm);
558 ret = inflateBackInit(&strm, 15, win);
559 assert(ret == Z_OK);
560 strm.avail_in = len;
561 strm.next_in = in;
562 ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
563 assert(ret != Z_STREAM_ERROR);
564 if (err) {
565 assert(ret == Z_DATA_ERROR);
566 assert(strcmp(id, strm.msg) == 0);
567 }
568 inflateBackEnd(&strm);
569 mem_done(&strm, prefix);
570 }
571
572 /* clean up */
573 free(prefix);
574 free(win);
575 free(out);
576 free(in);
577 return ret;
578 }
579
580 /* cover deflate data cases in both inflate() and inflateBack() */
cover_inflate(void)581 local void cover_inflate(void)
582 {
583 try("0 0 0 0 0", "invalid stored block lengths", 1);
584 try("3 0", "fixed", 0);
585 try("6", "invalid block type", 1);
586 try("1 1 0 fe ff 0", "stored", 0);
587 try("fc 0 0", "too many length or distance symbols", 1);
588 try("4 0 fe ff", "invalid code lengths set", 1);
589 try("4 0 24 49 0", "invalid bit length repeat", 1);
590 try("4 0 24 e9 ff ff", "invalid bit length repeat", 1);
591 try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1);
592 try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0",
593 "invalid literal/lengths set", 1);
594 try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1);
595 try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1);
596 try("2 7e ff ff", "invalid distance code", 1);
597 try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1);
598
599 /* also trailer mismatch just in inflate() */
600 try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1);
601 try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1",
602 "incorrect length check", -1);
603 try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0);
604 try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f",
605 "long code", 0);
606 try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0);
607 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",
608 "long distance and extra", 0);
609 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 "
610 "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0);
611 inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258,
612 Z_STREAM_END);
613 inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK);
614 }
615
616 /* cover remaining lines in inftrees.c */
cover_trees(void)617 local void cover_trees(void)
618 {
619 int ret;
620 unsigned bits;
621 unsigned short lens[16], work[16];
622 code *next, table[ENOUGH_DISTS];
623
624 /* we need to call inflate_table() directly in order to manifest not-
625 enough errors, since zlib insures that enough is always enough */
626 for (bits = 0; bits < 15; bits++)
627 lens[bits] = (unsigned short)(bits + 1);
628 lens[15] = 15;
629 next = table;
630 bits = 15;
631 ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
632 assert(ret == 1);
633 next = table;
634 bits = 1;
635 ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
636 assert(ret == 1);
637 fputs("inflate_table not enough errors\n", stderr);
638 }
639
640 /* cover remaining inffast.c decoding and window copying */
cover_fast(void)641 local void cover_fast(void)
642 {
643 inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68"
644 " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR);
645 inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49"
646 " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258,
647 Z_DATA_ERROR);
648 inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258,
649 Z_DATA_ERROR);
650 inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258,
651 Z_DATA_ERROR);
652 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",
653 "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR);
654 inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK);
655 inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0",
656 "contiguous and wrap around window", 6, -8, 259, Z_OK);
657 inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259,
658 Z_STREAM_END);
659 }
660
main(void)661 int main(void)
662 {
663 fprintf(stderr, "%s\n", zlibVersion());
664 cover_support();
665 cover_wrap();
666 cover_back();
667 cover_inflate();
668 cover_trees();
669 cover_fast();
670 return 0;
671 }
672