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