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