chromium/third_party/zlib/contrib/tests/infcover.cc

/* infcover.c -- test zlib's inflate routines with full code coverage
 * Copyright (C) 2011, 2016 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* to use, do: ./configure --cover && make cover */
// clang-format off
#include "infcover.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "zlib.h"

/* get definition of internal structure so we can mess with it (see pull()),
   and so we can call inflate_trees() (see cover5()) */
#define ZLIB_INTERNAL
#include "inftrees.h"
#include "inflate.h"

/* XXX: use C++ streams instead of printf/fputs/etc due to portability
 * as type sizes can vary between platforms.
 */
#include <iostream>
#define local

/* XXX: hacking C assert and plugging into GTest. */
#include "gtest.h"
#if defined(assert)
#undef assert
#define assert
#endif

/* XXX: handle what is a reserved word in C++. */
#define try try_f

/* -- memory tracking routines -- */

/*
   These memory tracking routines are provided to zlib and track all of zlib's
   allocations and deallocations, check for LIFO operations, keep a current
   and high water mark of total bytes requested, optionally set a limit on the
   total memory that can be allocated, and when done check for memory leaks.

   They are used as follows:

   z_stream strm;
   mem_setup(&strm)         initializes the memory tracking and sets the
                            zalloc, zfree, and opaque members of strm to use
                            memory tracking for all zlib operations on strm
   mem_limit(&strm, limit)  sets a limit on the total bytes requested -- a
                            request that exceeds this limit will result in an
                            allocation failure (returns NULL) -- setting the
                            limit to zero means no limit, which is the default
                            after mem_setup()
   mem_used(&strm, "msg")   prints to stderr "msg" and the total bytes used
   mem_high(&strm, "msg")   prints to stderr "msg" and the high water mark
   mem_done(&strm, "msg")   ends memory tracking, releases all allocations
                            for the tracking as well as leaked zlib blocks, if
                            any.  If there was anything unusual, such as leaked
                            blocks, non-FIFO frees, or frees of addresses not
                            allocated, then "msg" and information about the
                            problem is printed to stderr.  If everything is
                            normal, nothing is printed. mem_done resets the
                            strm members to Z_NULL to use the default memory
                            allocation routines on the next zlib initialization
                            using strm.
 */

/* these items are strung together in a linked list, one for each allocation */
struct mem_item {};

/* this structure is at the root of the linked list, and tracks statistics */
struct mem_zone {};

/* memory allocation routine to pass to zlib */
local void *mem_alloc(void *mem, unsigned count, unsigned size)
{}

/* memory free routine to pass to zlib */
local void mem_free(void *mem, void *ptr)
{}

/* set up a controlled memory allocation space for monitoring, set the stream
   parameters to the controlled routines, with opaque pointing to the space */
local void mem_setup(z_stream *strm)
{}

/* set a limit on the total memory allocation, or 0 to remove the limit */
local void mem_limit(z_stream *strm, size_t limit)
{}

/* show the current total requested allocations in bytes */
local void mem_used(z_stream *strm, const char *prefix)
{}

/* show the high water allocation in bytes */
local void mem_high(z_stream *strm, const char *prefix)
{}

/* release the memory allocation zone -- if there are any surprises, notify */
local void mem_done(z_stream *strm, const char *prefix)
{}

/* -- inflate test routines -- */

/* Decode a hexadecimal string, set *len to length, in[] to the bytes.  This
   decodes liberally, in that hex digits can be adjacent, in which case two in
   a row writes a byte.  Or they can be delimited by any non-hex character,
   where the delimiters are ignored except when a single hex digit is followed
   by a delimiter, where that single digit writes a byte.  The returned data is
   allocated and must eventually be freed.  NULL is returned if out of memory.
   If the length is not needed, then len can be NULL. */
local unsigned char *h2b(const char *hex, unsigned *len)
{}

/* generic inflate() run, where hex is the hexadecimal input data, what is the
   text to include in an error message, step is how much input data to feed
   inflate() on each call, or zero to feed it all, win is the window bits
   parameter to inflateInit2(), len is the size of the output buffer, and err
   is the error code expected from the first inflate() call (the second
   inflate() call is expected to return Z_STREAM_END).  If win is 47, then
   header information is collected with inflateGetHeader().  If a zlib stream
   is looking for a dictionary, then an empty dictionary is provided.
   inflate() is run until all of the input data is consumed. */
local void inf(const char *hex, const char *what, unsigned step, int win, unsigned len,
               int err)
{}

/* cover all of the lines in inflate.c up to inflate() */
void cover_support(void)
{}

/* cover all inflate() header and trailer cases and code after inflate() */
void cover_wrap(void)
{}

/* input and output functions for inflateBack() */
local unsigned pull(void *desc, unsigned char **buf)
{}

local int push(void *desc, unsigned char *buf, unsigned len)
{}

/* cover inflateBack() up to common deflate data cases and after those */
void cover_back(void)
{}

/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
local int try(const char *hex, const char *id, int err)
{}

/* cover deflate data cases in both inflate() and inflateBack() */
void cover_inflate(void)
{}

/* XXX(cavalcantii): fix linking error due inflate_table. */
/* cover remaining lines in inftrees.c */
/* void cover_trees(void) */
/* { */
/*     int ret; */
/*     unsigned bits; */
/*     unsigned short lens[16], work[16]; */
/*     code *next, table[ENOUGH_DISTS]; */

/*     /\* we need to call inflate_table() directly in order to manifest not- */
/*        enough errors, since zlib insures that enough is always enough *\/ */
/*     for (bits = 0; bits < 15; bits++) */
/*         lens[bits] = (unsigned short)(bits + 1); */
/*     lens[15] = 15; */
/*     next = table; */
/*     bits = 15; */
/*     ret = inflate_table(DISTS, lens, 16, &next, &bits, work); */
/*                                                 assert(ret == 1); */
/*     next = table; */
/*     bits = 1; */
/*     ret = inflate_table(DISTS, lens, 16, &next, &bits, work); */
/*                                                 assert(ret == 1); */
/*     fputs("inflate_table not enough errors\n", stderr); */
/* } */

/* cover remaining inffast.c decoding and window copying */
void cover_fast(void)
{}

/* Adapted from Evgeny Legerov PoC (https://github.com/ivd38/zlib_overflow)
 * this test case crashes in ASAN builds with the correct payload.
 */
local void inf_cve_2022_37434(char *hex, char *what, unsigned step, int win, unsigned len,
                              int err)
{}

void cover_CVE_2022_37434(void)
{}

// clang-format on