blob: a7eacfc10a5514daa28d0820d66b0d3e825c4e95 [file] [log] [blame] [edit]
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//% This code is derived from puff.{c,h}, found in the zlib development. The
//% original files come with the following copyright notice:
//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
//% version 2.3, 21 Jan 2013
//% This software is provided 'as-is', without any express or implied
//% warranty. In no event will the author be held liable for any damages
//% arising from the use of this software.
//% Permission is granted to anyone to use this software for any purpose,
//% including commercial applications, and to alter it and redistribute it
//% freely, subject to the following restrictions:
//% 1. The origin of this software must not be misrepresented; you must not
//% claim that you wrote the original software. If you use this software
//% in a product, an acknowledgment in the product documentation would be
//% appreciated but is not required.
//% 2. Altered source versions must be plainly marked as such, and must not be
//% misrepresented as being the original software.
//% 3. This notice may not be removed or altered from any source distribution.
//% Mark Adler madler@alumni.caltech.edu
//% BEGIN CODE DERIVED FROM puff.{c,h}
// All dynamically allocated memory comes from the stack. The stack required
// is less than 2K bytes. This code is compatible with 16-bit int's and
// assumes that long's are at least 32 bits. puff.c uses the short data type,
// assumed to be 16 bits, for arrays in order to conserve memory. The code
// works whether integers are stored big endian or little endian.
#include <setjmp.h> // for setjmp(), longjmp(), and jmp_buf
// Maximums for allocations and loops.
#define MAXBITS 15 // maximum bits in a code
#define MAXLCODES 286 // maximum number of literal/length codes
#define MAXDCODES 30 // maximum number of distance codes
#define MAXCODES (MAXLCODES + MAXDCODES) // maximum codes lengths to read
#define FIXLCODES 288 // number of fixed literal/length codes
struct puff_state {
// output state
unsigned char* out; // output buffer
unsigned long outlen; // available space at out
unsigned long outcnt; // bytes written to out so far
// input state
const unsigned char* in; // input buffer
unsigned long inlen; // available input at in
unsigned long incnt; // bytes read so far
int bitbuf; // bit buffer
int bitcnt; // number of bits in bit buffer
// input limit error return state for bits() and decode()
jmp_buf env;
};
// Return need bits from the input stream. This always leaves less than
// eight bits in the buffer. bits() works properly for need == 0.
static int puff_bits(struct puff_state* s, int need)
{
// bit accumulator (can use up to 20 bits)
// load at least need bits into val
long val = s->bitbuf;
while (s->bitcnt < need) {
if (s->incnt == s->inlen)
longjmp(s->env, 1); // out of input
val |= (long)(s->in[s->incnt++]) << s->bitcnt; // load eight bits
s->bitcnt += 8;
}
// drop need bits and update buffer, always zero to seven bits left
s->bitbuf = (int)(val >> need);
s->bitcnt -= need;
// return need bits, zeroing the bits above that
return (int)(val & ((1L << need) - 1));
}
// Process a stored block.
static int puff_stored(struct puff_state* s)
{
// discard leftover bits from current byte (assumes s->bitcnt < 8)
s->bitbuf = 0;
s->bitcnt = 0;
// get length and check against its one's complement
if (s->incnt + 4 > s->inlen)
return 2; // not enough input
unsigned len = s->in[s->incnt++]; // length of stored block
len |= s->in[s->incnt++] << 8;
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2; // didn't match complement!
// copy len bytes from in to out
if (s->incnt + len > s->inlen)
return 2; // not enough input
if (s->outcnt + len > s->outlen)
return 1; // not enough output space
for (; len--; s->outcnt++, s->incnt++) {
if (s->in[s->incnt])
s->out[s->outcnt] = s->in[s->incnt];
}
// done with a valid stored block
return 0;
}
// Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of
// each length, which for a canonical code are stepped through in order.
// symbol[] are the symbol values in canonical order, where the number of
// entries is the sum of the counts in count[]. The decoding process can be
// seen in the function decode() below.
struct puff_huffman {
short* count; // number of symbols of each length
short* symbol; // canonically ordered symbols
};
// Decode a code from the stream s using huffman table h. Return the symbol or
// a negative value if there is an error. If all of the lengths are zero, i.e.
// an empty code, or if the code is incomplete and an invalid code is received,
// then -10 is returned after reading MAXBITS bits.
static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
{
int first = 0; // first code of length len
int index = 0; // index of first code of length len in symbol table
int bitbuf = s->bitbuf; // bits from stream
int left = s->bitcnt; // bits left in next or left to process
int code = first = index = 0; // len bits being decoded
int len = 1; // current number of bits in code
short* next = h->count + 1; // next number of codes
while (1) {
while (left--) {
code |= bitbuf & 1;
bitbuf >>= 1;
int count = *next++; // number of codes of length len
if (code - count < first) { // if length len, return symbol
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7;
return h->symbol[index + (code - first)];
}
index += count; // else update for next length
first += count;
first <<= 1;
code <<= 1;
len++;
}
left = (MAXBITS + 1) - len;
if (left == 0)
break;
if (s->incnt == s->inlen)
longjmp(s->env, 1); // out of input
bitbuf = s->in[s->incnt++];
if (left > 8)
left = 8;
}
return -10; // ran out of codes
}
// Given the list of code lengths length[0..n-1] representing a canonical
// Huffman code for n symbols, construct the tables required to decode those
// codes. Those tables are the number of codes of each length, and the symbols
// sorted by length, retaining their original order within each length. The
// return value is zero for a complete code set, negative for an over-
// subscribed code set, and positive for an incomplete code set. The tables
// can be used if the return value is zero or positive, but they cannot be used
// if the return value is negative. If the return value is zero, it is not
// possible for decode() using that table to return an error--any stream of
// enough bits will resolve to a symbol. If the return value is positive, then
// it is possible for decode() using that table to return an error for received
// codes past the end of the incomplete lengths.
// Not used by decode(), but used for error checking, h->count[0] is the number
// of the n symbols not in the code. So n - h->count[0] is the number of
// codes. This is useful for checking for incomplete codes that have more than
// one symbol, which is an error in a dynamic block.
// Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS
// This is assured by the construction of the length arrays in dynamic() and
// fixed() and is not verified by construct().
static int puff_construct(struct puff_huffman* h, const short* length, int n)
{
// count number of codes of each length
int len; // current length when stepping through h->count[]
for (len = 0; len <= MAXBITS; len++)
h->count[len] = 0;
int symbol; // current symbol when stepping through length[]
for (symbol = 0; symbol < n; symbol++)
(h->count[length[symbol]])++; // assumes lengths are within bounds
if (h->count[0] == n) // no codes!
return 0; // complete, but decode() will fail
// check for an over-subscribed or incomplete set of lengths
int left = 1; // one possible code of zero length
for (len = 1; len <= MAXBITS; len++) {
left <<= 1; // one more bit, double codes left
left -= h->count[len]; // deduct count from possible codes
if (left < 0)
return left; // over-subscribed--return negative
} // left > 0 means incomplete
// generate offsets into symbol table for each length for sorting
short offs[MAXBITS + 1];
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + h->count[len];
// put symbols in table sorted by length, by symbol order within each length
for (symbol = 0; symbol < n; symbol++)
if (length[symbol] != 0)
h->symbol[offs[length[symbol]]++] = symbol;
// return zero for complete set, positive for incomplete set
return left;
}
// Decode literal/length and distance codes until an end-of-block code.
static int puff_codes(struct puff_state* s,
const struct puff_huffman* lencode,
const struct puff_huffman* distcode)
{
static const short lens[29] = {// Size base for length codes 257..285
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
static const short lext[29] = {// Extra bits for length codes 257..285
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
static const short dists[30] = {// Offset base for distance codes 0..29
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
static const short dext[30] = {// Extra bits for distance codes 0..29
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
// decode literals and length/distance pairs
int symbol; // decoded symbol
do {
symbol = puff_decode(s, lencode);
if (symbol < 0)
return symbol; // invalid symbol
if (symbol < 256) { // literal: symbol is the byte
// write out the literal
if (s->outcnt == s->outlen)
return 1;
if (symbol)
s->out[s->outcnt] = symbol;
s->outcnt++;
} else if (symbol > 256) { // length
// get and compute length
symbol -= 257;
if (symbol >= 29)
return -10; // invalid fixed code
int len = lens[symbol] + puff_bits(s, lext[symbol]);
// get and check distance
symbol = puff_decode(s, distcode);
if (symbol < 0)
return symbol; // invalid symbol
unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
if (dist > s->outcnt)
return -11; // distance too far back
// copy length bytes from distance bytes back
if (s->outcnt + len > s->outlen)
return 1;
while (len--) {
if (dist <= s->outcnt && s->out[s->outcnt - dist])
s->out[s->outcnt] = s->out[s->outcnt - dist];
s->outcnt++;
}
}
} while (symbol != 256); // end of block symbol
// done with a valid fixed or dynamic block
return 0;
}
// Process a fixed codes block.
static int puff_fixed(struct puff_state* s)
{
static int virgin = 1;
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
static struct puff_huffman lencode, distcode;
// build fixed huffman tables if first call (may not be thread safe)
if (virgin) {
// construct lencode and distcode
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;
// literal/length table
short lengths[FIXLCODES];
int symbol;
for (symbol = 0; symbol < 144; symbol++)
lengths[symbol] = 8;
for (; symbol < 256; symbol++)
lengths[symbol] = 9;
for (; symbol < 280; symbol++)
lengths[symbol] = 7;
for (; symbol < FIXLCODES; symbol++)
lengths[symbol] = 8;
puff_construct(&lencode, lengths, FIXLCODES);
// distance table
for (symbol = 0; symbol < MAXDCODES; symbol++)
lengths[symbol] = 5;
puff_construct(&distcode, lengths, MAXDCODES);
// do this just once
virgin = 0;
}
// decode data until end-of-block code
return puff_codes(s, &lencode, &distcode);
}
// Process a dynamic codes block.
static int puff_dynamic(struct puff_state* s)
{
static const short order[19] = // permutation of code length codes
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
// get number of lengths in each table, check lengths
int nlen = puff_bits(s, 5) + 257; // number of lengths in descriptor
int ndist = puff_bits(s, 5) + 1;
int ncode = puff_bits(s, 4) + 4;
if (nlen > MAXLCODES || ndist > MAXDCODES)
return -3; // bad counts
// read code length code lengths (really), missing lengths are zero
short lengths[MAXCODES]; // descriptor code lengths
int index; // index of lengths[]
for (index = 0; index < ncode; index++)
lengths[order[index]] = puff_bits(s, 3);
for (; index < 19; index++)
lengths[order[index]] = 0;
// build huffman table for code lengths codes (use lencode temporarily)
short lencnt[MAXBITS + 1], lensym[MAXLCODES]; // lencode memory
struct puff_huffman lencode = {lencnt, lensym}; // length codes
int err = puff_construct(&lencode, lengths, 19);
if (err != 0) // require complete code set here
return -4;
// read length/literal and distance code length tables
index = 0;
while (index < nlen + ndist) {
int symbol; // decoded value
int len; // last length to repeat
symbol = puff_decode(s, &lencode);
if (symbol < 0)
return symbol; // invalid symbol
if (symbol < 16) // length in 0..15
lengths[index++] = symbol;
else { // repeat instruction
len = 0; // assume repeating zeros
if (symbol == 16) { // repeat last length 3..6 times
if (index == 0)
return -5; // no last length!
len = lengths[index - 1]; // last length
symbol = 3 + puff_bits(s, 2);
} else if (symbol == 17) // repeat zero 3..10 times
symbol = 3 + puff_bits(s, 3);
else // == 18, repeat zero 11..138 times
symbol = 11 + puff_bits(s, 7);
if (index + symbol > nlen + ndist)
return -6; // too many lengths!
while (symbol--) // repeat last or zero symbol times
lengths[index++] = len;
}
}
// check for end-of-block code -- there better be one!
if (lengths[256] == 0)
return -9;
// build huffman table for literal/length codes
err = puff_construct(&lencode, lengths, nlen);
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
return -7; // incomplete code ok only for single length 1 code
// build huffman table for distance codes
short distcnt[MAXBITS + 1], distsym[MAXDCODES]; // distcode memory
struct puff_huffman distcode = {distcnt, distsym}; // distance codes
err = puff_construct(&distcode, lengths + nlen, ndist);
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
return -8; // incomplete code ok only for single length 1 code
// decode data until end-of-block code
return puff_codes(s, &lencode, &distcode);
}
// Inflate source to dest. On return, destlen and sourcelen are updated to the
// size of the uncompressed data and the size of the deflate data respectively.
// On success, the return value of puff() is zero. If there is an error in the
// source data, i.e. it is not in the deflate format, then a negative value is
// returned. If there is not enough input available or there is not enough
// output space, then a positive error is returned. In that case, destlen and
// sourcelen are not updated to facilitate retrying from the beginning with the
// provision of more input data or more output space. In the case of invalid
// inflate data (a negative error), the dest and source pointers are updated to
// facilitate the debugging of deflators.
// The return codes are:
// 2: available inflate data did not terminate
// 1: output space exhausted before completing inflate
// 0: successful inflate
// -1: invalid block type (type == 3)
// -2: stored block length did not match one's complement
// -3: dynamic block code description: too many length or distance codes
// -4: dynamic block code description: code lengths codes incomplete
// -5: dynamic block code description: repeat lengths with no first length
// -6: dynamic block code description: repeat more than specified lengths
// -7: dynamic block code description: invalid literal/length code lengths
// -8: dynamic block code description: invalid distance code lengths
// -9: dynamic block code description: missing end-of-block code
// -10: invalid literal/length or distance code in fixed or dynamic block
// -11: distance is too far back in fixed or dynamic block
static int puff(
unsigned char* dest, // pointer to destination pointer
unsigned long* destlen, // amount of output space
const unsigned char* source, // pointer to source data pointer
unsigned long sourcelen) // amount of input available
{
struct puff_state s = {
.out = dest,
.outlen = *destlen,
.outcnt = 0,
.in = source,
.inlen = sourcelen,
.incnt = 0,
.bitbuf = 0,
.bitcnt = 0,
};
// return if bits() or decode() tries to read past available input
int err; // return value
if (setjmp(s.env) != 0) // if came back here via longjmp()
err = 2; // then skip do-loop, return error
else {
// process blocks until last block or error
int last;
do {
last = puff_bits(&s, 1); // one if last block
int type = puff_bits(&s, 2); // block type 0..3
err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1)); // type == 3, invalid
if (err != 0)
break; // return with error
} while (!last);
}
*destlen = s.outcnt;
return err;
}
//% END CODE DERIVED FROM puff.{c,h}
#include <errno.h>
#include <sys/mman.h>
#define ZLIB_HEADER_WIDTH 2 // Two-byte zlib header width.
static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
{
// Ignore zlib header.
if (sourcelen < ZLIB_HEADER_WIDTH)
return 0;
source += ZLIB_HEADER_WIDTH;
sourcelen -= ZLIB_HEADER_WIDTH;
// Note: pkg/image/compression.go also knows this const.
const unsigned long max_destlen = 132 << 20;
void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
if (ret == MAP_FAILED)
return -1;
unsigned char* dest = (unsigned char*)ret;
// Inflate source array to destination file.
unsigned long destlen = max_destlen; // copy destlen as puff() may modify it
int err = puff(dest, &destlen, source, sourcelen);
if (err) {
munmap(dest, max_destlen);
errno = -err;
return -1;
}
if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
munmap(dest, max_destlen);
return -1;
}
// Unmap memory-mapped region
return munmap(dest, max_destlen);
}