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 */
56struct 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 */
63struct 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 */
71local 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 */
112local 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 */
158local 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 */
176local 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 */
184local 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 */
192local 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 */
200local 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. */
245local 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. */
284local 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() */
350local 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() */
388local 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() */
447local 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
463local 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 */
470local 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 */
507local 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() */
581local 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 */
617local 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 */
641local 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
661int 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