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