tinf, minzllib: support unknown input sizes

This can be used when the input file size is unknown: the decompression
functions will keep track of it and return it to the caller instead.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-02-06 15:10:14 +09:00
parent 0cd328214c
commit 61e2c36ef5
9 changed files with 95 additions and 45 deletions

View file

@ -102,6 +102,14 @@ BfSeek (
return true;
}
uint32_t
BfTell (
void
)
{
return In.Offset;
}
bool
BfRead (
uint8_t* Byte

View file

@ -37,6 +37,7 @@ Environment:
//
bool BfRead(uint8_t* Byte);
bool BfSeek(uint32_t Length, uint8_t** Bytes);
uint32_t BfTell(void);
bool BfAlign(void);
void BfInitialize(uint8_t* InputBuffer, uint32_t InputSize);
bool BfSetSoftLimit(uint32_t Remaining);

View file

@ -10,7 +10,8 @@
* either CRC32 or None as the checksum type.
*
* @param[in] InputBuffer - A fully formed buffer containing the XZ stream.
* @param[in] InputSize - The size of the input buffer.
* @param[in,out] InputSize - The size of the input buffer. On output, the size
* consumed from the input buffer.
* @param[in] OutputBuffer - A fully allocated buffer to receive the output.
* Callers can pass in NULL if they do not intend to decompress,
* in combination with setting OutputSize to 0, in order to query
@ -26,7 +27,7 @@
bool
XzDecode (
uint8_t* InputBuffer,
uint32_t InputSize,
uint32_t* InputSize,
uint8_t* OutputBuffer,
uint32_t* OutputSize
);

View file

@ -28,6 +28,8 @@ Environment:
--*/
#define MINLZ_META_CHECKS
#include "minlzlib.h"
#include "xzstream.h"
#include "../utils.h"
@ -467,17 +469,16 @@ XzDecodeBlockHeader (
bool
XzDecode (
uint8_t* InputBuffer,
uint32_t InputSize,
uint32_t* InputSize,
uint8_t* OutputBuffer,
uint32_t* OutputSize
)
{
printf("Output size: %p %ld\n", OutputSize, *OutputSize);
//
// Initialize the input buffer descriptor and history buffer (dictionary)
//
BfInitialize(InputBuffer, InputSize);
BfInitialize(InputBuffer, *InputSize ? *InputSize : UINT32_MAX);
DtInitialize(OutputBuffer, *OutputSize);
//
@ -498,11 +499,9 @@ XzDecode (
printf("block header failed\n");
return false;
case XzBlockHeaderNoBlock:
printf("no block\n");
*OutputSize = 0;
break;
case XzBlockHeaderSuccess:
printf("block ok\n");
//
// Decode the actual block
//
@ -530,6 +529,9 @@ XzDecode (
{
return false;
}
if (!*InputSize)
*InputSize = BfTell();
#endif
return true;
}

View file

@ -221,10 +221,11 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
break;
case P_XZDEC: {
u32 output_size = request->args[3];
if (XzDecode((void *)request->args[0], request->args[1], (void *)request->args[2],
&output_size))
reply->retval = output_size;
uint32_t destlen, srclen;
destlen = request->args[3];
srclen = request->args[1];
if (XzDecode((void *)request->args[0], &srclen, (void *)request->args[2], &destlen))
reply->retval = destlen;
else
reply->retval = ~0L;
break;
@ -234,7 +235,7 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
destlen = request->args[3];
srclen = request->args[1];
size_t ret = tinf_gzip_uncompress((void *)request->args[2], &destlen,
(void *)request->args[0], srclen);
(void *)request->args[0], &srclen);
if (ret != TINF_OK)
reply->retval = ret;
else

View file

@ -3,6 +3,8 @@
*
* Copyright (c) 2003-2019 Joergen Ibsen
*
* This version of tinfzlib was modified for use with m1n1.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
@ -77,7 +79,7 @@ void TINFCC tinf_init(void);
* @return `TINF_OK` on success, error code on error
*/
int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
const void *source, unsigned int *sourceLen);
/**
* Decompress `sourceLen` bytes of gzip data from `source` to `dest`.
@ -95,7 +97,7 @@ int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
* @return `TINF_OK` on success, error code on error
*/
int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
const void *source, unsigned int *sourceLen);
/**
* Decompress `sourceLen` bytes of zlib data from `source` to `dest`.
@ -113,7 +115,7 @@ int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
* @return `TINF_OK` on success, error code on error
*/
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
const void *source, unsigned int *sourceLen);
/**
* Compute Adler-32 checksum of `length` bytes starting at `data`.

View file

@ -3,6 +3,8 @@
*
* Copyright (c) 2003-2019 Joergen Ibsen
*
* This version of tinfzlib was modified for use with m1n1.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
@ -48,7 +50,7 @@ static unsigned int read_le32(const unsigned char *p)
}
int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
const void *source, unsigned int *sourceLen)
{
const unsigned char *src = (const unsigned char *) source;
unsigned char *dst = (unsigned char *) dest;
@ -56,11 +58,12 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
unsigned int dlen, crc32;
int res;
unsigned char flg;
unsigned int sourceDataLen = 0;
/* -- Check header -- */
/* Check room for at least 10 byte header and 8 byte trailer */
if (sourceLen < 18) {
if (*sourceLen && *sourceLen < 18) {
return TINF_DATA_ERROR;
}
@ -91,7 +94,7 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
if (flg & FEXTRA) {
unsigned int xlen = read_le16(start);
if (xlen > sourceLen - 12) {
if (*sourceLen && xlen > *sourceLen - 12) {
return TINF_DATA_ERROR;
}
@ -101,7 +104,7 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
/* Skip file name if present */
if (flg & FNAME) {
do {
if (start - src >= sourceLen) {
if (*sourceLen && start - src >= *sourceLen) {
return TINF_DATA_ERROR;
}
} while (*start++);
@ -110,7 +113,7 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
/* Skip file comment if present */
if (flg & FCOMMENT) {
do {
if (start - src >= sourceLen) {
if (*sourceLen && start - src >= *sourceLen) {
return TINF_DATA_ERROR;
}
} while (*start++);
@ -120,7 +123,7 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
if (flg & FHCRC) {
unsigned int hcrc;
if (start - src > sourceLen - 2) {
if (*sourceLen && start - src > *sourceLen - 2) {
return TINF_DATA_ERROR;
}
@ -133,37 +136,53 @@ int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
start += 2;
}
/* -- Get decompressed length -- */
/* -- Get decompressed length if available -- */
dlen = read_le32(&src[sourceLen - 4]);
if (*sourceLen) {
dlen = read_le32(&src[*sourceLen - 4]);
if (dlen > *destLen) {
return TINF_BUF_ERROR;
if (dlen > *destLen) {
return TINF_BUF_ERROR;
}
}
/* -- Get CRC32 checksum of original data -- */
/* -- Check source length if available -- */
crc32 = read_le32(&src[sourceLen - 8]);
if (*sourceLen) {
if ((src + *sourceLen) - start < 8) {
return TINF_DATA_ERROR;
}
sourceDataLen = (src + *sourceLen) - start - 8;
}
/* -- Decompress data -- */
if ((src + sourceLen) - start < 8) {
return TINF_DATA_ERROR;
}
res = tinf_uncompress(dst, destLen, start,
(src + sourceLen) - start - 8);
res = tinf_uncompress(dst, destLen, start, &sourceDataLen);
if (res != TINF_OK) {
return TINF_DATA_ERROR;
}
sourceDataLen += (start - src) + 8;
if (*sourceLen && *sourceLen != sourceDataLen) {
return TINF_DATA_ERROR;
}
*sourceLen = sourceDataLen;
/* -- Check decompressed length -- */
dlen = read_le32(&src[*sourceLen - 4]);
if (*destLen != dlen) {
return TINF_DATA_ERROR;
}
/* -- Check CRC32 checksum -- */
crc32 = read_le32(&src[*sourceLen - 8]);
if (crc32 != tinf_crc32(dst, dlen)) {
return TINF_DATA_ERROR;
}

View file

@ -3,6 +3,8 @@
*
* Copyright (c) 2003-2019 Joergen Ibsen
*
* This version of tinfzlib was modified for use with m1n1.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
@ -484,7 +486,7 @@ static int tinf_inflate_uncompressed_block(struct tinf_data *d)
{
unsigned int length, invlength;
if (d->source_end - d->source < 4) {
if (d->source_end && d->source_end - d->source < 4) {
return TINF_DATA_ERROR;
}
@ -501,7 +503,7 @@ static int tinf_inflate_uncompressed_block(struct tinf_data *d)
d->source += 4;
if (d->source_end - d->source < length) {
if (d->source_end && d->source_end - d->source < length) {
return TINF_DATA_ERROR;
}
@ -555,14 +557,17 @@ void tinf_init(void)
/* Inflate stream from source to dest */
int tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
const void *source, unsigned int *sourceLen)
{
struct tinf_data d;
int bfinal;
/* Initialise data */
d.source = (const unsigned char *) source;
d.source_end = d.source + sourceLen;
if (sourceLen && *sourceLen)
d.source_end = d.source + *sourceLen;
else
d.source_end = 0;
d.tag = 0;
d.bitcount = 0;
d.overflow = 0;
@ -610,8 +615,15 @@ int tinf_uncompress(void *dest, unsigned int *destLen,
return TINF_DATA_ERROR;
}
*destLen = d.dest - d.dest_start;
if (sourceLen) {
unsigned int slen = d.source - (const unsigned char *)source;
if (!*sourceLen)
*sourceLen = slen;
else if (*sourceLen != slen)
return TINF_DATA_ERROR;
}
*destLen = d.dest - d.dest_start;
return TINF_OK;
}

View file

@ -1,6 +1,8 @@
/*
* tinfzlib - tiny zlib decompressor
*
* This version of tinfzlib was modified for use with m1n1.
*
* Copyright (c) 2003-2019 Joergen Ibsen
*
* This software is provided 'as-is', without any express or implied
@ -34,18 +36,19 @@ static unsigned int read_be32(const unsigned char *p)
}
int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
const void *source, unsigned int *sourceLen)
{
const unsigned char *src = (const unsigned char *) source;
unsigned char *dst = (unsigned char *) dest;
unsigned int a32;
int res;
unsigned char cmf, flg;
unsigned int sourceDataLen = sourceLen ? *sourceLen - 6 : 0;
/* -- Check header -- */
/* Check room for at least 2 byte header and 4 byte trailer */
if (sourceLen < 6) {
if (*sourceLen && *sourceLen < 6) {
return TINF_DATA_ERROR;
}
@ -73,13 +76,9 @@ int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
return TINF_DATA_ERROR;
}
/* -- Get Adler-32 checksum of original data -- */
a32 = read_be32(&src[sourceLen - 4]);
/* -- Decompress data -- */
res = tinf_uncompress(dst, destLen, src + 2, sourceLen - 6);
res = tinf_uncompress(dst, destLen, src + 2, &sourceDataLen);
if (res != TINF_OK) {
return TINF_DATA_ERROR;
@ -87,9 +86,14 @@ int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
/* -- Check Adler-32 checksum -- */
a32 = read_be32(&src[sourceDataLen + 2]);
if (a32 != tinf_adler32(dst, *destLen)) {
return TINF_DATA_ERROR;
}
if (sourceLen)
*sourceLen = sourceDataLen + 6;
return TINF_OK;
}