1275793eaSopenharmony_ci/* infcover.c -- test zlib's inflate routines with full code coverage 2275793eaSopenharmony_ci * Copyright (C) 2011, 2016 Mark Adler 3275793eaSopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 4275793eaSopenharmony_ci */ 5275793eaSopenharmony_ci 6275793eaSopenharmony_ci/* to use, do: ./configure --cover && make cover */ 7275793eaSopenharmony_ci 8275793eaSopenharmony_ci#include <stdio.h> 9275793eaSopenharmony_ci#include <stdlib.h> 10275793eaSopenharmony_ci#include <string.h> 11275793eaSopenharmony_ci#include <assert.h> 12275793eaSopenharmony_ci#include "zlib.h" 13275793eaSopenharmony_ci 14275793eaSopenharmony_ci/* get definition of internal structure so we can mess with it (see pull()), 15275793eaSopenharmony_ci and so we can call inflate_trees() (see cover5()) */ 16275793eaSopenharmony_ci#define ZLIB_INTERNAL 17275793eaSopenharmony_ci#include "inftrees.h" 18275793eaSopenharmony_ci#include "inflate.h" 19275793eaSopenharmony_ci 20275793eaSopenharmony_ci#define local static 21275793eaSopenharmony_ci 22275793eaSopenharmony_ci/* -- memory tracking routines -- */ 23275793eaSopenharmony_ci 24275793eaSopenharmony_ci/* 25275793eaSopenharmony_ci These memory tracking routines are provided to zlib and track all of zlib's 26275793eaSopenharmony_ci allocations and deallocations, check for LIFO operations, keep a current 27275793eaSopenharmony_ci and high water mark of total bytes requested, optionally set a limit on the 28275793eaSopenharmony_ci total memory that can be allocated, and when done check for memory leaks. 29275793eaSopenharmony_ci 30275793eaSopenharmony_ci They are used as follows: 31275793eaSopenharmony_ci 32275793eaSopenharmony_ci z_stream strm; 33275793eaSopenharmony_ci mem_setup(&strm) initializes the memory tracking and sets the 34275793eaSopenharmony_ci zalloc, zfree, and opaque members of strm to use 35275793eaSopenharmony_ci memory tracking for all zlib operations on strm 36275793eaSopenharmony_ci mem_limit(&strm, limit) sets a limit on the total bytes requested -- a 37275793eaSopenharmony_ci request that exceeds this limit will result in an 38275793eaSopenharmony_ci allocation failure (returns NULL) -- setting the 39275793eaSopenharmony_ci limit to zero means no limit, which is the default 40275793eaSopenharmony_ci after mem_setup() 41275793eaSopenharmony_ci mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used 42275793eaSopenharmony_ci mem_high(&strm, "msg") prints to stderr "msg" and the high water mark 43275793eaSopenharmony_ci mem_done(&strm, "msg") ends memory tracking, releases all allocations 44275793eaSopenharmony_ci for the tracking as well as leaked zlib blocks, if 45275793eaSopenharmony_ci any. If there was anything unusual, such as leaked 46275793eaSopenharmony_ci blocks, non-FIFO frees, or frees of addresses not 47275793eaSopenharmony_ci allocated, then "msg" and information about the 48275793eaSopenharmony_ci problem is printed to stderr. If everything is 49275793eaSopenharmony_ci normal, nothing is printed. mem_done resets the 50275793eaSopenharmony_ci strm members to Z_NULL to use the default memory 51275793eaSopenharmony_ci allocation routines on the next zlib initialization 52275793eaSopenharmony_ci using strm. 53275793eaSopenharmony_ci */ 54275793eaSopenharmony_ci 55275793eaSopenharmony_ci/* these items are strung together in a linked list, one for each allocation */ 56275793eaSopenharmony_cistruct mem_item { 57275793eaSopenharmony_ci void *ptr; /* pointer to allocated memory */ 58275793eaSopenharmony_ci size_t size; /* requested size of allocation */ 59275793eaSopenharmony_ci struct mem_item *next; /* pointer to next item in list, or NULL */ 60275793eaSopenharmony_ci}; 61275793eaSopenharmony_ci 62275793eaSopenharmony_ci/* this structure is at the root of the linked list, and tracks statistics */ 63275793eaSopenharmony_cistruct mem_zone { 64275793eaSopenharmony_ci struct mem_item *first; /* pointer to first item in list, or NULL */ 65275793eaSopenharmony_ci size_t total, highwater; /* total allocations, and largest total */ 66275793eaSopenharmony_ci size_t limit; /* memory allocation limit, or 0 if no limit */ 67275793eaSopenharmony_ci int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ 68275793eaSopenharmony_ci}; 69275793eaSopenharmony_ci 70275793eaSopenharmony_ci/* memory allocation routine to pass to zlib */ 71275793eaSopenharmony_cilocal void *mem_alloc(void *mem, unsigned count, unsigned size) 72275793eaSopenharmony_ci{ 73275793eaSopenharmony_ci void *ptr; 74275793eaSopenharmony_ci struct mem_item *item; 75275793eaSopenharmony_ci struct mem_zone *zone = mem; 76275793eaSopenharmony_ci size_t len = count * (size_t)size; 77275793eaSopenharmony_ci 78275793eaSopenharmony_ci /* induced allocation failure */ 79275793eaSopenharmony_ci if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) 80275793eaSopenharmony_ci return NULL; 81275793eaSopenharmony_ci 82275793eaSopenharmony_ci /* perform allocation using the standard library, fill memory with a 83275793eaSopenharmony_ci non-zero value to make sure that the code isn't depending on zeros */ 84275793eaSopenharmony_ci ptr = malloc(len); 85275793eaSopenharmony_ci if (ptr == NULL) 86275793eaSopenharmony_ci return NULL; 87275793eaSopenharmony_ci memset(ptr, 0xa5, len); 88275793eaSopenharmony_ci 89275793eaSopenharmony_ci /* create a new item for the list */ 90275793eaSopenharmony_ci item = malloc(sizeof(struct mem_item)); 91275793eaSopenharmony_ci if (item == NULL) { 92275793eaSopenharmony_ci free(ptr); 93275793eaSopenharmony_ci return NULL; 94275793eaSopenharmony_ci } 95275793eaSopenharmony_ci item->ptr = ptr; 96275793eaSopenharmony_ci item->size = len; 97275793eaSopenharmony_ci 98275793eaSopenharmony_ci /* insert item at the beginning of the list */ 99275793eaSopenharmony_ci item->next = zone->first; 100275793eaSopenharmony_ci zone->first = item; 101275793eaSopenharmony_ci 102275793eaSopenharmony_ci /* update the statistics */ 103275793eaSopenharmony_ci zone->total += item->size; 104275793eaSopenharmony_ci if (zone->total > zone->highwater) 105275793eaSopenharmony_ci zone->highwater = zone->total; 106275793eaSopenharmony_ci 107275793eaSopenharmony_ci /* return the allocated memory */ 108275793eaSopenharmony_ci return ptr; 109275793eaSopenharmony_ci} 110275793eaSopenharmony_ci 111275793eaSopenharmony_ci/* memory free routine to pass to zlib */ 112275793eaSopenharmony_cilocal void mem_free(void *mem, void *ptr) 113275793eaSopenharmony_ci{ 114275793eaSopenharmony_ci struct mem_item *item, *next; 115275793eaSopenharmony_ci struct mem_zone *zone = mem; 116275793eaSopenharmony_ci 117275793eaSopenharmony_ci /* if no zone, just do a free */ 118275793eaSopenharmony_ci if (zone == NULL) { 119275793eaSopenharmony_ci free(ptr); 120275793eaSopenharmony_ci return; 121275793eaSopenharmony_ci } 122275793eaSopenharmony_ci 123275793eaSopenharmony_ci /* point next to the item that matches ptr, or NULL if not found -- remove 124275793eaSopenharmony_ci the item from the linked list if found */ 125275793eaSopenharmony_ci next = zone->first; 126275793eaSopenharmony_ci if (next) { 127275793eaSopenharmony_ci if (next->ptr == ptr) 128275793eaSopenharmony_ci zone->first = next->next; /* first one is it, remove from list */ 129275793eaSopenharmony_ci else { 130275793eaSopenharmony_ci do { /* search the linked list */ 131275793eaSopenharmony_ci item = next; 132275793eaSopenharmony_ci next = item->next; 133275793eaSopenharmony_ci } while (next != NULL && next->ptr != ptr); 134275793eaSopenharmony_ci if (next) { /* if found, remove from linked list */ 135275793eaSopenharmony_ci item->next = next->next; 136275793eaSopenharmony_ci zone->notlifo++; /* not a LIFO free */ 137275793eaSopenharmony_ci } 138275793eaSopenharmony_ci 139275793eaSopenharmony_ci } 140275793eaSopenharmony_ci } 141275793eaSopenharmony_ci 142275793eaSopenharmony_ci /* if found, update the statistics and free the item */ 143275793eaSopenharmony_ci if (next) { 144275793eaSopenharmony_ci zone->total -= next->size; 145275793eaSopenharmony_ci free(next); 146275793eaSopenharmony_ci } 147275793eaSopenharmony_ci 148275793eaSopenharmony_ci /* if not found, update the rogue count */ 149275793eaSopenharmony_ci else 150275793eaSopenharmony_ci zone->rogue++; 151275793eaSopenharmony_ci 152275793eaSopenharmony_ci /* in any case, do the requested free with the standard library function */ 153275793eaSopenharmony_ci free(ptr); 154275793eaSopenharmony_ci} 155275793eaSopenharmony_ci 156275793eaSopenharmony_ci/* set up a controlled memory allocation space for monitoring, set the stream 157275793eaSopenharmony_ci parameters to the controlled routines, with opaque pointing to the space */ 158275793eaSopenharmony_cilocal void mem_setup(z_stream *strm) 159275793eaSopenharmony_ci{ 160275793eaSopenharmony_ci struct mem_zone *zone; 161275793eaSopenharmony_ci 162275793eaSopenharmony_ci zone = malloc(sizeof(struct mem_zone)); 163275793eaSopenharmony_ci assert(zone != NULL); 164275793eaSopenharmony_ci zone->first = NULL; 165275793eaSopenharmony_ci zone->total = 0; 166275793eaSopenharmony_ci zone->highwater = 0; 167275793eaSopenharmony_ci zone->limit = 0; 168275793eaSopenharmony_ci zone->notlifo = 0; 169275793eaSopenharmony_ci zone->rogue = 0; 170275793eaSopenharmony_ci strm->opaque = zone; 171275793eaSopenharmony_ci strm->zalloc = mem_alloc; 172275793eaSopenharmony_ci strm->zfree = mem_free; 173275793eaSopenharmony_ci} 174275793eaSopenharmony_ci 175275793eaSopenharmony_ci/* set a limit on the total memory allocation, or 0 to remove the limit */ 176275793eaSopenharmony_cilocal void mem_limit(z_stream *strm, size_t limit) 177275793eaSopenharmony_ci{ 178275793eaSopenharmony_ci struct mem_zone *zone = strm->opaque; 179275793eaSopenharmony_ci 180275793eaSopenharmony_ci zone->limit = limit; 181275793eaSopenharmony_ci} 182275793eaSopenharmony_ci 183275793eaSopenharmony_ci/* show the current total requested allocations in bytes */ 184275793eaSopenharmony_cilocal void mem_used(z_stream *strm, char *prefix) 185275793eaSopenharmony_ci{ 186275793eaSopenharmony_ci struct mem_zone *zone = strm->opaque; 187275793eaSopenharmony_ci 188275793eaSopenharmony_ci fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); 189275793eaSopenharmony_ci} 190275793eaSopenharmony_ci 191275793eaSopenharmony_ci/* show the high water allocation in bytes */ 192275793eaSopenharmony_cilocal void mem_high(z_stream *strm, char *prefix) 193275793eaSopenharmony_ci{ 194275793eaSopenharmony_ci struct mem_zone *zone = strm->opaque; 195275793eaSopenharmony_ci 196275793eaSopenharmony_ci fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); 197275793eaSopenharmony_ci} 198275793eaSopenharmony_ci 199275793eaSopenharmony_ci/* release the memory allocation zone -- if there are any surprises, notify */ 200275793eaSopenharmony_cilocal void mem_done(z_stream *strm, char *prefix) 201275793eaSopenharmony_ci{ 202275793eaSopenharmony_ci int count = 0; 203275793eaSopenharmony_ci struct mem_item *item, *next; 204275793eaSopenharmony_ci struct mem_zone *zone = strm->opaque; 205275793eaSopenharmony_ci 206275793eaSopenharmony_ci /* show high water mark */ 207275793eaSopenharmony_ci mem_high(strm, prefix); 208275793eaSopenharmony_ci 209275793eaSopenharmony_ci /* free leftover allocations and item structures, if any */ 210275793eaSopenharmony_ci item = zone->first; 211275793eaSopenharmony_ci while (item != NULL) { 212275793eaSopenharmony_ci free(item->ptr); 213275793eaSopenharmony_ci next = item->next; 214275793eaSopenharmony_ci free(item); 215275793eaSopenharmony_ci item = next; 216275793eaSopenharmony_ci count++; 217275793eaSopenharmony_ci } 218275793eaSopenharmony_ci 219275793eaSopenharmony_ci /* issue alerts about anything unexpected */ 220275793eaSopenharmony_ci if (count || zone->total) 221275793eaSopenharmony_ci fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", 222275793eaSopenharmony_ci prefix, zone->total, count); 223275793eaSopenharmony_ci if (zone->notlifo) 224275793eaSopenharmony_ci fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); 225275793eaSopenharmony_ci if (zone->rogue) 226275793eaSopenharmony_ci fprintf(stderr, "** %s: %d frees not recognized\n", 227275793eaSopenharmony_ci prefix, zone->rogue); 228275793eaSopenharmony_ci 229275793eaSopenharmony_ci /* free the zone and delete from the stream */ 230275793eaSopenharmony_ci free(zone); 231275793eaSopenharmony_ci strm->opaque = Z_NULL; 232275793eaSopenharmony_ci strm->zalloc = Z_NULL; 233275793eaSopenharmony_ci strm->zfree = Z_NULL; 234275793eaSopenharmony_ci} 235275793eaSopenharmony_ci 236275793eaSopenharmony_ci/* -- inflate test routines -- */ 237275793eaSopenharmony_ci 238275793eaSopenharmony_ci/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This 239275793eaSopenharmony_ci decodes liberally, in that hex digits can be adjacent, in which case two in 240275793eaSopenharmony_ci a row writes a byte. Or they can be delimited by any non-hex character, 241275793eaSopenharmony_ci where the delimiters are ignored except when a single hex digit is followed 242275793eaSopenharmony_ci by a delimiter, where that single digit writes a byte. The returned data is 243275793eaSopenharmony_ci allocated and must eventually be freed. NULL is returned if out of memory. 244275793eaSopenharmony_ci If the length is not needed, then len can be NULL. */ 245275793eaSopenharmony_cilocal unsigned char *h2b(const char *hex, unsigned *len) 246275793eaSopenharmony_ci{ 247275793eaSopenharmony_ci unsigned char *in, *re; 248275793eaSopenharmony_ci unsigned next, val; 249275793eaSopenharmony_ci 250275793eaSopenharmony_ci in = malloc((strlen(hex) + 1) >> 1); 251275793eaSopenharmony_ci if (in == NULL) 252275793eaSopenharmony_ci return NULL; 253275793eaSopenharmony_ci next = 0; 254275793eaSopenharmony_ci val = 1; 255275793eaSopenharmony_ci do { 256275793eaSopenharmony_ci if (*hex >= '0' && *hex <= '9') 257275793eaSopenharmony_ci val = (val << 4) + *hex - '0'; 258275793eaSopenharmony_ci else if (*hex >= 'A' && *hex <= 'F') 259275793eaSopenharmony_ci val = (val << 4) + *hex - 'A' + 10; 260275793eaSopenharmony_ci else if (*hex >= 'a' && *hex <= 'f') 261275793eaSopenharmony_ci val = (val << 4) + *hex - 'a' + 10; 262275793eaSopenharmony_ci else if (val != 1 && val < 32) /* one digit followed by delimiter */ 263275793eaSopenharmony_ci val += 240; /* make it look like two digits */ 264275793eaSopenharmony_ci if (val > 255) { /* have two digits */ 265275793eaSopenharmony_ci in[next++] = val & 0xff; /* save the decoded byte */ 266275793eaSopenharmony_ci val = 1; /* start over */ 267275793eaSopenharmony_ci } 268275793eaSopenharmony_ci } while (*hex++); /* go through the loop with the terminating null */ 269275793eaSopenharmony_ci if (len != NULL) 270275793eaSopenharmony_ci *len = next; 271275793eaSopenharmony_ci re = realloc(in, next); 272275793eaSopenharmony_ci return re == NULL ? in : re; 273275793eaSopenharmony_ci} 274275793eaSopenharmony_ci 275275793eaSopenharmony_ci/* generic inflate() run, where hex is the hexadecimal input data, what is the 276275793eaSopenharmony_ci text to include in an error message, step is how much input data to feed 277275793eaSopenharmony_ci inflate() on each call, or zero to feed it all, win is the window bits 278275793eaSopenharmony_ci parameter to inflateInit2(), len is the size of the output buffer, and err 279275793eaSopenharmony_ci is the error code expected from the first inflate() call (the second 280275793eaSopenharmony_ci inflate() call is expected to return Z_STREAM_END). If win is 47, then 281275793eaSopenharmony_ci header information is collected with inflateGetHeader(). If a zlib stream 282275793eaSopenharmony_ci is looking for a dictionary, then an empty dictionary is provided. 283275793eaSopenharmony_ci inflate() is run until all of the input data is consumed. */ 284275793eaSopenharmony_cilocal void inf(char *hex, char *what, unsigned step, int win, unsigned len, 285275793eaSopenharmony_ci int err) 286275793eaSopenharmony_ci{ 287275793eaSopenharmony_ci int ret; 288275793eaSopenharmony_ci unsigned have; 289275793eaSopenharmony_ci unsigned char *in, *out; 290275793eaSopenharmony_ci z_stream strm, copy; 291275793eaSopenharmony_ci gz_header head; 292275793eaSopenharmony_ci 293275793eaSopenharmony_ci mem_setup(&strm); 294275793eaSopenharmony_ci strm.avail_in = 0; 295275793eaSopenharmony_ci strm.next_in = Z_NULL; 296275793eaSopenharmony_ci ret = inflateInit2(&strm, win); 297275793eaSopenharmony_ci if (ret != Z_OK) { 298275793eaSopenharmony_ci mem_done(&strm, what); 299275793eaSopenharmony_ci return; 300275793eaSopenharmony_ci } 301275793eaSopenharmony_ci out = malloc(len); assert(out != NULL); 302275793eaSopenharmony_ci if (win == 47) { 303275793eaSopenharmony_ci head.extra = out; 304275793eaSopenharmony_ci head.extra_max = len; 305275793eaSopenharmony_ci head.name = out; 306275793eaSopenharmony_ci head.name_max = len; 307275793eaSopenharmony_ci head.comment = out; 308275793eaSopenharmony_ci head.comm_max = len; 309275793eaSopenharmony_ci ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); 310275793eaSopenharmony_ci } 311275793eaSopenharmony_ci in = h2b(hex, &have); assert(in != NULL); 312275793eaSopenharmony_ci if (step == 0 || step > have) 313275793eaSopenharmony_ci step = have; 314275793eaSopenharmony_ci strm.avail_in = step; 315275793eaSopenharmony_ci have -= step; 316275793eaSopenharmony_ci strm.next_in = in; 317275793eaSopenharmony_ci do { 318275793eaSopenharmony_ci strm.avail_out = len; 319275793eaSopenharmony_ci strm.next_out = out; 320275793eaSopenharmony_ci ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); 321275793eaSopenharmony_ci if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) 322275793eaSopenharmony_ci break; 323275793eaSopenharmony_ci if (ret == Z_NEED_DICT) { 324275793eaSopenharmony_ci ret = inflateSetDictionary(&strm, in, 1); 325275793eaSopenharmony_ci assert(ret == Z_DATA_ERROR); 326275793eaSopenharmony_ci mem_limit(&strm, 1); 327275793eaSopenharmony_ci ret = inflateSetDictionary(&strm, out, 0); 328275793eaSopenharmony_ci assert(ret == Z_MEM_ERROR); 329275793eaSopenharmony_ci mem_limit(&strm, 0); 330275793eaSopenharmony_ci ((struct inflate_state *)strm.state)->mode = DICT; 331275793eaSopenharmony_ci ret = inflateSetDictionary(&strm, out, 0); 332275793eaSopenharmony_ci assert(ret == Z_OK); 333275793eaSopenharmony_ci ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); 334275793eaSopenharmony_ci } 335275793eaSopenharmony_ci ret = inflateCopy(©, &strm); assert(ret == Z_OK); 336275793eaSopenharmony_ci ret = inflateEnd(©); assert(ret == Z_OK); 337275793eaSopenharmony_ci err = 9; /* don't care next time around */ 338275793eaSopenharmony_ci have += strm.avail_in; 339275793eaSopenharmony_ci strm.avail_in = step > have ? have : step; 340275793eaSopenharmony_ci have -= strm.avail_in; 341275793eaSopenharmony_ci } while (strm.avail_in); 342275793eaSopenharmony_ci free(in); 343275793eaSopenharmony_ci free(out); 344275793eaSopenharmony_ci ret = inflateReset2(&strm, -8); assert(ret == Z_OK); 345275793eaSopenharmony_ci ret = inflateEnd(&strm); assert(ret == Z_OK); 346275793eaSopenharmony_ci mem_done(&strm, what); 347275793eaSopenharmony_ci} 348275793eaSopenharmony_ci 349275793eaSopenharmony_ci/* cover all of the lines in inflate.c up to inflate() */ 350275793eaSopenharmony_cilocal void cover_support(void) 351275793eaSopenharmony_ci{ 352275793eaSopenharmony_ci int ret; 353275793eaSopenharmony_ci z_stream strm; 354275793eaSopenharmony_ci 355275793eaSopenharmony_ci mem_setup(&strm); 356275793eaSopenharmony_ci strm.avail_in = 0; 357275793eaSopenharmony_ci strm.next_in = Z_NULL; 358275793eaSopenharmony_ci ret = inflateInit(&strm); assert(ret == Z_OK); 359275793eaSopenharmony_ci mem_used(&strm, "inflate init"); 360275793eaSopenharmony_ci ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); 361275793eaSopenharmony_ci ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); 362275793eaSopenharmony_ci ret = inflateSetDictionary(&strm, Z_NULL, 0); 363275793eaSopenharmony_ci assert(ret == Z_STREAM_ERROR); 364275793eaSopenharmony_ci ret = inflateEnd(&strm); assert(ret == Z_OK); 365275793eaSopenharmony_ci mem_done(&strm, "prime"); 366275793eaSopenharmony_ci 367275793eaSopenharmony_ci inf("63 0", "force window allocation", 0, -15, 1, Z_OK); 368275793eaSopenharmony_ci inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); 369275793eaSopenharmony_ci inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); 370275793eaSopenharmony_ci inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); 371275793eaSopenharmony_ci inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); 372275793eaSopenharmony_ci 373275793eaSopenharmony_ci mem_setup(&strm); 374275793eaSopenharmony_ci strm.avail_in = 0; 375275793eaSopenharmony_ci strm.next_in = Z_NULL; 376275793eaSopenharmony_ci ret = inflateInit_(&strm, "!", (int)sizeof(z_stream)); 377275793eaSopenharmony_ci assert(ret == Z_VERSION_ERROR); 378275793eaSopenharmony_ci mem_done(&strm, "wrong version"); 379275793eaSopenharmony_ci 380275793eaSopenharmony_ci strm.avail_in = 0; 381275793eaSopenharmony_ci strm.next_in = Z_NULL; 382275793eaSopenharmony_ci ret = inflateInit(&strm); assert(ret == Z_OK); 383275793eaSopenharmony_ci ret = inflateEnd(&strm); assert(ret == Z_OK); 384275793eaSopenharmony_ci fputs("inflate built-in memory routines\n", stderr); 385275793eaSopenharmony_ci} 386275793eaSopenharmony_ci 387275793eaSopenharmony_ci/* cover all inflate() header and trailer cases and code after inflate() */ 388275793eaSopenharmony_cilocal void cover_wrap(void) 389275793eaSopenharmony_ci{ 390275793eaSopenharmony_ci int ret; 391275793eaSopenharmony_ci z_stream strm, copy; 392275793eaSopenharmony_ci unsigned char dict[257]; 393275793eaSopenharmony_ci 394275793eaSopenharmony_ci ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); 395275793eaSopenharmony_ci ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 396275793eaSopenharmony_ci ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); 397275793eaSopenharmony_ci fputs("inflate bad parameters\n", stderr); 398275793eaSopenharmony_ci 399275793eaSopenharmony_ci inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); 400275793eaSopenharmony_ci inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); 401275793eaSopenharmony_ci inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); 402275793eaSopenharmony_ci inf("8 99", "set window size from header", 0, 0, 0, Z_OK); 403275793eaSopenharmony_ci inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); 404275793eaSopenharmony_ci inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); 405275793eaSopenharmony_ci inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, 406275793eaSopenharmony_ci Z_DATA_ERROR); 407275793eaSopenharmony_ci 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", 408275793eaSopenharmony_ci 0, 47, 0, Z_STREAM_END); 409275793eaSopenharmony_ci inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); 410275793eaSopenharmony_ci inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); 411275793eaSopenharmony_ci inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); 412275793eaSopenharmony_ci 413275793eaSopenharmony_ci mem_setup(&strm); 414275793eaSopenharmony_ci strm.avail_in = 0; 415275793eaSopenharmony_ci strm.next_in = Z_NULL; 416275793eaSopenharmony_ci ret = inflateInit2(&strm, -8); 417275793eaSopenharmony_ci strm.avail_in = 2; 418275793eaSopenharmony_ci strm.next_in = (void *)"\x63"; 419275793eaSopenharmony_ci strm.avail_out = 1; 420275793eaSopenharmony_ci strm.next_out = (void *)&ret; 421275793eaSopenharmony_ci mem_limit(&strm, 1); 422275793eaSopenharmony_ci ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 423275793eaSopenharmony_ci ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); 424275793eaSopenharmony_ci mem_limit(&strm, 0); 425275793eaSopenharmony_ci memset(dict, 0, 257); 426275793eaSopenharmony_ci ret = inflateSetDictionary(&strm, dict, 257); 427275793eaSopenharmony_ci assert(ret == Z_OK); 428275793eaSopenharmony_ci mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); 429275793eaSopenharmony_ci ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); 430275793eaSopenharmony_ci strm.avail_in = 2; 431275793eaSopenharmony_ci strm.next_in = (void *)"\x80"; 432275793eaSopenharmony_ci ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); 433275793eaSopenharmony_ci ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); 434275793eaSopenharmony_ci strm.avail_in = 4; 435275793eaSopenharmony_ci strm.next_in = (void *)"\0\0\xff\xff"; 436275793eaSopenharmony_ci ret = inflateSync(&strm); assert(ret == Z_OK); 437275793eaSopenharmony_ci (void)inflateSyncPoint(&strm); 438275793eaSopenharmony_ci ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); 439275793eaSopenharmony_ci mem_limit(&strm, 0); 440275793eaSopenharmony_ci ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); 441275793eaSopenharmony_ci (void)inflateMark(&strm); 442275793eaSopenharmony_ci ret = inflateEnd(&strm); assert(ret == Z_OK); 443275793eaSopenharmony_ci mem_done(&strm, "miscellaneous, force memory errors"); 444275793eaSopenharmony_ci} 445275793eaSopenharmony_ci 446275793eaSopenharmony_ci/* input and output functions for inflateBack() */ 447275793eaSopenharmony_cilocal unsigned pull(void *desc, unsigned char **buf) 448275793eaSopenharmony_ci{ 449275793eaSopenharmony_ci static unsigned int next = 0; 450275793eaSopenharmony_ci static unsigned char dat[] = {0x63, 0, 2, 0}; 451275793eaSopenharmony_ci struct inflate_state *state; 452275793eaSopenharmony_ci 453275793eaSopenharmony_ci if (desc == Z_NULL) { 454275793eaSopenharmony_ci next = 0; 455275793eaSopenharmony_ci return 0; /* no input (already provided at next_in) */ 456275793eaSopenharmony_ci } 457275793eaSopenharmony_ci state = (void *)((z_stream *)desc)->state; 458275793eaSopenharmony_ci if (state != Z_NULL) 459275793eaSopenharmony_ci state->mode = SYNC; /* force an otherwise impossible situation */ 460275793eaSopenharmony_ci return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; 461275793eaSopenharmony_ci} 462275793eaSopenharmony_ci 463275793eaSopenharmony_cilocal int push(void *desc, unsigned char *buf, unsigned len) 464275793eaSopenharmony_ci{ 465275793eaSopenharmony_ci (void)buf; 466275793eaSopenharmony_ci (void)len; 467275793eaSopenharmony_ci return desc != Z_NULL; /* force error if desc not null */ 468275793eaSopenharmony_ci} 469275793eaSopenharmony_ci 470275793eaSopenharmony_ci/* cover inflateBack() up to common deflate data cases and after those */ 471275793eaSopenharmony_cilocal void cover_back(void) 472275793eaSopenharmony_ci{ 473275793eaSopenharmony_ci int ret; 474275793eaSopenharmony_ci z_stream strm; 475275793eaSopenharmony_ci unsigned char win[32768]; 476275793eaSopenharmony_ci 477275793eaSopenharmony_ci ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); 478275793eaSopenharmony_ci assert(ret == Z_VERSION_ERROR); 479275793eaSopenharmony_ci ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); 480275793eaSopenharmony_ci ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); 481275793eaSopenharmony_ci assert(ret == Z_STREAM_ERROR); 482275793eaSopenharmony_ci ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); 483275793eaSopenharmony_ci fputs("inflateBack bad parameters\n", stderr); 484275793eaSopenharmony_ci 485275793eaSopenharmony_ci mem_setup(&strm); 486275793eaSopenharmony_ci ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 487275793eaSopenharmony_ci strm.avail_in = 2; 488275793eaSopenharmony_ci strm.next_in = (void *)"\x03"; 489275793eaSopenharmony_ci ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 490275793eaSopenharmony_ci assert(ret == Z_STREAM_END); 491275793eaSopenharmony_ci /* force output error */ 492275793eaSopenharmony_ci strm.avail_in = 3; 493275793eaSopenharmony_ci strm.next_in = (void *)"\x63\x00"; 494275793eaSopenharmony_ci ret = inflateBack(&strm, pull, Z_NULL, push, &strm); 495275793eaSopenharmony_ci assert(ret == Z_BUF_ERROR); 496275793eaSopenharmony_ci /* force mode error by mucking with state */ 497275793eaSopenharmony_ci ret = inflateBack(&strm, pull, &strm, push, Z_NULL); 498275793eaSopenharmony_ci assert(ret == Z_STREAM_ERROR); 499275793eaSopenharmony_ci ret = inflateBackEnd(&strm); assert(ret == Z_OK); 500275793eaSopenharmony_ci mem_done(&strm, "inflateBack bad state"); 501275793eaSopenharmony_ci 502275793eaSopenharmony_ci ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); 503275793eaSopenharmony_ci ret = inflateBackEnd(&strm); assert(ret == Z_OK); 504275793eaSopenharmony_ci fputs("inflateBack built-in memory routines\n", stderr); 505275793eaSopenharmony_ci} 506275793eaSopenharmony_ci 507275793eaSopenharmony_ci/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ 508275793eaSopenharmony_cilocal int try(char *hex, char *id, int err) 509275793eaSopenharmony_ci{ 510275793eaSopenharmony_ci int ret; 511275793eaSopenharmony_ci unsigned len, size; 512275793eaSopenharmony_ci unsigned char *in, *out, *win; 513275793eaSopenharmony_ci char *prefix; 514275793eaSopenharmony_ci z_stream strm; 515275793eaSopenharmony_ci 516275793eaSopenharmony_ci /* convert to hex */ 517275793eaSopenharmony_ci in = h2b(hex, &len); 518275793eaSopenharmony_ci assert(in != NULL); 519275793eaSopenharmony_ci 520275793eaSopenharmony_ci /* allocate work areas */ 521275793eaSopenharmony_ci size = len << 3; 522275793eaSopenharmony_ci out = malloc(size); 523275793eaSopenharmony_ci assert(out != NULL); 524275793eaSopenharmony_ci win = malloc(32768); 525275793eaSopenharmony_ci assert(win != NULL); 526275793eaSopenharmony_ci prefix = malloc(strlen(id) + 6); 527275793eaSopenharmony_ci assert(prefix != NULL); 528275793eaSopenharmony_ci 529275793eaSopenharmony_ci /* first with inflate */ 530275793eaSopenharmony_ci strcpy(prefix, id); 531275793eaSopenharmony_ci strcat(prefix, "-late"); 532275793eaSopenharmony_ci mem_setup(&strm); 533275793eaSopenharmony_ci strm.avail_in = 0; 534275793eaSopenharmony_ci strm.next_in = Z_NULL; 535275793eaSopenharmony_ci ret = inflateInit2(&strm, err < 0 ? 47 : -15); 536275793eaSopenharmony_ci assert(ret == Z_OK); 537275793eaSopenharmony_ci strm.avail_in = len; 538275793eaSopenharmony_ci strm.next_in = in; 539275793eaSopenharmony_ci do { 540275793eaSopenharmony_ci strm.avail_out = size; 541275793eaSopenharmony_ci strm.next_out = out; 542275793eaSopenharmony_ci ret = inflate(&strm, Z_TREES); 543275793eaSopenharmony_ci assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); 544275793eaSopenharmony_ci if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) 545275793eaSopenharmony_ci break; 546275793eaSopenharmony_ci } while (strm.avail_in || strm.avail_out == 0); 547275793eaSopenharmony_ci if (err) { 548275793eaSopenharmony_ci assert(ret == Z_DATA_ERROR); 549275793eaSopenharmony_ci assert(strcmp(id, strm.msg) == 0); 550275793eaSopenharmony_ci } 551275793eaSopenharmony_ci inflateEnd(&strm); 552275793eaSopenharmony_ci mem_done(&strm, prefix); 553275793eaSopenharmony_ci 554275793eaSopenharmony_ci /* then with inflateBack */ 555275793eaSopenharmony_ci if (err >= 0) { 556275793eaSopenharmony_ci strcpy(prefix, id); 557275793eaSopenharmony_ci strcat(prefix, "-back"); 558275793eaSopenharmony_ci mem_setup(&strm); 559275793eaSopenharmony_ci ret = inflateBackInit(&strm, 15, win); 560275793eaSopenharmony_ci assert(ret == Z_OK); 561275793eaSopenharmony_ci strm.avail_in = len; 562275793eaSopenharmony_ci strm.next_in = in; 563275793eaSopenharmony_ci ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); 564275793eaSopenharmony_ci assert(ret != Z_STREAM_ERROR); 565275793eaSopenharmony_ci if (err) { 566275793eaSopenharmony_ci assert(ret == Z_DATA_ERROR); 567275793eaSopenharmony_ci assert(strcmp(id, strm.msg) == 0); 568275793eaSopenharmony_ci } 569275793eaSopenharmony_ci inflateBackEnd(&strm); 570275793eaSopenharmony_ci mem_done(&strm, prefix); 571275793eaSopenharmony_ci } 572275793eaSopenharmony_ci 573275793eaSopenharmony_ci /* clean up */ 574275793eaSopenharmony_ci free(prefix); 575275793eaSopenharmony_ci free(win); 576275793eaSopenharmony_ci free(out); 577275793eaSopenharmony_ci free(in); 578275793eaSopenharmony_ci return ret; 579275793eaSopenharmony_ci} 580275793eaSopenharmony_ci 581275793eaSopenharmony_ci/* cover deflate data cases in both inflate() and inflateBack() */ 582275793eaSopenharmony_cilocal void cover_inflate(void) 583275793eaSopenharmony_ci{ 584275793eaSopenharmony_ci try("0 0 0 0 0", "invalid stored block lengths", 1); 585275793eaSopenharmony_ci try("3 0", "fixed", 0); 586275793eaSopenharmony_ci try("6", "invalid block type", 1); 587275793eaSopenharmony_ci try("1 1 0 fe ff 0", "stored", 0); 588275793eaSopenharmony_ci try("fc 0 0", "too many length or distance symbols", 1); 589275793eaSopenharmony_ci try("4 0 fe ff", "invalid code lengths set", 1); 590275793eaSopenharmony_ci try("4 0 24 49 0", "invalid bit length repeat", 1); 591275793eaSopenharmony_ci try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); 592275793eaSopenharmony_ci try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); 593275793eaSopenharmony_ci try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", 594275793eaSopenharmony_ci "invalid literal/lengths set", 1); 595275793eaSopenharmony_ci try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); 596275793eaSopenharmony_ci try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); 597275793eaSopenharmony_ci try("2 7e ff ff", "invalid distance code", 1); 598275793eaSopenharmony_ci try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); 599275793eaSopenharmony_ci 600275793eaSopenharmony_ci /* also trailer mismatch just in inflate() */ 601275793eaSopenharmony_ci try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); 602275793eaSopenharmony_ci try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", 603275793eaSopenharmony_ci "incorrect length check", -1); 604275793eaSopenharmony_ci try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); 605275793eaSopenharmony_ci try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", 606275793eaSopenharmony_ci "long code", 0); 607275793eaSopenharmony_ci try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); 608275793eaSopenharmony_ci 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", 609275793eaSopenharmony_ci "long distance and extra", 0); 610275793eaSopenharmony_ci 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 " 611275793eaSopenharmony_ci "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); 612275793eaSopenharmony_ci inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, 613275793eaSopenharmony_ci Z_STREAM_END); 614275793eaSopenharmony_ci inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); 615275793eaSopenharmony_ci} 616275793eaSopenharmony_ci 617275793eaSopenharmony_ci/* cover remaining lines in inftrees.c */ 618275793eaSopenharmony_cilocal void cover_trees(void) 619275793eaSopenharmony_ci{ 620275793eaSopenharmony_ci int ret; 621275793eaSopenharmony_ci unsigned bits; 622275793eaSopenharmony_ci unsigned short lens[16], work[16]; 623275793eaSopenharmony_ci code *next, table[ENOUGH_DISTS]; 624275793eaSopenharmony_ci 625275793eaSopenharmony_ci /* we need to call inflate_table() directly in order to manifest not- 626275793eaSopenharmony_ci enough errors, since zlib insures that enough is always enough */ 627275793eaSopenharmony_ci for (bits = 0; bits < 15; bits++) 628275793eaSopenharmony_ci lens[bits] = (unsigned short)(bits + 1); 629275793eaSopenharmony_ci lens[15] = 15; 630275793eaSopenharmony_ci next = table; 631275793eaSopenharmony_ci bits = 15; 632275793eaSopenharmony_ci ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 633275793eaSopenharmony_ci assert(ret == 1); 634275793eaSopenharmony_ci next = table; 635275793eaSopenharmony_ci bits = 1; 636275793eaSopenharmony_ci ret = inflate_table(DISTS, lens, 16, &next, &bits, work); 637275793eaSopenharmony_ci assert(ret == 1); 638275793eaSopenharmony_ci fputs("inflate_table not enough errors\n", stderr); 639275793eaSopenharmony_ci} 640275793eaSopenharmony_ci 641275793eaSopenharmony_ci/* cover remaining inffast.c decoding and window copying */ 642275793eaSopenharmony_cilocal void cover_fast(void) 643275793eaSopenharmony_ci{ 644275793eaSopenharmony_ci inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" 645275793eaSopenharmony_ci " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); 646275793eaSopenharmony_ci inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" 647275793eaSopenharmony_ci " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, 648275793eaSopenharmony_ci Z_DATA_ERROR); 649275793eaSopenharmony_ci inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, 650275793eaSopenharmony_ci Z_DATA_ERROR); 651275793eaSopenharmony_ci inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, 652275793eaSopenharmony_ci Z_DATA_ERROR); 653275793eaSopenharmony_ci 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", 654275793eaSopenharmony_ci "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); 655275793eaSopenharmony_ci inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); 656275793eaSopenharmony_ci inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", 657275793eaSopenharmony_ci "contiguous and wrap around window", 6, -8, 259, Z_OK); 658275793eaSopenharmony_ci inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, 659275793eaSopenharmony_ci Z_STREAM_END); 660275793eaSopenharmony_ci} 661275793eaSopenharmony_ci 662275793eaSopenharmony_ciint main(void) 663275793eaSopenharmony_ci{ 664275793eaSopenharmony_ci fprintf(stderr, "%s\n", zlibVersion()); 665275793eaSopenharmony_ci cover_support(); 666275793eaSopenharmony_ci cover_wrap(); 667275793eaSopenharmony_ci cover_back(); 668275793eaSopenharmony_ci cover_inflate(); 669275793eaSopenharmony_ci cover_trees(); 670275793eaSopenharmony_ci cover_fast(); 671275793eaSopenharmony_ci return 0; 672275793eaSopenharmony_ci} 673