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