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