1
/* infcover.c -- test zlib's inflate routines with full code coverage
2
* Copyright (C) 2011 Mark Adler
3
* For conditions of distribution and use, see copyright notice in zlib.h
6
/* to use, do: ./configure --cover && make cover */
14
/* get definition of internal structure so we can mess with it (see pull()),
15
and so we can call inflate_trees() (see cover5()) */
22
/* -- memory tracking routines -- */
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.
30
They are used as follows:
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
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
55
/* these items are strung together in a linked list, one for each allocation */
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 */
62
/* this structure is at the root of the linked list, and tracks statistics */
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 */
70
/* memory allocation routine to pass to zlib */
71
local void *mem_alloc(void *mem, unsigned count, unsigned size)
74
struct mem_item *item;
75
struct mem_zone *zone = mem;
76
size_t len = count * (size_t)size;
78
/* induced allocation failure */
79
if (zone == NULL || (zone->limit && zone->total + len > zone->limit))
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 */
87
memset(ptr, 0xa5, len);
89
/* create a new item for the list */
90
item = malloc(sizeof(struct mem_item));
98
/* insert item at the beginning of the list */
99
item->next = zone->first;
102
/* update the statistics */
103
zone->total += item->size;
104
if (zone->total > zone->highwater)
105
zone->highwater = zone->total;
107
/* return the allocated memory */
111
/* memory free routine to pass to zlib */
112
local void mem_free(void *mem, void *ptr)
114
struct mem_item *item, *next;
115
struct mem_zone *zone = mem;
117
/* if no zone, just do a free */
123
/* point next to the item that matches ptr, or NULL if not found -- remove
124
the item from the linked list if found */
127
if (next->ptr == ptr)
128
zone->first = next->next; /* first one is it, remove from list */
130
do { /* search the linked list */
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 */
142
/* if found, update the statistics and free the item */
144
zone->total -= next->size;
148
/* if not found, update the rogue count */
152
/* in any case, do the requested free with the standard library function */
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 */
158
local void mem_setup(z_stream *strm)
160
struct mem_zone *zone;
162
zone = malloc(sizeof(struct mem_zone));
163
assert(zone != NULL);
171
strm->zalloc = mem_alloc;
172
strm->zfree = mem_free;
175
/* set a limit on the total memory allocation, or 0 to remove the limit */
176
local void mem_limit(z_stream *strm, size_t limit)
178
struct mem_zone *zone = strm->opaque;
183
/* show the current total requested allocations in bytes */
184
local void mem_used(z_stream *strm, char *prefix)
186
struct mem_zone *zone = strm->opaque;
188
fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total);
191
/* show the high water allocation in bytes */
192
local void mem_high(z_stream *strm, char *prefix)
194
struct mem_zone *zone = strm->opaque;
196
fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater);
199
/* release the memory allocation zone -- if there are any surprises, notify */
200
local void mem_done(z_stream *strm, char *prefix)
203
struct mem_item *item, *next;
204
struct mem_zone *zone = strm->opaque;
206
/* show high water mark */
207
mem_high(strm, prefix);
209
/* free leftover allocations and item structures, if any */
211
while (item != NULL) {
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);
224
fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo);
226
fprintf(stderr, "** %s: %d frees not recognized\n",
227
prefix, zone->rogue);
229
/* free the zone and delete from the stream */
231
strm->opaque = Z_NULL;
232
strm->zalloc = Z_NULL;
233
strm->zfree = Z_NULL;
236
/* -- inflate test routines -- */
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 delimited by any non-hex character, where
241
the delimiters are ignored except when a single hex digit is followed by a
242
delimiter in which case that single digit writes a byte. The returned
243
data is allocated and must eventually be freed. NULL is returned if out of
244
memory. If the length is not needed, then len can be NULL. */
245
local unsigned char *h2b(const char *hex, unsigned *len)
250
in = malloc((strlen(hex) + 1) >> 1);
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 */
268
} while (*hex++); /* go through the loop with the terminating null */
271
in = reallocf(in, next);
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. */
284
local void inf(char *hex, char *what, unsigned step, int win, unsigned len,
289
unsigned char *in, *out;
295
strm.next_in = Z_NULL;
296
ret = inflateInit2(&strm, win);
298
mem_done(&strm, what);
301
out = malloc(len); assert(out != NULL);
304
head.extra_max = len;
309
ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK);
311
in = h2b(hex, &have); assert(in != NULL);
312
if (step == 0 || step > have)
314
strm.avail_in = step;
318
strm.avail_out = len;
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)
323
if (ret == Z_NEED_DICT) {
324
ret = inflateSetDictionary(&strm, in, 1);
325
assert(ret == Z_DATA_ERROR);
327
ret = inflateSetDictionary(&strm, out, 0);
328
assert(ret == Z_MEM_ERROR);
330
((struct inflate_state *)strm.state)->mode = DICT;
331
ret = inflateSetDictionary(&strm, out, 0);
333
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR);
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);
344
ret = inflateReset2(&strm, -8); assert(ret == Z_OK);
345
ret = inflateEnd(&strm); assert(ret == Z_OK);
346
mem_done(&strm, what);
349
/* cover all of the lines in inflate.c up to inflate() */
350
local void cover_support(void)
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");
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);
375
strm.next_in = Z_NULL;
376
ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream));
377
assert(ret == Z_VERSION_ERROR);
378
mem_done(&strm, "wrong version");
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);
387
/* cover all inflate() header and trailer cases and code after inflate() */
388
local void cover_wrap(void)
392
unsigned char dict[257];
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);
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,
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);
415
strm.next_in = Z_NULL;
416
ret = inflateInit2(&strm, -8);
418
strm.next_in = (void *)"\x63";
420
strm.next_out = (void *)&ret;
422
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
423
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
425
memset(dict, 0, 257);
426
ret = inflateSetDictionary(&strm, dict, 257);
428
mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256);
429
ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK);
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);
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);
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");
446
/* input and output functions for inflateBack() */
447
local unsigned pull(void *desc, unsigned char **buf)
449
static unsigned int next = 0;
450
static unsigned char dat[] = {0x63, 0, 2, 0};
451
struct inflate_state *state;
453
if (desc == Z_NULL) {
455
return 0; /* no input (already provided at next_in) */
457
state = (void *)((z_stream *)desc)->state;
459
state->mode = SYNC; /* force an otherwise impossible situation */
460
return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0;
463
local int push(void *desc, unsigned char *buf, unsigned len)
466
return desc != Z_NULL; /* force error if desc not null */
469
/* cover inflateBack() up to common deflate data cases and after those */
470
local void cover_back(void)
474
unsigned char win[32768];
476
ret = inflateBackInit_(Z_NULL, 0, win, 0, 0);
477
assert(ret == Z_VERSION_ERROR);
478
ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR);
479
ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL);
480
assert(ret == Z_STREAM_ERROR);
481
ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
482
fputs("inflateBack bad parameters\n", stderr);
485
ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
487
strm.next_in = (void *)"\x03";
488
ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
489
assert(ret == Z_STREAM_END);
490
/* force output error */
492
strm.next_in = (void *)"\x63\x00";
493
ret = inflateBack(&strm, pull, Z_NULL, push, &strm);
494
assert(ret == Z_BUF_ERROR);
495
/* force mode error by mucking with state */
496
ret = inflateBack(&strm, pull, &strm, push, Z_NULL);
497
assert(ret == Z_STREAM_ERROR);
498
ret = inflateBackEnd(&strm); assert(ret == Z_OK);
499
mem_done(&strm, "inflateBack bad state");
501
ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
502
ret = inflateBackEnd(&strm); assert(ret == Z_OK);
503
fputs("inflateBack built-in memory routines\n", stderr);
506
/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
507
local int try(char *hex, char *id, int err)
511
unsigned char *in, *out, *win;
519
/* allocate work areas */
525
prefix = malloc(strlen(id) + 6);
526
assert(prefix != NULL);
528
/* first with inflate */
530
strcat(prefix, "-late");
533
strm.next_in = Z_NULL;
534
ret = inflateInit2(&strm, err < 0 ? 47 : -15);
539
strm.avail_out = size;
541
ret = inflate(&strm, Z_TREES);
542
assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR);
543
if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT)
545
} while (strm.avail_in || strm.avail_out == 0);
547
assert(ret == Z_DATA_ERROR);
548
assert(strcmp(id, strm.msg) == 0);
551
mem_done(&strm, prefix);
553
/* then with inflateBack */
556
strcat(prefix, "-back");
558
ret = inflateBackInit(&strm, 15, win);
562
ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
563
assert(ret != Z_STREAM_ERROR);
565
assert(ret == Z_DATA_ERROR);
566
assert(strcmp(id, strm.msg) == 0);
568
inflateBackEnd(&strm);
569
mem_done(&strm, prefix);
580
/* cover deflate data cases in both inflate() and inflateBack() */
581
local void cover_inflate(void)
583
try("0 0 0 0 0", "invalid stored block lengths", 1);
584
try("3 0", "fixed", 0);
585
try("6", "invalid block type", 1);
586
try("1 1 0 fe ff 0", "stored", 0);
587
try("fc 0 0", "too many length or distance symbols", 1);
588
try("4 0 fe ff", "invalid code lengths set", 1);
589
try("4 0 24 49 0", "invalid bit length repeat", 1);
590
try("4 0 24 e9 ff ff", "invalid bit length repeat", 1);
591
try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1);
592
try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0",
593
"invalid literal/lengths set", 1);
594
try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1);
595
try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1);
596
try("2 7e ff ff", "invalid distance code", 1);
597
try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1);
599
/* also trailer mismatch just in inflate() */
600
try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1);
601
try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1",
602
"incorrect length check", -1);
603
try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0);
604
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
try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0);
607
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",
608
"long distance and extra", 0);
609
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 "
610
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0);
611
inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258,
613
inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK);
616
/* cover remaining lines in inftrees.c */
617
local void cover_trees(void)
621
unsigned short lens[16], work[16];
622
code *next, table[ENOUGH_DISTS];
624
/* we need to call inflate_table() directly in order to manifest not-
625
enough errors, since zlib insures that enough is always enough */
626
for (bits = 0; bits < 15; bits++)
627
lens[bits] = (unsigned short)(bits + 1);
631
ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
635
ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
637
fputs("inflate_table not enough errors\n", stderr);
640
/* cover remaining inffast.c decoding and window copying */
641
local void cover_fast(void)
643
inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68"
644
" ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR);
645
inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49"
646
" 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258,
648
inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258,
650
inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258,
652
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",
653
"fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR);
654
inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK);
655
inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0",
656
"contiguous and wrap around window", 6, -8, 259, Z_OK);
657
inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259,
663
fprintf(stderr, "%s\n", zlibVersion());