mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 01:34:12 +00:00
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:
parent
0cd328214c
commit
61e2c36ef5
9 changed files with 95 additions and 45 deletions
|
@ -102,6 +102,14 @@ BfSeek (
|
|||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
BfTell (
|
||||
void
|
||||
)
|
||||
{
|
||||
return In.Offset;
|
||||
}
|
||||
|
||||
bool
|
||||
BfRead (
|
||||
uint8_t* Byte
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
11
src/proxy.c
11
src/proxy.c
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue