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