~ubuntu-branches/ubuntu/trusty/zlib/trusty

« back to all changes in this revision

Viewing changes to test/infcover.c

  • Committer: Package Import Robot
  • Author(s): Mark Brown
  • Date: 2012-06-22 16:55:56 UTC
  • mfrom: (1.1.23 sid)
  • Revision ID: package-import@ubuntu.com-20120622165556-9xuc7gnq4w25b3i0
Yet more s390x cleanup.  Thanks to the s390x porters for thei
prompt an efficient buildd monitoring (closes: #678511).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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 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)
 
246
{
 
247
    unsigned char *in;
 
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
    in = reallocf(in, next);
 
272
    return in;
 
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, ZLIB_VERSION - 1, (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
    buf += len;
 
466
    return desc != Z_NULL;      /* force error if desc not null */
 
467
}
 
468
 
 
469
/* cover inflateBack() up to common deflate data cases and after those */
 
470
local void cover_back(void)
 
471
{
 
472
    int ret;
 
473
    z_stream strm;
 
474
    unsigned char win[32768];
 
475
 
 
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);
 
483
 
 
484
    mem_setup(&strm);
 
485
    ret = inflateBackInit(&strm, 15, win);      assert(ret == Z_OK);
 
486
    strm.avail_in = 2;
 
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 */
 
491
    strm.avail_in = 3;
 
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");
 
500
 
 
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);
 
504
}
 
505
 
 
506
/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
 
507
local int try(char *hex, char *id, int err)
 
508
{
 
509
    int ret;
 
510
    unsigned len, size;
 
511
    unsigned char *in, *out, *win;
 
512
    char *prefix;
 
513
    z_stream strm;
 
514
 
 
515
    /* convert to hex */
 
516
    in = h2b(hex, &len);
 
517
    assert(in != NULL);
 
518
 
 
519
    /* allocate work areas */
 
520
    size = len << 3;
 
521
    out = malloc(size);
 
522
    assert(out != NULL);
 
523
    win = malloc(32768);
 
524
    assert(win != NULL);
 
525
    prefix = malloc(strlen(id) + 6);
 
526
    assert(prefix != NULL);
 
527
 
 
528
    /* first with inflate */
 
529
    strcpy(prefix, id);
 
530
    strcat(prefix, "-late");
 
531
    mem_setup(&strm);
 
532
    strm.avail_in = 0;
 
533
    strm.next_in = Z_NULL;
 
534
    ret = inflateInit2(&strm, err < 0 ? 47 : -15);
 
535
    assert(ret == Z_OK);
 
536
    strm.avail_in = len;
 
537
    strm.next_in = in;
 
538
    do {
 
539
        strm.avail_out = size;
 
540
        strm.next_out = out;
 
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)
 
544
            break;
 
545
    } while (strm.avail_in || strm.avail_out == 0);
 
546
    if (err) {
 
547
        assert(ret == Z_DATA_ERROR);
 
548
        assert(strcmp(id, strm.msg) == 0);
 
549
    }
 
550
    inflateEnd(&strm);
 
551
    mem_done(&strm, prefix);
 
552
 
 
553
    /* then with inflateBack */
 
554
    if (err >= 0) {
 
555
        strcpy(prefix, id);
 
556
        strcat(prefix, "-back");
 
557
        mem_setup(&strm);
 
558
        ret = inflateBackInit(&strm, 15, win);
 
559
        assert(ret == Z_OK);
 
560
        strm.avail_in = len;
 
561
        strm.next_in = in;
 
562
        ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
 
563
        assert(ret != Z_STREAM_ERROR);
 
564
        if (err) {
 
565
            assert(ret == Z_DATA_ERROR);
 
566
            assert(strcmp(id, strm.msg) == 0);
 
567
        }
 
568
        inflateBackEnd(&strm);
 
569
        mem_done(&strm, prefix);
 
570
    }
 
571
 
 
572
    /* clean up */
 
573
    free(prefix);
 
574
    free(win);
 
575
    free(out);
 
576
    free(in);
 
577
    return ret;
 
578
}
 
579
 
 
580
/* cover deflate data cases in both inflate() and inflateBack() */
 
581
local void cover_inflate(void)
 
582
{
 
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);
 
598
 
 
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",
 
605
        "long code", 0);
 
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,
 
612
        Z_STREAM_END);
 
613
    inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK);
 
614
}
 
615
 
 
616
/* cover remaining lines in inftrees.c */
 
617
local void cover_trees(void)
 
618
{
 
619
    int ret;
 
620
    unsigned bits;
 
621
    unsigned short lens[16], work[16];
 
622
    code *next, table[ENOUGH_DISTS];
 
623
 
 
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);
 
628
    lens[15] = 15;
 
629
    next = table;
 
630
    bits = 15;
 
631
    ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
 
632
                                                assert(ret == 1);
 
633
    next = table;
 
634
    bits = 1;
 
635
    ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
 
636
                                                assert(ret == 1);
 
637
    fputs("inflate_table not enough errors\n", stderr);
 
638
}
 
639
 
 
640
/* cover remaining inffast.c decoding and window copying */
 
641
local void cover_fast(void)
 
642
{
 
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,
 
647
        Z_DATA_ERROR);
 
648
    inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258,
 
649
        Z_DATA_ERROR);
 
650
    inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258,
 
651
        Z_DATA_ERROR);
 
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,
 
658
        Z_STREAM_END);
 
659
}
 
660
 
 
661
int main(void)
 
662
{
 
663
    fprintf(stderr, "%s\n", zlibVersion());
 
664
    cover_support();
 
665
    cover_wrap();
 
666
    cover_back();
 
667
    cover_inflate();
 
668
    cover_trees();
 
669
    cover_fast();
 
670
    return 0;
 
671
}