Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/zlib/test/infcover.c
48261 views
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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. */
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. */
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(&copy, &strm); assert(ret == Z_OK);
336
ret = inflateEnd(&copy); 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() */
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() */
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(&copy, &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() */
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
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 */
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 */
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() */
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 */
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 */
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
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
674