1230837Sdelphij/* infcover.c -- test zlib's inflate routines with full code coverage 2230837Sdelphij * Copyright (C) 2011 Mark Adler 3230837Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4230837Sdelphij */ 5230837Sdelphij 6230837Sdelphij/* to use, do: ./configure --cover && make cover */ 7230837Sdelphij 8230837Sdelphij#include <stdio.h> 9230837Sdelphij#include <stdlib.h> 10230837Sdelphij#include <string.h> 11230837Sdelphij#include <assert.h> 12230837Sdelphij#include "zlib.h" 13230837Sdelphij 14230837Sdelphij/* get definition of internal structure so we can mess with it (see pull()), 15230837Sdelphij and so we can call inflate_trees() (see cover5()) */ 16230837Sdelphij#define ZLIB_INTERNAL 17230837Sdelphij#include "inftrees.h" 18230837Sdelphij#include "inflate.h" 19230837Sdelphij 20230837Sdelphij#define local static 21230837Sdelphij 22230837Sdelphij/* -- memory tracking routines -- */ 23230837Sdelphij 24230837Sdelphij/* 25230837Sdelphij These memory tracking routines are provided to zlib and track all of zlib's 26230837Sdelphij allocations and deallocations, check for LIFO operations, keep a current 27230837Sdelphij and high water mark of total bytes requested, optionally set a limit on the 28230837Sdelphij total memory that can be allocated, and when done check for memory leaks. 29230837Sdelphij 30230837Sdelphij They are used as follows: 31230837Sdelphij 32230837Sdelphij z_stream strm; 33230837Sdelphij mem_setup(&strm) initializes the memory tracking and sets the 34230837Sdelphij zalloc, zfree, and opaque members of strm to use 35230837Sdelphij memory tracking for all zlib operations on strm 36230837Sdelphij mem_limit(&strm, limit) sets a limit on the total bytes requested -- a 37230837Sdelphij request that exceeds this limit will result in an 38230837Sdelphij allocation failure (returns NULL) -- setting the 39230837Sdelphij limit to zero means no limit, which is the default 40230837Sdelphij after mem_setup() 41230837Sdelphij mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used 42230837Sdelphij mem_high(&strm, "msg") prints to stderr "msg" and the high water mark 43230837Sdelphij mem_done(&strm, "msg") ends memory tracking, releases all allocations 44230837Sdelphij for the tracking as well as leaked zlib blocks, if 45230837Sdelphij any. If there was anything unusual, such as leaked 46230837Sdelphij blocks, non-FIFO frees, or frees of addresses not 47230837Sdelphij allocated, then "msg" and information about the 48230837Sdelphij problem is printed to stderr. If everything is 49230837Sdelphij normal, nothing is printed. mem_done resets the 50230837Sdelphij strm members to Z_NULL to use the default memory 51230837Sdelphij allocation routines on the next zlib initialization 52230837Sdelphij using strm. 53230837Sdelphij */ 54230837Sdelphij 55230837Sdelphij/* these items are strung together in a linked list, one for each allocation */ 56230837Sdelphijstruct mem_item { 57230837Sdelphij void *ptr; /* pointer to allocated memory */ 58230837Sdelphij size_t size; /* requested size of allocation */ 59230837Sdelphij struct mem_item *next; /* pointer to next item in list, or NULL */ 60230837Sdelphij}; 61230837Sdelphij 62230837Sdelphij/* this structure is at the root of the linked list, and tracks statistics */ 63230837Sdelphijstruct mem_zone { 64230837Sdelphij struct mem_item *first; /* pointer to first item in list, or NULL */ 65230837Sdelphij size_t total, highwater; /* total allocations, and largest total */ 66230837Sdelphij size_t limit; /* memory allocation limit, or 0 if no limit */ 67230837Sdelphij int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ 68230837Sdelphij}; 69230837Sdelphij 70230837Sdelphij/* memory allocation routine to pass to zlib */ 71230837Sdelphijlocal void *mem_alloc(void *mem, unsigned count, unsigned size) 72230837Sdelphij{ 73230837Sdelphij void *ptr; 74230837Sdelphij struct mem_item *item; 75230837Sdelphij struct mem_zone *zone = mem; 76230837Sdelphij size_t len = count * (size_t)size; 77230837Sdelphij 78230837Sdelphij /* induced allocation failure */ 79230837Sdelphij if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) 80230837Sdelphij return NULL; 81230837Sdelphij 82230837Sdelphij /* perform allocation using the standard library, fill memory with a 83230837Sdelphij non-zero value to make sure that the code isn't depending on zeros */ 84230837Sdelphij ptr = malloc(len); 85230837Sdelphij if (ptr == NULL) 86230837Sdelphij return NULL; 87230837Sdelphij memset(ptr, 0xa5, len); 88230837Sdelphij 89230837Sdelphij /* create a new item for the list */ 90230837Sdelphij item = malloc(sizeof(struct mem_item)); 91230837Sdelphij if (item == NULL) { 92230837Sdelphij free(ptr); 93230837Sdelphij return NULL; 94230837Sdelphij } 95230837Sdelphij item->ptr = ptr; 96230837Sdelphij item->size = len; 97230837Sdelphij 98230837Sdelphij /* insert item at the beginning of the list */ 99230837Sdelphij item->next = zone->first; 100230837Sdelphij zone->first = item; 101230837Sdelphij 102230837Sdelphij /* update the statistics */ 103230837Sdelphij zone->total += item->size; 104230837Sdelphij if (zone->total > zone->highwater) 105230837Sdelphij zone->highwater = zone->total; 106230837Sdelphij 107230837Sdelphij /* return the allocated memory */ 108230837Sdelphij return ptr; 109230837Sdelphij} 110230837Sdelphij 111230837Sdelphij/* memory free routine to pass to zlib */ 112230837Sdelphijlocal void mem_free(void *mem, void *ptr) 113230837Sdelphij{ 114230837Sdelphij struct mem_item *item, *next; 115230837Sdelphij struct mem_zone *zone = mem; 116230837Sdelphij 117230837Sdelphij /* if no zone, just do a free */ 118230837Sdelphij if (zone == NULL) { 119230837Sdelphij free(ptr); 120230837Sdelphij return; 121230837Sdelphij } 122230837Sdelphij 123230837Sdelphij /* point next to the item that matches ptr, or NULL if not found -- remove 124230837Sdelphij the item from the linked list if found */ 125230837Sdelphij next = zone->first; 126230837Sdelphij if (next) { 127230837Sdelphij if (next->ptr == ptr) 128230837Sdelphij zone->first = next->next; /* first one is it, remove from list */ 129230837Sdelphij else { 130230837Sdelphij do { /* search the linked list */ 131230837Sdelphij item = next; 132230837Sdelphij next = item->next; 133230837Sdelphij } while (next != NULL && next->ptr != ptr); 134230837Sdelphij if (next) { /* if found, remove from linked list */ 135230837Sdelphij item->next = next->next; 136230837Sdelphij zone->notlifo++; /* not a LIFO free */ 137230837Sdelphij } 138230837Sdelphij 139230837Sdelphij } 140230837Sdelphij } 141230837Sdelphij 142230837Sdelphij /* if found, update the statistics and free the item */ 143230837Sdelphij if (next) { 144230837Sdelphij zone->total -= next->size; 145230837Sdelphij free(next); 146230837Sdelphij } 147230837Sdelphij 148230837Sdelphij /* if not found, update the rogue count */ 149230837Sdelphij else 150230837Sdelphij zone->rogue++; 151230837Sdelphij 152230837Sdelphij /* in any case, do the requested free with the standard library function */ 153230837Sdelphij free(ptr); 154230837Sdelphij} 155230837Sdelphij 156230837Sdelphij/* set up a controlled memory allocation space for monitoring, set the stream 157230837Sdelphij parameters to the controlled routines, with opaque pointing to the space */ 158230837Sdelphijlocal void mem_setup(z_stream *strm) 159230837Sdelphij{ 160230837Sdelphij struct mem_zone *zone; 161230837Sdelphij 162230837Sdelphij zone = malloc(sizeof(struct mem_zone)); 163230837Sdelphij assert(zone != NULL); 164230837Sdelphij zone->first = NULL; 165230837Sdelphij zone->total = 0; 166230837Sdelphij zone->highwater = 0; 167230837Sdelphij zone->limit = 0; 168230837Sdelphij zone->notlifo = 0; 169230837Sdelphij zone->rogue = 0; 170230837Sdelphij strm->opaque = zone; 171230837Sdelphij strm->zalloc = mem_alloc; 172230837Sdelphij strm->zfree = mem_free; 173230837Sdelphij} 174230837Sdelphij 175230837Sdelphij/* set a limit on the total memory allocation, or 0 to remove the limit */ 176230837Sdelphijlocal void mem_limit(z_stream *strm, size_t limit) 177230837Sdelphij{ 178230837Sdelphij struct mem_zone *zone = strm->opaque; 179230837Sdelphij 180230837Sdelphij zone->limit = limit; 181230837Sdelphij} 182230837Sdelphij 183230837Sdelphij/* show the current total requested allocations in bytes */ 184230837Sdelphijlocal void mem_used(z_stream *strm, char *prefix) 185230837Sdelphij{ 186230837Sdelphij struct mem_zone *zone = strm->opaque; 187230837Sdelphij 188230837Sdelphij fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); 189230837Sdelphij} 190230837Sdelphij 191230837Sdelphij/* show the high water allocation in bytes */ 192230837Sdelphijlocal void mem_high(z_stream *strm, char *prefix) 193230837Sdelphij{ 194230837Sdelphij struct mem_zone *zone = strm->opaque; 195230837Sdelphij 196230837Sdelphij fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); 197230837Sdelphij} 198230837Sdelphij 199230837Sdelphij/* release the memory allocation zone -- if there are any surprises, notify */ 200230837Sdelphijlocal void mem_done(z_stream *strm, char *prefix) 201230837Sdelphij{ 202230837Sdelphij int count = 0; 203230837Sdelphij struct mem_item *item, *next; 204230837Sdelphij struct mem_zone *zone = strm->opaque; 205230837Sdelphij 206230837Sdelphij /* show high water mark */ 207230837Sdelphij mem_high(strm, prefix); 208230837Sdelphij 209230837Sdelphij /* free leftover allocations and item structures, if any */ 210230837Sdelphij item = zone->first; 211230837Sdelphij while (item != NULL) { 212230837Sdelphij free(item->ptr); 213230837Sdelphij next = item->next; 214230837Sdelphij free(item); 215230837Sdelphij item = next; 216230837Sdelphij count++; 217230837Sdelphij } 218230837Sdelphij 219230837Sdelphij /* issue alerts about anything unexpected */ 220230837Sdelphij if (count || zone->total) 221230837Sdelphij fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", 222230837Sdelphij prefix, zone->total, count); 223230837Sdelphij if (zone->notlifo) 224230837Sdelphij fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); 225230837Sdelphij if (zone->rogue) 226230837Sdelphij fprintf(stderr, "** %s: %d frees not recognized\n", 227230837Sdelphij prefix, zone->rogue); 228230837Sdelphij 229230837Sdelphij /* free the zone and delete from the stream */ 230230837Sdelphij free(zone); 231230837Sdelphij strm->opaque = Z_NULL; 232230837Sdelphij strm->zalloc = Z_NULL; 233230837Sdelphij strm->zfree = Z_NULL; 234230837Sdelphij} 235230837Sdelphij 236230837Sdelphij/* -- inflate test routines -- */ 237230837Sdelphij 238230837Sdelphij/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This 239230837Sdelphij decodes liberally, in that hex digits can be adjacent, in which case two in 240230837Sdelphij a row writes a byte. Or they can delimited by any non-hex character, where 241230837Sdelphij the delimiters are ignored except when a single hex digit is followed by a 242230837Sdelphij delimiter in which case that single digit writes a byte. The returned 243230837Sdelphij data is allocated and must eventually be freed. NULL is returned if out of 244230837Sdelphij memory. If the length is not needed, then len can be NULL. */ 245230837Sdelphijlocal unsigned char *h2b(const char *hex, unsigned *len) 246230837Sdelphij{ 247230837Sdelphij unsigned char *in; 248230837Sdelphij unsigned next, val; 249230837Sdelphij 250230837Sdelphij in = malloc((strlen(hex) + 1) >> 1); 251230837Sdelphij if (in == NULL) 252230837Sdelphij return NULL; 253230837Sdelphij next = 0; 254230837Sdelphij val = 1; 255230837Sdelphij do { 256230837Sdelphij if (*hex >= '0' && *hex <= '9') 257230837Sdelphij val = (val << 4) + *hex - '0'; 258230837Sdelphij else if (*hex >= 'A' && *hex <= 'F') 259230837Sdelphij val = (val << 4) + *hex - 'A' + 10; 260230837Sdelphij else if (*hex >= 'a' && *hex <= 'f') 261230837Sdelphij val = (val << 4) + *hex - 'a' + 10; 262230837Sdelphij else if (val != 1 && val < 32) /* one digit followed by delimiter */ 263230837Sdelphij val += 240; /* make it look like two digits */ 264230837Sdelphij if (val > 255) { /* have two digits */ 265230837Sdelphij in[next++] = val & 0xff; /* save the decoded byte */ 266230837Sdelphij val = 1; /* start over */ 267230837Sdelphij } 268230837Sdelphij } while (*hex++); /* go through the loop with the terminating null */ 269230837Sdelphij if (len != NULL) 270230837Sdelphij *len = next; 271230837Sdelphij in = reallocf(in, next); 272230837Sdelphij return in; 273230837Sdelphij} 274230837Sdelphij 275230837Sdelphij/* generic inflate() run, where hex is the hexadecimal input data, what is the 276230837Sdelphij text to include in an error message, step is how much input data to feed 277230837Sdelphij inflate() on each call, or zero to feed it all, win is the window bits 278230837Sdelphij parameter to inflateInit2(), len is the size of the output buffer, and err 279230837Sdelphij is the error code expected from the first inflate() call (the second 280230837Sdelphij inflate() call is expected to return Z_STREAM_END). If win is 47, then 281230837Sdelphij header information is collected with inflateGetHeader(). If a zlib stream 282230837Sdelphij is looking for a dictionary, then an empty dictionary is provided. 283230837Sdelphij inflate() is run until all of the input data is consumed. */ 284230837Sdelphijlocal void inf(char *hex, char *what, unsigned step, int win, unsigned len, 285230837Sdelphij int err) 286230837Sdelphij{ 287230837Sdelphij int ret; 288230837Sdelphij unsigned have; 289230837Sdelphij unsigned char *in, *out; 290230837Sdelphij z_stream strm, copy; 291230837Sdelphij gz_header head; 292230837Sdelphij 293230837Sdelphij mem_setup(&strm); 294230837Sdelphij strm.avail_in = 0; 295230837Sdelphij strm.next_in = Z_NULL; 296230837Sdelphij ret = inflateInit2(&strm, win); 297230837Sdelphij if (ret != Z_OK) { 298230837Sdelphij mem_done(&strm, what); 299230837Sdelphij return; 300230837Sdelphij } 301230837Sdelphij out = malloc(len); assert(out != NULL); 302230837Sdelphij if (win == 47) { 303230837Sdelphij head.extra = out; 304230837Sdelphij head.extra_max = len; 305230837Sdelphij head.name = out; 306230837Sdelphij head.name_max = len; 307230837Sdelphij head.comment = out; 308230837Sdelphij head.comm_max = len; 309230837Sdelphij ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); 310230837Sdelphij } 311230837Sdelphij in = h2b(hex, &have); assert(in != NULL); 312230837Sdelphij if (step == 0 || step > have) 313230837Sdelphij step = have; 314230837Sdelphij strm.avail_in = step; 315230837Sdelphij have -= step; 316230837Sdelphij strm.next_in = in; 317230837Sdelphij do { 318230837Sdelphij strm.avail_out = len; 319230837Sdelphij strm.next_out = out; 320230837Sdelphij ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); 321230837Sdelphij if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) 322230837Sdelphij break; 323230837Sdelphij if (ret == Z_NEED_DICT) { 324230837Sdelphij ret = inflateSetDictionary(&strm, in, 1); 325230837Sdelphij assert(ret == Z_DATA_ERROR); 326230837Sdelphij mem_limit(&strm, 1); 327230837Sdelphij ret = inflateSetDictionary(&strm, out, 0); 328230837Sdelphij assert(ret == Z_MEM_ERROR); 329230837Sdelphij mem_limit(&strm, 0); 330230837Sdelphij ((struct inflate_state *)strm.state)->mode = DICT; 331230837Sdelphij ret = inflateSetDictionary(&strm, out, 0); 332230837Sdelphij assert(ret == Z_OK); 333230837Sdelphij ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); 334230837Sdelphij } 335230837Sdelphij ret = inflateCopy(©, &strm); assert(ret == Z_OK); 336230837Sdelphij ret = inflateEnd(©); assert(ret == Z_OK); 337230837Sdelphij err = 9; /* don't care next time around */ 338230837Sdelphij have += strm.avail_in; 339230837Sdelphij strm.avail_in = step > have ? have : step; 340230837Sdelphij have -= strm.avail_in; 341230837Sdelphij } while (strm.avail_in); 342230837Sdelphij free(in); 343230837Sdelphij free(out); 344230837Sdelphij ret = inflateReset2(&strm, -8); assert(ret == Z_OK); 345230837Sdelphij ret = inflateEnd(&strm); assert(ret == Z_OK); 346230837Sdelphij mem_done(&strm, what); 347230837Sdelphij} 348230837Sdelphij 349230837Sdelphij/* cover all of the lines in inflate.c up to inflate() */ 350230837Sdelphijlocal void cover_support(void) 351230837Sdelphij{ 352230837Sdelphij int ret; 353230837Sdelphij z_stream strm; 354230837Sdelphij 355230837Sdelphij mem_setup(&strm); 356230837Sdelphij strm.avail_in = 0; 357230837Sdelphij strm.next_in = Z_NULL; 358230837Sdelphij ret = inflateInit(&strm); assert(ret == Z_OK); 359230837Sdelphij mem_used(&strm, "inflate init"); 360230837Sdelphij ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); 361230837Sdelphij ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); 362230837Sdelphij ret = inflateSetDictionary(&strm, Z_NULL, 0); 363230837Sdelphij assert(ret == Z_STREAM_ERROR); 364230837Sdelphij ret = inflateEnd(&strm); assert(ret == Z_OK); 365230837Sdelphij mem_done(&strm, "prime"); 366230837Sdelphij 367230837Sdelphij inf("63 0", "force window allocation", 0, -15, 1, Z_OK); 368230837Sdelphij inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); 369230837Sdelphij inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); 370230837Sdelphij inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); 371230837Sdelphij inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); 372230837Sdelphij 373230837Sdelphij mem_setup(&strm); 374230837Sdelphij strm.avail_in = 0; 375230837Sdelphij strm.next_in = Z_NULL; 376230837Sdelphij ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); 377230837Sdelphij assert(ret == Z_VERSION_ERROR); 378230837Sdelphij mem_done(&strm, "wrong version"); 379230837Sdelphij 380230837Sdelphij strm.avail_in = 0; 381230837Sdelphij strm.next_in = Z_NULL; 382230837Sdelphij ret = inflateInit(&strm); assert(ret == Z_OK); 383230837Sdelphij ret = inflateEnd(&strm); assert(ret == Z_OK); 384230837Sdelphij fputs("inflate built-in memory routines\n", stderr); 385230837Sdelphij} 386230837Sdelphij 387230837Sdelphij/* cover all inflate() header and trailer cases and code after inflate() */ 388230837Sdelphijlocal void cover_wrap(void) 389230837Sdelphij{ 390230837Sdelphij int ret; 391230837Sdelphij z_stream strm, copy; 392230837Sdelphij unsigned char dict[257]; 393230837Sdelphij 394230837Sdelphij ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); 395230837Sdelphij ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 396230837Sdelphij ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); 397230837Sdelphij fputs("inflate bad parameters\n", stderr); 398230837Sdelphij 399230837Sdelphij inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); 400230837Sdelphij inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); 401230837Sdelphij inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); 402230837Sdelphij inf("8 99", "set window size from header", 0, 0, 0, Z_OK); 403230837Sdelphij inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); 404230837Sdelphij inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); 405230837Sdelphij inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, 406230837Sdelphij Z_DATA_ERROR); 407230837Sdelphij 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", 408230837Sdelphij 0, 47, 0, Z_STREAM_END); 409230837Sdelphij inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); 410230837Sdelphij inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); 411230837Sdelphij inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); 412230837Sdelphij 413230837Sdelphij mem_setup(&strm); 414230837Sdelphij strm.avail_in = 0; 415230837Sdelphij strm.next_in = Z_NULL; 416230837Sdelphij ret = inflateInit2(&strm, -8); 417230837Sdelphij strm.avail_in = 2; 418230837Sdelphij strm.next_in = (void *)"\x63"; 419230837Sdelphij strm.avail_out = 1; 420230837Sdelphij strm.next_out = (void *)&ret; 421230837Sdelphij mem_limit(&strm, 1); 422230837Sdelphij ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 423230837Sdelphij ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 424230837Sdelphij mem_limit(&strm, 0); 425230837Sdelphij memset(dict, 0, 257); 426230837Sdelphij ret = inflateSetDictionary(&strm, dict, 257); 427230837Sdelphij assert(ret == Z_OK); 428230837Sdelphij mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); 429230837Sdelphij ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); 430230837Sdelphij strm.avail_in = 2; 431230837Sdelphij strm.next_in = (void *)"\x80"; 432230837Sdelphij ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); 433230837Sdelphij ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); 434230837Sdelphij strm.avail_in = 4; 435230837Sdelphij strm.next_in = (void *)"\0\0\xff\xff"; 436230837Sdelphij ret = inflateSync(&strm); assert(ret == Z_OK); 437230837Sdelphij (void)inflateSyncPoint(&strm); 438230837Sdelphij ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); 439230837Sdelphij mem_limit(&strm, 0); 440230837Sdelphij ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); 441230837Sdelphij (void)inflateMark(&strm); 442230837Sdelphij ret = inflateEnd(&strm); assert(ret == Z_OK); 443230837Sdelphij mem_done(&strm, "miscellaneous, force memory errors"); 444230837Sdelphij} 445230837Sdelphij 446230837Sdelphij/* input and output functions for inflateBack() */ 447230837Sdelphijlocal unsigned pull(void *desc, unsigned char **buf) 448230837Sdelphij{ 449230837Sdelphij static unsigned int next = 0; 450230837Sdelphij static unsigned char dat[] = {0x63, 0, 2, 0}; 451230837Sdelphij struct inflate_state *state; 452230837Sdelphij 453230837Sdelphij if (desc == Z_NULL) { 454230837Sdelphij next = 0; 455230837Sdelphij return 0; /* no input (already provided at next_in) */ 456230837Sdelphij } 457230837Sdelphij state = (void *)((z_stream *)desc)->state; 458230837Sdelphij if (state != Z_NULL) 459230837Sdelphij state->mode = SYNC; /* force an otherwise impossible situation */ 460230837Sdelphij return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; 461230837Sdelphij} 462230837Sdelphij 463230837Sdelphijlocal int push(void *desc, unsigned char *buf, unsigned len) 464230837Sdelphij{ 465230837Sdelphij buf += len; 466230837Sdelphij return desc != Z_NULL; /* force error if desc not null */ 467230837Sdelphij} 468230837Sdelphij 469230837Sdelphij/* cover inflateBack() up to common deflate data cases and after those */ 470230837Sdelphijlocal void cover_back(void) 471230837Sdelphij{ 472230837Sdelphij int ret; 473230837Sdelphij z_stream strm; 474230837Sdelphij unsigned char win[32768]; 475230837Sdelphij 476230837Sdelphij ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); 477230837Sdelphij assert(ret == Z_VERSION_ERROR); 478230837Sdelphij ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); 479230837Sdelphij ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); 480230837Sdelphij assert(ret == Z_STREAM_ERROR); 481230837Sdelphij ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 482230837Sdelphij fputs("inflateBack bad parameters\n", stderr); 483230837Sdelphij 484230837Sdelphij mem_setup(&strm); 485230837Sdelphij ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 486230837Sdelphij strm.avail_in = 2; 487230837Sdelphij strm.next_in = (void *)"\x03"; 488230837Sdelphij ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 489230837Sdelphij assert(ret == Z_STREAM_END); 490230837Sdelphij /* force output error */ 491230837Sdelphij strm.avail_in = 3; 492230837Sdelphij strm.next_in = (void *)"\x63\x00"; 493230837Sdelphij ret = inflateBack(&strm, pull, Z_NULL, push, &strm); 494230837Sdelphij assert(ret == Z_BUF_ERROR); 495230837Sdelphij /* force mode error by mucking with state */ 496230837Sdelphij ret = inflateBack(&strm, pull, &strm, push, Z_NULL); 497230837Sdelphij assert(ret == Z_STREAM_ERROR); 498230837Sdelphij ret = inflateBackEnd(&strm); assert(ret == Z_OK); 499230837Sdelphij mem_done(&strm, "inflateBack bad state"); 500230837Sdelphij 501230837Sdelphij ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 502230837Sdelphij ret = inflateBackEnd(&strm); assert(ret == Z_OK); 503230837Sdelphij fputs("inflateBack built-in memory routines\n", stderr); 504230837Sdelphij} 505230837Sdelphij 506230837Sdelphij/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ 507230837Sdelphijlocal int try(char *hex, char *id, int err) 508230837Sdelphij{ 509230837Sdelphij int ret; 510230837Sdelphij unsigned len, size; 511230837Sdelphij unsigned char *in, *out, *win; 512230837Sdelphij char *prefix; 513230837Sdelphij z_stream strm; 514230837Sdelphij 515230837Sdelphij /* convert to hex */ 516230837Sdelphij in = h2b(hex, &len); 517230837Sdelphij assert(in != NULL); 518230837Sdelphij 519230837Sdelphij /* allocate work areas */ 520230837Sdelphij size = len << 3; 521230837Sdelphij out = malloc(size); 522230837Sdelphij assert(out != NULL); 523230837Sdelphij win = malloc(32768); 524230837Sdelphij assert(win != NULL); 525230837Sdelphij prefix = malloc(strlen(id) + 6); 526230837Sdelphij assert(prefix != NULL); 527230837Sdelphij 528230837Sdelphij /* first with inflate */ 529230837Sdelphij strcpy(prefix, id); 530230837Sdelphij strcat(prefix, "-late"); 531230837Sdelphij mem_setup(&strm); 532230837Sdelphij strm.avail_in = 0; 533230837Sdelphij strm.next_in = Z_NULL; 534230837Sdelphij ret = inflateInit2(&strm, err < 0 ? 47 : -15); 535230837Sdelphij assert(ret == Z_OK); 536230837Sdelphij strm.avail_in = len; 537230837Sdelphij strm.next_in = in; 538230837Sdelphij do { 539230837Sdelphij strm.avail_out = size; 540230837Sdelphij strm.next_out = out; 541230837Sdelphij ret = inflate(&strm, Z_TREES); 542230837Sdelphij assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); 543230837Sdelphij if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) 544230837Sdelphij break; 545230837Sdelphij } while (strm.avail_in || strm.avail_out == 0); 546230837Sdelphij if (err) { 547230837Sdelphij assert(ret == Z_DATA_ERROR); 548230837Sdelphij assert(strcmp(id, strm.msg) == 0); 549230837Sdelphij } 550230837Sdelphij inflateEnd(&strm); 551230837Sdelphij mem_done(&strm, prefix); 552230837Sdelphij 553230837Sdelphij /* then with inflateBack */ 554230837Sdelphij if (err >= 0) { 555230837Sdelphij strcpy(prefix, id); 556230837Sdelphij strcat(prefix, "-back"); 557230837Sdelphij mem_setup(&strm); 558230837Sdelphij ret = inflateBackInit(&strm, 15, win); 559230837Sdelphij assert(ret == Z_OK); 560230837Sdelphij strm.avail_in = len; 561230837Sdelphij strm.next_in = in; 562230837Sdelphij ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 563230837Sdelphij assert(ret != Z_STREAM_ERROR); 564230837Sdelphij if (err) { 565230837Sdelphij assert(ret == Z_DATA_ERROR); 566230837Sdelphij assert(strcmp(id, strm.msg) == 0); 567230837Sdelphij } 568230837Sdelphij inflateBackEnd(&strm); 569230837Sdelphij mem_done(&strm, prefix); 570230837Sdelphij } 571230837Sdelphij 572230837Sdelphij /* clean up */ 573230837Sdelphij free(prefix); 574230837Sdelphij free(win); 575230837Sdelphij free(out); 576230837Sdelphij free(in); 577230837Sdelphij return ret; 578230837Sdelphij} 579230837Sdelphij 580230837Sdelphij/* cover deflate data cases in both inflate() and inflateBack() */ 581230837Sdelphijlocal void cover_inflate(void) 582230837Sdelphij{ 583230837Sdelphij try("0 0 0 0 0", "invalid stored block lengths", 1); 584230837Sdelphij try("3 0", "fixed", 0); 585230837Sdelphij try("6", "invalid block type", 1); 586230837Sdelphij try("1 1 0 fe ff 0", "stored", 0); 587230837Sdelphij try("fc 0 0", "too many length or distance symbols", 1); 588230837Sdelphij try("4 0 fe ff", "invalid code lengths set", 1); 589230837Sdelphij try("4 0 24 49 0", "invalid bit length repeat", 1); 590230837Sdelphij try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); 591230837Sdelphij try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); 592230837Sdelphij try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", 593230837Sdelphij "invalid literal/lengths set", 1); 594230837Sdelphij try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); 595230837Sdelphij try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); 596230837Sdelphij try("2 7e ff ff", "invalid distance code", 1); 597230837Sdelphij try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); 598230837Sdelphij 599230837Sdelphij /* also trailer mismatch just in inflate() */ 600230837Sdelphij try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); 601230837Sdelphij try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", 602230837Sdelphij "incorrect length check", -1); 603230837Sdelphij try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); 604230837Sdelphij try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", 605230837Sdelphij "long code", 0); 606230837Sdelphij try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); 607230837Sdelphij 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", 608230837Sdelphij "long distance and extra", 0); 609230837Sdelphij 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 " 610230837Sdelphij "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); 611230837Sdelphij inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, 612230837Sdelphij Z_STREAM_END); 613230837Sdelphij inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); 614230837Sdelphij} 615230837Sdelphij 616230837Sdelphij/* cover remaining lines in inftrees.c */ 617230837Sdelphijlocal void cover_trees(void) 618230837Sdelphij{ 619230837Sdelphij int ret; 620230837Sdelphij unsigned bits; 621230837Sdelphij unsigned short lens[16], work[16]; 622230837Sdelphij code *next, table[ENOUGH_DISTS]; 623230837Sdelphij 624230837Sdelphij /* we need to call inflate_table() directly in order to manifest not- 625230837Sdelphij enough errors, since zlib insures that enough is always enough */ 626230837Sdelphij for (bits = 0; bits < 15; bits++) 627230837Sdelphij lens[bits] = (unsigned short)(bits + 1); 628230837Sdelphij lens[15] = 15; 629230837Sdelphij next = table; 630230837Sdelphij bits = 15; 631230837Sdelphij ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 632230837Sdelphij assert(ret == 1); 633230837Sdelphij next = table; 634230837Sdelphij bits = 1; 635230837Sdelphij ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 636230837Sdelphij assert(ret == 1); 637230837Sdelphij fputs("inflate_table not enough errors\n", stderr); 638230837Sdelphij} 639230837Sdelphij 640230837Sdelphij/* cover remaining inffast.c decoding and window copying */ 641230837Sdelphijlocal void cover_fast(void) 642230837Sdelphij{ 643230837Sdelphij inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" 644230837Sdelphij " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); 645230837Sdelphij inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" 646230837Sdelphij " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, 647230837Sdelphij Z_DATA_ERROR); 648230837Sdelphij inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, 649230837Sdelphij Z_DATA_ERROR); 650230837Sdelphij inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, 651230837Sdelphij Z_DATA_ERROR); 652230837Sdelphij 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", 653230837Sdelphij "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); 654230837Sdelphij inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); 655230837Sdelphij inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", 656230837Sdelphij "contiguous and wrap around window", 6, -8, 259, Z_OK); 657230837Sdelphij inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, 658230837Sdelphij Z_STREAM_END); 659230837Sdelphij} 660230837Sdelphij 661230837Sdelphijint main(void) 662230837Sdelphij{ 663230837Sdelphij fprintf(stderr, "%s\n", zlibVersion()); 664230837Sdelphij cover_support(); 665230837Sdelphij cover_wrap(); 666230837Sdelphij cover_back(); 667230837Sdelphij cover_inflate(); 668230837Sdelphij cover_trees(); 669230837Sdelphij cover_fast(); 670230837Sdelphij return 0; 671230837Sdelphij} 672