12569963fSbluhm /* infcover.c -- test zlib's inflate routines with full code coverage
22569963fSbluhm * Copyright (C) 2011, 2016 Mark Adler
32569963fSbluhm * For conditions of distribution and use, see copyright notice in zlib.h
42569963fSbluhm */
52569963fSbluhm
62569963fSbluhm /* to use, do: ./configure --cover && make cover */
72569963fSbluhm
82569963fSbluhm #include <stdio.h>
92569963fSbluhm #include <stdlib.h>
102569963fSbluhm #include <string.h>
112569963fSbluhm #include <assert.h>
122569963fSbluhm #include "zlib.h"
132569963fSbluhm
142569963fSbluhm /* get definition of internal structure so we can mess with it (see pull()),
152569963fSbluhm and so we can call inflate_trees() (see cover5()) */
162569963fSbluhm #define ZLIB_INTERNAL
172569963fSbluhm #include "inftrees.h"
182569963fSbluhm #include "inflate.h"
192569963fSbluhm
202569963fSbluhm #define local static
212569963fSbluhm
222569963fSbluhm /* -- memory tracking routines -- */
232569963fSbluhm
242569963fSbluhm /*
252569963fSbluhm These memory tracking routines are provided to zlib and track all of zlib's
262569963fSbluhm allocations and deallocations, check for LIFO operations, keep a current
272569963fSbluhm and high water mark of total bytes requested, optionally set a limit on the
282569963fSbluhm total memory that can be allocated, and when done check for memory leaks.
292569963fSbluhm
302569963fSbluhm They are used as follows:
312569963fSbluhm
322569963fSbluhm z_stream strm;
332569963fSbluhm mem_setup(&strm) initializes the memory tracking and sets the
342569963fSbluhm zalloc, zfree, and opaque members of strm to use
352569963fSbluhm memory tracking for all zlib operations on strm
362569963fSbluhm mem_limit(&strm, limit) sets a limit on the total bytes requested -- a
372569963fSbluhm request that exceeds this limit will result in an
382569963fSbluhm allocation failure (returns NULL) -- setting the
392569963fSbluhm limit to zero means no limit, which is the default
402569963fSbluhm after mem_setup()
412569963fSbluhm mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used
422569963fSbluhm mem_high(&strm, "msg") prints to stderr "msg" and the high water mark
432569963fSbluhm mem_done(&strm, "msg") ends memory tracking, releases all allocations
442569963fSbluhm for the tracking as well as leaked zlib blocks, if
452569963fSbluhm any. If there was anything unusual, such as leaked
462569963fSbluhm blocks, non-FIFO frees, or frees of addresses not
472569963fSbluhm allocated, then "msg" and information about the
482569963fSbluhm problem is printed to stderr. If everything is
492569963fSbluhm normal, nothing is printed. mem_done resets the
502569963fSbluhm strm members to Z_NULL to use the default memory
512569963fSbluhm allocation routines on the next zlib initialization
522569963fSbluhm using strm.
532569963fSbluhm */
542569963fSbluhm
552569963fSbluhm /* these items are strung together in a linked list, one for each allocation */
562569963fSbluhm struct mem_item {
572569963fSbluhm void *ptr; /* pointer to allocated memory */
582569963fSbluhm size_t size; /* requested size of allocation */
592569963fSbluhm struct mem_item *next; /* pointer to next item in list, or NULL */
602569963fSbluhm };
612569963fSbluhm
622569963fSbluhm /* this structure is at the root of the linked list, and tracks statistics */
632569963fSbluhm struct mem_zone {
642569963fSbluhm struct mem_item *first; /* pointer to first item in list, or NULL */
652569963fSbluhm size_t total, highwater; /* total allocations, and largest total */
662569963fSbluhm size_t limit; /* memory allocation limit, or 0 if no limit */
672569963fSbluhm int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */
682569963fSbluhm };
692569963fSbluhm
702569963fSbluhm /* memory allocation routine to pass to zlib */
mem_alloc(void * mem,unsigned count,unsigned size)712569963fSbluhm local void *mem_alloc(void *mem, unsigned count, unsigned size)
722569963fSbluhm {
732569963fSbluhm void *ptr;
742569963fSbluhm struct mem_item *item;
752569963fSbluhm struct mem_zone *zone = mem;
762569963fSbluhm size_t len = count * (size_t)size;
772569963fSbluhm
782569963fSbluhm /* induced allocation failure */
792569963fSbluhm if (zone == NULL || (zone->limit && zone->total + len > zone->limit))
802569963fSbluhm return NULL;
812569963fSbluhm
822569963fSbluhm /* perform allocation using the standard library, fill memory with a
832569963fSbluhm non-zero value to make sure that the code isn't depending on zeros */
842569963fSbluhm ptr = malloc(len);
852569963fSbluhm if (ptr == NULL)
862569963fSbluhm return NULL;
872569963fSbluhm memset(ptr, 0xa5, len);
882569963fSbluhm
892569963fSbluhm /* create a new item for the list */
902569963fSbluhm item = malloc(sizeof(struct mem_item));
912569963fSbluhm if (item == NULL) {
922569963fSbluhm free(ptr);
932569963fSbluhm return NULL;
942569963fSbluhm }
952569963fSbluhm item->ptr = ptr;
962569963fSbluhm item->size = len;
972569963fSbluhm
982569963fSbluhm /* insert item at the beginning of the list */
992569963fSbluhm item->next = zone->first;
1002569963fSbluhm zone->first = item;
1012569963fSbluhm
1022569963fSbluhm /* update the statistics */
1032569963fSbluhm zone->total += item->size;
1042569963fSbluhm if (zone->total > zone->highwater)
1052569963fSbluhm zone->highwater = zone->total;
1062569963fSbluhm
1072569963fSbluhm /* return the allocated memory */
1082569963fSbluhm return ptr;
1092569963fSbluhm }
1102569963fSbluhm
1112569963fSbluhm /* memory free routine to pass to zlib */
mem_free(void * mem,void * ptr)1122569963fSbluhm local void mem_free(void *mem, void *ptr)
1132569963fSbluhm {
1142569963fSbluhm struct mem_item *item, *next;
1152569963fSbluhm struct mem_zone *zone = mem;
1162569963fSbluhm
1172569963fSbluhm /* if no zone, just do a free */
1182569963fSbluhm if (zone == NULL) {
1192569963fSbluhm free(ptr);
1202569963fSbluhm return;
1212569963fSbluhm }
1222569963fSbluhm
1232569963fSbluhm /* point next to the item that matches ptr, or NULL if not found -- remove
1242569963fSbluhm the item from the linked list if found */
1252569963fSbluhm next = zone->first;
1262569963fSbluhm if (next) {
1272569963fSbluhm if (next->ptr == ptr)
1282569963fSbluhm zone->first = next->next; /* first one is it, remove from list */
1292569963fSbluhm else {
1302569963fSbluhm do { /* search the linked list */
1312569963fSbluhm item = next;
1322569963fSbluhm next = item->next;
1332569963fSbluhm } while (next != NULL && next->ptr != ptr);
1342569963fSbluhm if (next) { /* if found, remove from linked list */
1352569963fSbluhm item->next = next->next;
1362569963fSbluhm zone->notlifo++; /* not a LIFO free */
1372569963fSbluhm }
1382569963fSbluhm
1392569963fSbluhm }
1402569963fSbluhm }
1412569963fSbluhm
1422569963fSbluhm /* if found, update the statistics and free the item */
1432569963fSbluhm if (next) {
1442569963fSbluhm zone->total -= next->size;
1452569963fSbluhm free(next);
1462569963fSbluhm }
1472569963fSbluhm
1482569963fSbluhm /* if not found, update the rogue count */
1492569963fSbluhm else
1502569963fSbluhm zone->rogue++;
1512569963fSbluhm
1522569963fSbluhm /* in any case, do the requested free with the standard library function */
1532569963fSbluhm free(ptr);
1542569963fSbluhm }
1552569963fSbluhm
1562569963fSbluhm /* set up a controlled memory allocation space for monitoring, set the stream
1572569963fSbluhm parameters to the controlled routines, with opaque pointing to the space */
mem_setup(z_stream * strm)1582569963fSbluhm local void mem_setup(z_stream *strm)
1592569963fSbluhm {
1602569963fSbluhm struct mem_zone *zone;
1612569963fSbluhm
1622569963fSbluhm zone = malloc(sizeof(struct mem_zone));
1632569963fSbluhm assert(zone != NULL);
1642569963fSbluhm zone->first = NULL;
1652569963fSbluhm zone->total = 0;
1662569963fSbluhm zone->highwater = 0;
1672569963fSbluhm zone->limit = 0;
1682569963fSbluhm zone->notlifo = 0;
1692569963fSbluhm zone->rogue = 0;
1702569963fSbluhm strm->opaque = zone;
1712569963fSbluhm strm->zalloc = mem_alloc;
1722569963fSbluhm strm->zfree = mem_free;
1732569963fSbluhm }
1742569963fSbluhm
1752569963fSbluhm /* set a limit on the total memory allocation, or 0 to remove the limit */
mem_limit(z_stream * strm,size_t limit)1762569963fSbluhm local void mem_limit(z_stream *strm, size_t limit)
1772569963fSbluhm {
1782569963fSbluhm struct mem_zone *zone = strm->opaque;
1792569963fSbluhm
1802569963fSbluhm zone->limit = limit;
1812569963fSbluhm }
1822569963fSbluhm
1832569963fSbluhm /* show the current total requested allocations in bytes */
mem_used(z_stream * strm,char * prefix)1842569963fSbluhm local void mem_used(z_stream *strm, char *prefix)
1852569963fSbluhm {
1862569963fSbluhm struct mem_zone *zone = strm->opaque;
1872569963fSbluhm
188*b9911c80Stb fprintf(stderr, "%s: %zu allocated\n", prefix, zone->total);
1892569963fSbluhm }
1902569963fSbluhm
1912569963fSbluhm /* show the high water allocation in bytes */
mem_high(z_stream * strm,char * prefix)1922569963fSbluhm local void mem_high(z_stream *strm, char *prefix)
1932569963fSbluhm {
1942569963fSbluhm struct mem_zone *zone = strm->opaque;
1952569963fSbluhm
196*b9911c80Stb fprintf(stderr, "%s: %zu high water mark\n", prefix, zone->highwater);
1972569963fSbluhm }
1982569963fSbluhm
1992569963fSbluhm /* release the memory allocation zone -- if there are any surprises, notify */
mem_done(z_stream * strm,char * prefix)2002569963fSbluhm local void mem_done(z_stream *strm, char *prefix)
2012569963fSbluhm {
2022569963fSbluhm int count = 0;
2032569963fSbluhm struct mem_item *item, *next;
2042569963fSbluhm struct mem_zone *zone = strm->opaque;
2052569963fSbluhm
2062569963fSbluhm /* show high water mark */
2072569963fSbluhm mem_high(strm, prefix);
2082569963fSbluhm
2092569963fSbluhm /* free leftover allocations and item structures, if any */
2102569963fSbluhm item = zone->first;
2112569963fSbluhm while (item != NULL) {
2122569963fSbluhm free(item->ptr);
2132569963fSbluhm next = item->next;
2142569963fSbluhm free(item);
2152569963fSbluhm item = next;
2162569963fSbluhm count++;
2172569963fSbluhm }
2182569963fSbluhm
2192569963fSbluhm /* issue alerts about anything unexpected */
2202569963fSbluhm if (count || zone->total)
221*b9911c80Stb fprintf(stderr, "** %s: %zu bytes in %d blocks not freed\n",
2222569963fSbluhm prefix, zone->total, count);
2232569963fSbluhm if (zone->notlifo)
2242569963fSbluhm fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo);
2252569963fSbluhm if (zone->rogue)
2262569963fSbluhm fprintf(stderr, "** %s: %d frees not recognized\n",
2272569963fSbluhm prefix, zone->rogue);
2282569963fSbluhm
2292569963fSbluhm /* free the zone and delete from the stream */
2302569963fSbluhm free(zone);
2312569963fSbluhm strm->opaque = Z_NULL;
2322569963fSbluhm strm->zalloc = Z_NULL;
2332569963fSbluhm strm->zfree = Z_NULL;
2342569963fSbluhm }
2352569963fSbluhm
2362569963fSbluhm /* -- inflate test routines -- */
2372569963fSbluhm
2382569963fSbluhm /* Decode a hexadecimal string, set *len to length, in[] to the bytes. This
2392569963fSbluhm decodes liberally, in that hex digits can be adjacent, in which case two in
2402569963fSbluhm a row writes a byte. Or they can be delimited by any non-hex character,
2412569963fSbluhm where the delimiters are ignored except when a single hex digit is followed
2422569963fSbluhm by a delimiter, where that single digit writes a byte. The returned data is
2432569963fSbluhm allocated and must eventually be freed. NULL is returned if out of memory.
2442569963fSbluhm If the length is not needed, then len can be NULL. */
h2b(const char * hex,unsigned * len)2452569963fSbluhm local unsigned char *h2b(const char *hex, unsigned *len)
2462569963fSbluhm {
2472569963fSbluhm unsigned char *in, *re;
2482569963fSbluhm unsigned next, val;
2492569963fSbluhm
2502569963fSbluhm in = malloc((strlen(hex) + 1) >> 1);
2512569963fSbluhm if (in == NULL)
2522569963fSbluhm return NULL;
2532569963fSbluhm next = 0;
2542569963fSbluhm val = 1;
2552569963fSbluhm do {
2562569963fSbluhm if (*hex >= '0' && *hex <= '9')
2572569963fSbluhm val = (val << 4) + *hex - '0';
2582569963fSbluhm else if (*hex >= 'A' && *hex <= 'F')
2592569963fSbluhm val = (val << 4) + *hex - 'A' + 10;
2602569963fSbluhm else if (*hex >= 'a' && *hex <= 'f')
2612569963fSbluhm val = (val << 4) + *hex - 'a' + 10;
2622569963fSbluhm else if (val != 1 && val < 32) /* one digit followed by delimiter */
2632569963fSbluhm val += 240; /* make it look like two digits */
2642569963fSbluhm if (val > 255) { /* have two digits */
2652569963fSbluhm in[next++] = val & 0xff; /* save the decoded byte */
2662569963fSbluhm val = 1; /* start over */
2672569963fSbluhm }
2682569963fSbluhm } while (*hex++); /* go through the loop with the terminating null */
2692569963fSbluhm if (len != NULL)
2702569963fSbluhm *len = next;
2712569963fSbluhm re = realloc(in, next);
2722569963fSbluhm return re == NULL ? in : re;
2732569963fSbluhm }
2742569963fSbluhm
2752569963fSbluhm /* generic inflate() run, where hex is the hexadecimal input data, what is the
2762569963fSbluhm text to include in an error message, step is how much input data to feed
2772569963fSbluhm inflate() on each call, or zero to feed it all, win is the window bits
2782569963fSbluhm parameter to inflateInit2(), len is the size of the output buffer, and err
2792569963fSbluhm is the error code expected from the first inflate() call (the second
2802569963fSbluhm inflate() call is expected to return Z_STREAM_END). If win is 47, then
2812569963fSbluhm header information is collected with inflateGetHeader(). If a zlib stream
2822569963fSbluhm is looking for a dictionary, then an empty dictionary is provided.
2832569963fSbluhm inflate() is run until all of the input data is consumed. */
inf(char * hex,char * what,unsigned step,int win,unsigned len,int err)2842569963fSbluhm local void inf(char *hex, char *what, unsigned step, int win, unsigned len,
2852569963fSbluhm int err)
2862569963fSbluhm {
2872569963fSbluhm int ret;
2882569963fSbluhm unsigned have;
2892569963fSbluhm unsigned char *in, *out;
2902569963fSbluhm z_stream strm, copy;
2912569963fSbluhm gz_header head;
2922569963fSbluhm
2932569963fSbluhm mem_setup(&strm);
2942569963fSbluhm strm.avail_in = 0;
2952569963fSbluhm strm.next_in = Z_NULL;
2962569963fSbluhm ret = inflateInit2(&strm, win);
2972569963fSbluhm if (ret != Z_OK) {
2982569963fSbluhm mem_done(&strm, what);
2992569963fSbluhm return;
3002569963fSbluhm }
3012569963fSbluhm out = malloc(len); assert(out != NULL);
3022569963fSbluhm if (win == 47) {
3032569963fSbluhm head.extra = out;
3042569963fSbluhm head.extra_max = len;
3052569963fSbluhm head.name = out;
3062569963fSbluhm head.name_max = len;
3072569963fSbluhm head.comment = out;
3082569963fSbluhm head.comm_max = len;
3092569963fSbluhm ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK);
3102569963fSbluhm }
3112569963fSbluhm in = h2b(hex, &have); assert(in != NULL);
3122569963fSbluhm if (step == 0 || step > have)
3132569963fSbluhm step = have;
3142569963fSbluhm strm.avail_in = step;
3152569963fSbluhm have -= step;
3162569963fSbluhm strm.next_in = in;
3172569963fSbluhm do {
3182569963fSbluhm strm.avail_out = len;
3192569963fSbluhm strm.next_out = out;
3202569963fSbluhm ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err);
3212569963fSbluhm if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT)
3222569963fSbluhm break;
3232569963fSbluhm if (ret == Z_NEED_DICT) {
3242569963fSbluhm ret = inflateSetDictionary(&strm, in, 1);
3252569963fSbluhm assert(ret == Z_DATA_ERROR);
3262569963fSbluhm mem_limit(&strm, 1);
3272569963fSbluhm ret = inflateSetDictionary(&strm, out, 0);
3282569963fSbluhm assert(ret == Z_MEM_ERROR);
3292569963fSbluhm mem_limit(&strm, 0);
3302569963fSbluhm ((struct inflate_state *)strm.state)->mode = DICT;
3312569963fSbluhm ret = inflateSetDictionary(&strm, out, 0);
3322569963fSbluhm assert(ret == Z_OK);
3332569963fSbluhm ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR);
3342569963fSbluhm }
3352569963fSbluhm ret = inflateCopy(©, &strm); assert(ret == Z_OK);
3362569963fSbluhm ret = inflateEnd(©); assert(ret == Z_OK);
3372569963fSbluhm err = 9; /* don't care next time around */
3382569963fSbluhm have += strm.avail_in;
3392569963fSbluhm strm.avail_in = step > have ? have : step;
3402569963fSbluhm have -= strm.avail_in;
3412569963fSbluhm } while (strm.avail_in);
3422569963fSbluhm free(in);
3432569963fSbluhm free(out);
3442569963fSbluhm ret = inflateReset2(&strm, -8); assert(ret == Z_OK);
3452569963fSbluhm ret = inflateEnd(&strm); assert(ret == Z_OK);
3462569963fSbluhm mem_done(&strm, what);
3472569963fSbluhm }
3482569963fSbluhm
3492569963fSbluhm /* cover all of the lines in inflate.c up to inflate() */
cover_support(void)3502569963fSbluhm local void cover_support(void)
3512569963fSbluhm {
3522569963fSbluhm int ret;
3532569963fSbluhm z_stream strm;
3542569963fSbluhm
3552569963fSbluhm mem_setup(&strm);
3562569963fSbluhm strm.avail_in = 0;
3572569963fSbluhm strm.next_in = Z_NULL;
3582569963fSbluhm ret = inflateInit(&strm); assert(ret == Z_OK);
3592569963fSbluhm mem_used(&strm, "inflate init");
3602569963fSbluhm ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK);
3612569963fSbluhm ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK);
3622569963fSbluhm ret = inflateSetDictionary(&strm, Z_NULL, 0);
3632569963fSbluhm assert(ret == Z_STREAM_ERROR);
3642569963fSbluhm ret = inflateEnd(&strm); assert(ret == Z_OK);
3652569963fSbluhm mem_done(&strm, "prime");
3662569963fSbluhm
3672569963fSbluhm inf("63 0", "force window allocation", 0, -15, 1, Z_OK);
3682569963fSbluhm inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK);
3692569963fSbluhm inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK);
3702569963fSbluhm inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END);
3712569963fSbluhm inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR);
3722569963fSbluhm
3732569963fSbluhm mem_setup(&strm);
3742569963fSbluhm strm.avail_in = 0;
3752569963fSbluhm strm.next_in = Z_NULL;
3762569963fSbluhm ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream));
3772569963fSbluhm assert(ret == Z_VERSION_ERROR);
3782569963fSbluhm mem_done(&strm, "wrong version");
3792569963fSbluhm
3802569963fSbluhm strm.avail_in = 0;
3812569963fSbluhm strm.next_in = Z_NULL;
3822569963fSbluhm ret = inflateInit(&strm); assert(ret == Z_OK);
3832569963fSbluhm ret = inflateEnd(&strm); assert(ret == Z_OK);
3842569963fSbluhm fputs("inflate built-in memory routines\n", stderr);
3852569963fSbluhm }
3862569963fSbluhm
3872569963fSbluhm /* cover all inflate() header and trailer cases and code after inflate() */
cover_wrap(void)3882569963fSbluhm local void cover_wrap(void)
3892569963fSbluhm {
3902569963fSbluhm int ret;
3912569963fSbluhm z_stream strm, copy;
3922569963fSbluhm unsigned char dict[257];
3932569963fSbluhm
3942569963fSbluhm ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR);
3952569963fSbluhm ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
3962569963fSbluhm ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR);
3972569963fSbluhm fputs("inflate bad parameters\n", stderr);
3982569963fSbluhm
3992569963fSbluhm inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR);
4002569963fSbluhm inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR);
4012569963fSbluhm inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR);
4022569963fSbluhm inf("8 99", "set window size from header", 0, 0, 0, Z_OK);
4032569963fSbluhm inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR);
4042569963fSbluhm inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END);
4052569963fSbluhm inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1,
4062569963fSbluhm Z_DATA_ERROR);
4072569963fSbluhm 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",
4082569963fSbluhm 0, 47, 0, Z_STREAM_END);
4092569963fSbluhm inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR);
4102569963fSbluhm inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT);
4112569963fSbluhm inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK);
4122569963fSbluhm
4132569963fSbluhm mem_setup(&strm);
4142569963fSbluhm strm.avail_in = 0;
4152569963fSbluhm strm.next_in = Z_NULL;
4162569963fSbluhm ret = inflateInit2(&strm, -8);
4172569963fSbluhm strm.avail_in = 2;
4182569963fSbluhm strm.next_in = (void *)"\x63";
4192569963fSbluhm strm.avail_out = 1;
4202569963fSbluhm strm.next_out = (void *)&ret;
4212569963fSbluhm mem_limit(&strm, 1);
4222569963fSbluhm ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
4232569963fSbluhm ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
4242569963fSbluhm mem_limit(&strm, 0);
4252569963fSbluhm memset(dict, 0, 257);
4262569963fSbluhm ret = inflateSetDictionary(&strm, dict, 257);
4272569963fSbluhm assert(ret == Z_OK);
4282569963fSbluhm mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256);
4292569963fSbluhm ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK);
4302569963fSbluhm strm.avail_in = 2;
4312569963fSbluhm strm.next_in = (void *)"\x80";
4322569963fSbluhm ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR);
4332569963fSbluhm ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR);
4342569963fSbluhm strm.avail_in = 4;
4352569963fSbluhm strm.next_in = (void *)"\0\0\xff\xff";
4362569963fSbluhm ret = inflateSync(&strm); assert(ret == Z_OK);
4372569963fSbluhm (void)inflateSyncPoint(&strm);
4382569963fSbluhm ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR);
4392569963fSbluhm mem_limit(&strm, 0);
4402569963fSbluhm ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR);
4412569963fSbluhm (void)inflateMark(&strm);
4422569963fSbluhm ret = inflateEnd(&strm); assert(ret == Z_OK);
4432569963fSbluhm mem_done(&strm, "miscellaneous, force memory errors");
4442569963fSbluhm }
4452569963fSbluhm
4462569963fSbluhm /* input and output functions for inflateBack() */
pull(void * desc,unsigned char ** buf)4472569963fSbluhm local unsigned pull(void *desc, unsigned char **buf)
4482569963fSbluhm {
4492569963fSbluhm static unsigned int next = 0;
4502569963fSbluhm static unsigned char dat[] = {0x63, 0, 2, 0};
4512569963fSbluhm struct inflate_state *state;
4522569963fSbluhm
4532569963fSbluhm if (desc == Z_NULL) {
4542569963fSbluhm next = 0;
4552569963fSbluhm return 0; /* no input (already provided at next_in) */
4562569963fSbluhm }
4572569963fSbluhm state = (void *)((z_stream *)desc)->state;
4582569963fSbluhm if (state != Z_NULL)
4592569963fSbluhm state->mode = SYNC; /* force an otherwise impossible situation */
4602569963fSbluhm return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0;
4612569963fSbluhm }
4622569963fSbluhm
push(void * desc,unsigned char * buf,unsigned len)4632569963fSbluhm local int push(void *desc, unsigned char *buf, unsigned len)
4642569963fSbluhm {
4652569963fSbluhm buf += len;
4662569963fSbluhm return desc != Z_NULL; /* force error if desc not null */
4672569963fSbluhm }
4682569963fSbluhm
4692569963fSbluhm /* cover inflateBack() up to common deflate data cases and after those */
cover_back(void)4702569963fSbluhm local void cover_back(void)
4712569963fSbluhm {
4722569963fSbluhm int ret;
4732569963fSbluhm z_stream strm;
4742569963fSbluhm unsigned char win[32768];
4752569963fSbluhm
4762569963fSbluhm ret = inflateBackInit_(Z_NULL, 0, win, 0, 0);
4772569963fSbluhm assert(ret == Z_VERSION_ERROR);
4782569963fSbluhm ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR);
4792569963fSbluhm ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL);
4802569963fSbluhm assert(ret == Z_STREAM_ERROR);
4812569963fSbluhm ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
4822569963fSbluhm fputs("inflateBack bad parameters\n", stderr);
4832569963fSbluhm
4842569963fSbluhm mem_setup(&strm);
4852569963fSbluhm ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
4862569963fSbluhm strm.avail_in = 2;
4872569963fSbluhm strm.next_in = (void *)"\x03";
4882569963fSbluhm ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
4892569963fSbluhm assert(ret == Z_STREAM_END);
4902569963fSbluhm /* force output error */
4912569963fSbluhm strm.avail_in = 3;
4922569963fSbluhm strm.next_in = (void *)"\x63\x00";
4932569963fSbluhm ret = inflateBack(&strm, pull, Z_NULL, push, &strm);
4942569963fSbluhm assert(ret == Z_BUF_ERROR);
4952569963fSbluhm /* force mode error by mucking with state */
4962569963fSbluhm ret = inflateBack(&strm, pull, &strm, push, Z_NULL);
4972569963fSbluhm assert(ret == Z_STREAM_ERROR);
4982569963fSbluhm ret = inflateBackEnd(&strm); assert(ret == Z_OK);
4992569963fSbluhm mem_done(&strm, "inflateBack bad state");
5002569963fSbluhm
5012569963fSbluhm ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
5022569963fSbluhm ret = inflateBackEnd(&strm); assert(ret == Z_OK);
5032569963fSbluhm fputs("inflateBack built-in memory routines\n", stderr);
5042569963fSbluhm }
5052569963fSbluhm
5062569963fSbluhm /* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
try(char * hex,char * id,int err)5072569963fSbluhm local int try(char *hex, char *id, int err)
5082569963fSbluhm {
5092569963fSbluhm int ret;
5102569963fSbluhm unsigned len, size;
5112569963fSbluhm unsigned char *in, *out, *win;
5122569963fSbluhm char *prefix;
5132569963fSbluhm z_stream strm;
5142569963fSbluhm
5152569963fSbluhm /* convert to hex */
5162569963fSbluhm in = h2b(hex, &len);
5172569963fSbluhm assert(in != NULL);
5182569963fSbluhm
5192569963fSbluhm /* allocate work areas */
5202569963fSbluhm size = len << 3;
5212569963fSbluhm out = malloc(size);
5222569963fSbluhm assert(out != NULL);
5232569963fSbluhm win = malloc(32768);
5242569963fSbluhm assert(win != NULL);
5252569963fSbluhm prefix = malloc(strlen(id) + 6);
5262569963fSbluhm assert(prefix != NULL);
5272569963fSbluhm
5282569963fSbluhm /* first with inflate */
5292569963fSbluhm strcpy(prefix, id);
5302569963fSbluhm strcat(prefix, "-late");
5312569963fSbluhm mem_setup(&strm);
5322569963fSbluhm strm.avail_in = 0;
5332569963fSbluhm strm.next_in = Z_NULL;
5342569963fSbluhm ret = inflateInit2(&strm, err < 0 ? 47 : -15);
5352569963fSbluhm assert(ret == Z_OK);
5362569963fSbluhm strm.avail_in = len;
5372569963fSbluhm strm.next_in = in;
5382569963fSbluhm do {
5392569963fSbluhm strm.avail_out = size;
5402569963fSbluhm strm.next_out = out;
5412569963fSbluhm ret = inflate(&strm, Z_TREES);
5422569963fSbluhm assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR);
5432569963fSbluhm if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT)
5442569963fSbluhm break;
5452569963fSbluhm } while (strm.avail_in || strm.avail_out == 0);
5462569963fSbluhm if (err) {
5472569963fSbluhm assert(ret == Z_DATA_ERROR);
5482569963fSbluhm assert(strcmp(id, strm.msg) == 0);
5492569963fSbluhm }
5502569963fSbluhm inflateEnd(&strm);
5512569963fSbluhm mem_done(&strm, prefix);
5522569963fSbluhm
5532569963fSbluhm /* then with inflateBack */
5542569963fSbluhm if (err >= 0) {
5552569963fSbluhm strcpy(prefix, id);
5562569963fSbluhm strcat(prefix, "-back");
5572569963fSbluhm mem_setup(&strm);
5582569963fSbluhm ret = inflateBackInit(&strm, 15, win);
5592569963fSbluhm assert(ret == Z_OK);
5602569963fSbluhm strm.avail_in = len;
5612569963fSbluhm strm.next_in = in;
5622569963fSbluhm ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
5632569963fSbluhm assert(ret != Z_STREAM_ERROR);
5642569963fSbluhm if (err) {
5652569963fSbluhm assert(ret == Z_DATA_ERROR);
5662569963fSbluhm assert(strcmp(id, strm.msg) == 0);
5672569963fSbluhm }
5682569963fSbluhm inflateBackEnd(&strm);
5692569963fSbluhm mem_done(&strm, prefix);
5702569963fSbluhm }
5712569963fSbluhm
5722569963fSbluhm /* clean up */
5732569963fSbluhm free(prefix);
5742569963fSbluhm free(win);
5752569963fSbluhm free(out);
5762569963fSbluhm free(in);
5772569963fSbluhm return ret;
5782569963fSbluhm }
5792569963fSbluhm
5802569963fSbluhm /* cover deflate data cases in both inflate() and inflateBack() */
cover_inflate(void)5812569963fSbluhm local void cover_inflate(void)
5822569963fSbluhm {
5832569963fSbluhm try("0 0 0 0 0", "invalid stored block lengths", 1);
5842569963fSbluhm try("3 0", "fixed", 0);
5852569963fSbluhm try("6", "invalid block type", 1);
5862569963fSbluhm try("1 1 0 fe ff 0", "stored", 0);
5872569963fSbluhm try("fc 0 0", "too many length or distance symbols", 1);
5882569963fSbluhm try("4 0 fe ff", "invalid code lengths set", 1);
5892569963fSbluhm try("4 0 24 49 0", "invalid bit length repeat", 1);
5902569963fSbluhm try("4 0 24 e9 ff ff", "invalid bit length repeat", 1);
5912569963fSbluhm try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1);
5922569963fSbluhm try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0",
5932569963fSbluhm "invalid literal/lengths set", 1);
5942569963fSbluhm try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1);
5952569963fSbluhm try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1);
5962569963fSbluhm try("2 7e ff ff", "invalid distance code", 1);
5972569963fSbluhm try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1);
5982569963fSbluhm
5992569963fSbluhm /* also trailer mismatch just in inflate() */
6002569963fSbluhm try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1);
6012569963fSbluhm try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1",
6022569963fSbluhm "incorrect length check", -1);
6032569963fSbluhm try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0);
6042569963fSbluhm try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f",
6052569963fSbluhm "long code", 0);
6062569963fSbluhm try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0);
6072569963fSbluhm 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",
6082569963fSbluhm "long distance and extra", 0);
6092569963fSbluhm 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 "
6102569963fSbluhm "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0);
6112569963fSbluhm inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258,
6122569963fSbluhm Z_STREAM_END);
6132569963fSbluhm inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK);
6142569963fSbluhm }
6152569963fSbluhm
6162569963fSbluhm /* cover remaining lines in inftrees.c */
cover_trees(void)6172569963fSbluhm local void cover_trees(void)
6182569963fSbluhm {
6192569963fSbluhm int ret;
6202569963fSbluhm unsigned bits;
6212569963fSbluhm unsigned short lens[16], work[16];
6222569963fSbluhm code *next, table[ENOUGH_DISTS];
6232569963fSbluhm
6242569963fSbluhm /* we need to call inflate_table() directly in order to manifest not-
6252569963fSbluhm enough errors, since zlib insures that enough is always enough */
6262569963fSbluhm for (bits = 0; bits < 15; bits++)
6272569963fSbluhm lens[bits] = (unsigned short)(bits + 1);
6282569963fSbluhm lens[15] = 15;
6292569963fSbluhm next = table;
6302569963fSbluhm bits = 15;
6312569963fSbluhm ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
6322569963fSbluhm assert(ret == 1);
6332569963fSbluhm next = table;
6342569963fSbluhm bits = 1;
6352569963fSbluhm ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
6362569963fSbluhm assert(ret == 1);
6372569963fSbluhm fputs("inflate_table not enough errors\n", stderr);
6382569963fSbluhm }
6392569963fSbluhm
6402569963fSbluhm /* cover remaining inffast.c decoding and window copying */
cover_fast(void)6412569963fSbluhm local void cover_fast(void)
6422569963fSbluhm {
6432569963fSbluhm inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68"
6442569963fSbluhm " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR);
6452569963fSbluhm inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49"
6462569963fSbluhm " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258,
6472569963fSbluhm Z_DATA_ERROR);
6482569963fSbluhm inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258,
6492569963fSbluhm Z_DATA_ERROR);
6502569963fSbluhm inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258,
6512569963fSbluhm Z_DATA_ERROR);
6522569963fSbluhm 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",
6532569963fSbluhm "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR);
6542569963fSbluhm inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK);
6552569963fSbluhm inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0",
6562569963fSbluhm "contiguous and wrap around window", 6, -8, 259, Z_OK);
6572569963fSbluhm inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259,
6582569963fSbluhm Z_STREAM_END);
6592569963fSbluhm }
6602569963fSbluhm
main(void)6612569963fSbluhm int main(void)
6622569963fSbluhm {
6632569963fSbluhm fprintf(stderr, "%s\n", zlibVersion());
6642569963fSbluhm cover_support();
6652569963fSbluhm cover_wrap();
6662569963fSbluhm cover_back();
6672569963fSbluhm cover_inflate();
6682569963fSbluhm cover_trees();
6692569963fSbluhm cover_fast();
6702569963fSbluhm return 0;
6712569963fSbluhm }
672