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