xref: /freebsd/sys/contrib/zlib/test/infcover.c (revision 61e21613)
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(&copy, &strm);        assert(ret == Z_OK);
336         ret = inflateEnd(&copy);                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(&copy, &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