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