mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-11 13:32:14 -04:00
Make decompress API functions return a result code rather than a 'bool'
This commit is contained in:
parent
be419e24fa
commit
ee1535ecc1
63
libdeflate.h
63
libdeflate.h
@ -9,7 +9,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
@ -124,26 +123,56 @@ struct deflate_decompressor;
|
|||||||
extern struct deflate_decompressor *
|
extern struct deflate_decompressor *
|
||||||
deflate_alloc_decompressor(void);
|
deflate_alloc_decompressor(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Result of a call to deflate_decompress(), zlib_decompress(), or
|
||||||
|
* gzip_decompress().
|
||||||
|
*/
|
||||||
|
enum decompress_result {
|
||||||
|
/* Decompression was successful. */
|
||||||
|
DECOMPRESS_SUCCESS = 0,
|
||||||
|
|
||||||
|
/* Decompressed failed because the compressed data was invalid, corrupt,
|
||||||
|
* or otherwise unsupported. */
|
||||||
|
DECOMPRESS_BAD_DATA = 1,
|
||||||
|
|
||||||
|
/* A NULL 'actual_out_nbytes_ret' was provided, but the data would have
|
||||||
|
* decompressed to fewer than 'out_nbytes_avail' bytes. */
|
||||||
|
DECOMPRESS_SHORT_OUTPUT = 2,
|
||||||
|
|
||||||
|
/* The data would have decompressed to more than 'out_nbytes_avail'
|
||||||
|
* bytes. */
|
||||||
|
DECOMPRESS_INSUFFICIENT_SPACE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* deflate_decompress() decompresses 'in_nbytes' bytes of DEFLATE-compressed
|
* deflate_decompress() decompresses 'in_nbytes' bytes of DEFLATE-compressed
|
||||||
* data at 'in' and writes the uncompressed data to 'out', which is a buffer of
|
* data at 'in' and writes the uncompressed data to 'out', which is a buffer of
|
||||||
* at least 'out_nbytes_avail' bytes. If decompression was successful, then
|
* at least 'out_nbytes_avail' bytes. If decompression was successful, then 0
|
||||||
* true is returned; otherwise, false is returned.
|
* (DECOMPRESS_SUCCESS) is returned; otherwise, a nonzero result code such as
|
||||||
|
* DECOMPRESS_BAD_DATA is returned. If a nonzero result code is returned, then
|
||||||
|
* the contents of the output buffer are undefined.
|
||||||
*
|
*
|
||||||
* deflate_decompress() can be used in cases where the actual uncompressed size
|
* deflate_decompress() can be used in cases where the actual uncompressed size
|
||||||
* is known (recommended) or unknown (not recommended). If the actual
|
* is known (recommended) or unknown (not recommended):
|
||||||
* uncompressed size is known, then pass the actual uncompressed size as
|
*
|
||||||
* 'out_nbytes_avail' and pass NULL for 'actual_out_nbytes_ret'. This makes
|
* - If the actual uncompressed size is known, then pass the actual
|
||||||
* deflate_decompress() return false if the data did not decompress to exactly
|
* uncompressed size as 'out_nbytes_avail' and pass NULL for
|
||||||
* the specified number of bytes. Alternatively, if the actual uncompressed
|
* 'actual_out_nbytes_ret'. This makes deflate_decompress() fail with
|
||||||
* size is unknown, then provide a non-NULL 'actual_out_nbytes_ret' and provide
|
* DECOMPRESS_SHORT_OUTPUT if the data decompressed to fewer than the
|
||||||
* a buffer with some size 'out_nbytes_avail' that you think is large enough to
|
* specified number of bytes.
|
||||||
* hold all the uncompressed data. In this case, if the data decompresses to
|
*
|
||||||
* less than or equal to 'out_nbytes_avail' bytes, then deflate_decompress()
|
* - If the actual uncompressed size is unknown, then provide a non-NULL
|
||||||
* will write the actual uncompressed size to *actual_out_nbytes_ret and return
|
* 'actual_out_nbytes_ret' and provide a buffer with some size
|
||||||
* true. Otherwise, it will return false.
|
* 'out_nbytes_avail' that you think is large enough to hold all the
|
||||||
|
* uncompressed data. In this case, if the data decompresses to less than
|
||||||
|
* or equal to 'out_nbytes_avail' bytes, then deflate_decompress() will
|
||||||
|
* write the actual uncompressed size to *actual_out_nbytes_ret and return 0
|
||||||
|
* (DECOMPRESS_SUCCESS). Otherwise, it will return
|
||||||
|
* DECOMPRESS_INSUFFICIENT_SPACE if the provided buffer was not large enough
|
||||||
|
* but no other problems were encountered, or another nonzero result code if
|
||||||
|
* decompression failed for another reason.
|
||||||
*/
|
*/
|
||||||
extern bool
|
extern enum decompress_result
|
||||||
deflate_decompress(struct deflate_decompressor *decompressor,
|
deflate_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
@ -153,7 +182,7 @@ deflate_decompress(struct deflate_decompressor *decompressor,
|
|||||||
* Like deflate_decompress(), but assumes the zlib wrapper format instead of raw
|
* Like deflate_decompress(), but assumes the zlib wrapper format instead of raw
|
||||||
* DEFLATE.
|
* DEFLATE.
|
||||||
*/
|
*/
|
||||||
extern bool
|
extern enum decompress_result
|
||||||
zlib_decompress(struct deflate_decompressor *decompressor,
|
zlib_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
@ -163,7 +192,7 @@ zlib_decompress(struct deflate_decompressor *decompressor,
|
|||||||
* Like deflate_decompress(), but assumes the gzip wrapper format instead of raw
|
* Like deflate_decompress(), but assumes the gzip wrapper format instead of raw
|
||||||
* DEFLATE.
|
* DEFLATE.
|
||||||
*/
|
*/
|
||||||
extern bool
|
extern enum decompress_result
|
||||||
gzip_decompress(struct deflate_decompressor *decompressor,
|
gzip_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* sets.
|
* sets.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool ATTRIBUTES
|
static enum decompress_result ATTRIBUTES
|
||||||
FUNCNAME(struct deflate_decompressor * restrict d,
|
FUNCNAME(struct deflate_decompressor * restrict d,
|
||||||
const void * restrict in, size_t in_nbytes,
|
const void * restrict in, size_t in_nbytes,
|
||||||
void * restrict out, size_t out_nbytes_avail,
|
void * restrict out, size_t out_nbytes_avail,
|
||||||
@ -176,7 +176,8 @@ next_block:
|
|||||||
nlen = READ_U16();
|
nlen = READ_U16();
|
||||||
|
|
||||||
SAFETY_CHECK(len == (u16)~nlen);
|
SAFETY_CHECK(len == (u16)~nlen);
|
||||||
SAFETY_CHECK(len <= out_end - out_next);
|
if (unlikely(len > out_end - out_next))
|
||||||
|
return DECOMPRESS_INSUFFICIENT_SPACE;
|
||||||
SAFETY_CHECK(len <= in_end - in_next);
|
SAFETY_CHECK(len <= in_end - in_next);
|
||||||
|
|
||||||
memcpy(out_next, in_next, len);
|
memcpy(out_next, in_next, len);
|
||||||
@ -236,7 +237,8 @@ next_block:
|
|||||||
REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK);
|
REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK);
|
||||||
if (entry & HUFFDEC_LITERAL) {
|
if (entry & HUFFDEC_LITERAL) {
|
||||||
/* Literal */
|
/* Literal */
|
||||||
SAFETY_CHECK(out_next < out_end);
|
if (unlikely(out_next == out_end))
|
||||||
|
return DECOMPRESS_INSUFFICIENT_SPACE;
|
||||||
*out_next++ = (u8)(entry >> HUFFDEC_RESULT_SHIFT);
|
*out_next++ = (u8)(entry >> HUFFDEC_RESULT_SHIFT);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -258,7 +260,8 @@ next_block:
|
|||||||
* SIZE_MAX. */
|
* SIZE_MAX. */
|
||||||
STATIC_ASSERT(HUFFDEC_END_OF_BLOCK_LENGTH == 0);
|
STATIC_ASSERT(HUFFDEC_END_OF_BLOCK_LENGTH == 0);
|
||||||
if (unlikely((size_t)length - 1 > out_end - out_next)) {
|
if (unlikely((size_t)length - 1 > out_end - out_next)) {
|
||||||
SAFETY_CHECK(length == HUFFDEC_END_OF_BLOCK_LENGTH);
|
if (unlikely(length != HUFFDEC_END_OF_BLOCK_LENGTH))
|
||||||
|
return DECOMPRESS_INSUFFICIENT_SPACE;
|
||||||
goto block_done;
|
goto block_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,9 +364,11 @@ block_done:
|
|||||||
|
|
||||||
/* That was the last block. */
|
/* That was the last block. */
|
||||||
|
|
||||||
if (!actual_out_nbytes_ret)
|
if (actual_out_nbytes_ret) {
|
||||||
return out_next == out_end;
|
|
||||||
|
|
||||||
*actual_out_nbytes_ret = out_next - (u8 *)out;
|
*actual_out_nbytes_ret = out_next - (u8 *)out;
|
||||||
return true;
|
} else {
|
||||||
|
if (out_next != out_end)
|
||||||
|
return DECOMPRESS_SHORT_OUTPUT;
|
||||||
|
}
|
||||||
|
return DECOMPRESS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,15 @@
|
|||||||
#include "x86_cpu_features.h"
|
#include "x86_cpu_features.h"
|
||||||
|
|
||||||
/* By default, if the expression passed to SAFETY_CHECK() evaluates to false,
|
/* By default, if the expression passed to SAFETY_CHECK() evaluates to false,
|
||||||
* then deflate_decompress() immediately returns false as the compressed data is
|
* then deflate_decompress() immediately returns DECOMPRESS_BAD_DATA as the
|
||||||
* invalid. But if unsafe decompression is enabled, then the value of the
|
* compressed data is invalid. But if unsafe decompression is enabled, then the
|
||||||
* expression is ignored, allowing the compiler to optimize out some code. */
|
* value of the expression is ignored, allowing the compiler to optimize out
|
||||||
|
* some code. */
|
||||||
#if UNSAFE_DECOMPRESSION
|
#if UNSAFE_DECOMPRESSION
|
||||||
# warning "UNSAFE DECOMPRESSION IS ENABLED. THIS MUST ONLY BE USED IF THE DECOMPRESSOR INPUT WILL ALWAYS BE TRUSTED!"
|
# warning "UNSAFE DECOMPRESSION IS ENABLED. THIS MUST ONLY BE USED IF THE DECOMPRESSOR INPUT WILL ALWAYS BE TRUSTED!"
|
||||||
# define SAFETY_CHECK(expr) (void)(expr)
|
# define SAFETY_CHECK(expr) (void)(expr)
|
||||||
#else
|
#else
|
||||||
# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return false
|
# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return DECOMPRESS_BAD_DATA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -814,20 +815,21 @@ copy_word_unaligned(const void *src, void *dst)
|
|||||||
|
|
||||||
#if DISPATCH_ENABLED
|
#if DISPATCH_ENABLED
|
||||||
|
|
||||||
static bool
|
static enum decompress_result
|
||||||
dispatch(struct deflate_decompressor * restrict d,
|
dispatch(struct deflate_decompressor * restrict d,
|
||||||
const void * restrict in, size_t in_nbytes,
|
const void * restrict in, size_t in_nbytes,
|
||||||
void * restrict out, size_t out_nbytes_avail,
|
void * restrict out, size_t out_nbytes_avail,
|
||||||
size_t *actual_out_nbytes_ret);
|
size_t *actual_out_nbytes_ret);
|
||||||
|
|
||||||
typedef bool (*decompress_func_t)(struct deflate_decompressor * restrict d,
|
typedef enum decompress_result (*decompress_func_t)
|
||||||
|
(struct deflate_decompressor * restrict d,
|
||||||
const void * restrict in, size_t in_nbytes,
|
const void * restrict in, size_t in_nbytes,
|
||||||
void * restrict out, size_t out_nbytes_avail,
|
void * restrict out, size_t out_nbytes_avail,
|
||||||
size_t *actual_out_nbytes_ret);
|
size_t *actual_out_nbytes_ret);
|
||||||
|
|
||||||
static decompress_func_t decompress_impl = dispatch;
|
static decompress_func_t decompress_impl = dispatch;
|
||||||
|
|
||||||
static bool
|
static enum decompress_result
|
||||||
dispatch(struct deflate_decompressor * restrict d,
|
dispatch(struct deflate_decompressor * restrict d,
|
||||||
const void * restrict in, size_t in_nbytes,
|
const void * restrict in, size_t in_nbytes,
|
||||||
void * restrict out, size_t out_nbytes_avail,
|
void * restrict out, size_t out_nbytes_avail,
|
||||||
@ -853,7 +855,7 @@ dispatch(struct deflate_decompressor * restrict d,
|
|||||||
* calling the appropriate implementation depending on the CPU features at
|
* calling the appropriate implementation depending on the CPU features at
|
||||||
* runtime.
|
* runtime.
|
||||||
*/
|
*/
|
||||||
LIBEXPORT bool
|
LIBEXPORT enum decompress_result
|
||||||
deflate_decompress(struct deflate_decompressor * restrict d,
|
deflate_decompress(struct deflate_decompressor * restrict d,
|
||||||
const void * restrict in, size_t in_nbytes,
|
const void * restrict in, size_t in_nbytes,
|
||||||
void * restrict out, size_t out_nbytes_avail,
|
void * restrict out, size_t out_nbytes_avail,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "gzip_constants.h"
|
#include "gzip_constants.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
|
|
||||||
LIBEXPORT bool
|
LIBEXPORT enum decompress_result
|
||||||
gzip_decompress(struct deflate_decompressor *d,
|
gzip_decompress(struct deflate_decompressor *d,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
@ -24,19 +24,20 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
const u8 * const in_end = in_next + in_nbytes;
|
const u8 * const in_end = in_next + in_nbytes;
|
||||||
u8 flg;
|
u8 flg;
|
||||||
size_t actual_out_nbytes;
|
size_t actual_out_nbytes;
|
||||||
|
enum decompress_result result;
|
||||||
|
|
||||||
if (in_nbytes < GZIP_MIN_OVERHEAD)
|
if (in_nbytes < GZIP_MIN_OVERHEAD)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* ID1 */
|
/* ID1 */
|
||||||
if (*in_next++ != GZIP_ID1)
|
if (*in_next++ != GZIP_ID1)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
/* ID2 */
|
/* ID2 */
|
||||||
if (*in_next++ != GZIP_ID2)
|
if (*in_next++ != GZIP_ID2)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
/* CM */
|
/* CM */
|
||||||
if (*in_next++ != GZIP_CM_DEFLATE)
|
if (*in_next++ != GZIP_CM_DEFLATE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
flg = *in_next++;
|
flg = *in_next++;
|
||||||
/* MTIME */
|
/* MTIME */
|
||||||
in_next += 4;
|
in_next += 4;
|
||||||
@ -46,7 +47,7 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
in_next += 1;
|
in_next += 1;
|
||||||
|
|
||||||
if (flg & GZIP_FRESERVED)
|
if (flg & GZIP_FRESERVED)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* Extra field */
|
/* Extra field */
|
||||||
if (flg & GZIP_FEXTRA) {
|
if (flg & GZIP_FEXTRA) {
|
||||||
@ -54,7 +55,7 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
in_next += 2;
|
in_next += 2;
|
||||||
|
|
||||||
if (in_end - in_next < (u32)xlen + GZIP_FOOTER_SIZE)
|
if (in_end - in_next < (u32)xlen + GZIP_FOOTER_SIZE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
in_next += xlen;
|
in_next += xlen;
|
||||||
}
|
}
|
||||||
@ -64,7 +65,7 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
while (*in_next++ != 0 && in_next != in_end)
|
while (*in_next++ != 0 && in_next != in_end)
|
||||||
;
|
;
|
||||||
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* File comment (zero terminated) */
|
/* File comment (zero terminated) */
|
||||||
@ -72,20 +73,23 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
while (*in_next++ != 0 && in_next != in_end)
|
while (*in_next++ != 0 && in_next != in_end)
|
||||||
;
|
;
|
||||||
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CRC16 for gzip header */
|
/* CRC16 for gzip header */
|
||||||
if (flg & GZIP_FHCRC) {
|
if (flg & GZIP_FHCRC) {
|
||||||
in_next += 2;
|
in_next += 2;
|
||||||
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
if (in_end - in_next < GZIP_FOOTER_SIZE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compressed data */
|
/* Compressed data */
|
||||||
if (!deflate_decompress(d, in_next, in_end - GZIP_FOOTER_SIZE - in_next,
|
result = deflate_decompress(d, in_next,
|
||||||
out, out_nbytes_avail, actual_out_nbytes_ret))
|
in_end - GZIP_FOOTER_SIZE - in_next,
|
||||||
return false;
|
out, out_nbytes_avail,
|
||||||
|
actual_out_nbytes_ret);
|
||||||
|
if (result != DECOMPRESS_SUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
if (actual_out_nbytes_ret)
|
if (actual_out_nbytes_ret)
|
||||||
actual_out_nbytes = *actual_out_nbytes_ret;
|
actual_out_nbytes = *actual_out_nbytes_ret;
|
||||||
@ -96,12 +100,12 @@ gzip_decompress(struct deflate_decompressor *d,
|
|||||||
|
|
||||||
/* CRC32 */
|
/* CRC32 */
|
||||||
if (crc32_gzip(out, actual_out_nbytes) != get_unaligned_le32(in_next))
|
if (crc32_gzip(out, actual_out_nbytes) != get_unaligned_le32(in_next))
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
in_next += 4;
|
in_next += 4;
|
||||||
|
|
||||||
/* ISIZE */
|
/* ISIZE */
|
||||||
if ((u32)actual_out_nbytes != get_unaligned_le32(in_next))
|
if ((u32)actual_out_nbytes != get_unaligned_le32(in_next))
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
return true;
|
return DECOMPRESS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
#include "zlib_constants.h"
|
#include "zlib_constants.h"
|
||||||
|
|
||||||
LIBEXPORT bool
|
LIBEXPORT enum decompress_result
|
||||||
zlib_decompress(struct deflate_decompressor *d,
|
zlib_decompress(struct deflate_decompressor *d,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
@ -24,9 +24,10 @@ zlib_decompress(struct deflate_decompressor *d,
|
|||||||
const u8 * const in_end = in_next + in_nbytes;
|
const u8 * const in_end = in_next + in_nbytes;
|
||||||
u16 hdr;
|
u16 hdr;
|
||||||
size_t actual_out_nbytes;
|
size_t actual_out_nbytes;
|
||||||
|
enum decompress_result result;
|
||||||
|
|
||||||
if (in_nbytes < ZLIB_MIN_OVERHEAD)
|
if (in_nbytes < ZLIB_MIN_OVERHEAD)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* 2 byte header: CMF and FLG */
|
/* 2 byte header: CMF and FLG */
|
||||||
hdr = get_unaligned_be16(in_next);
|
hdr = get_unaligned_be16(in_next);
|
||||||
@ -34,24 +35,27 @@ zlib_decompress(struct deflate_decompressor *d,
|
|||||||
|
|
||||||
/* FCHECK */
|
/* FCHECK */
|
||||||
if ((hdr % 31) != 0)
|
if ((hdr % 31) != 0)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* CM */
|
/* CM */
|
||||||
if (((hdr >> 8) & 0xF) != ZLIB_CM_DEFLATE)
|
if (((hdr >> 8) & 0xF) != ZLIB_CM_DEFLATE)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* CINFO */
|
/* CINFO */
|
||||||
if ((hdr >> 12) > ZLIB_CINFO_32K_WINDOW)
|
if ((hdr >> 12) > ZLIB_CINFO_32K_WINDOW)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* FDICT */
|
/* FDICT */
|
||||||
if ((hdr >> 5) & 1)
|
if ((hdr >> 5) & 1)
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
/* Compressed data */
|
/* Compressed data */
|
||||||
if (!deflate_decompress(d, in_next, in_end - ZLIB_FOOTER_SIZE - in_next,
|
result = deflate_decompress(d, in_next,
|
||||||
out, out_nbytes_avail, actual_out_nbytes_ret))
|
in_end - ZLIB_FOOTER_SIZE - in_next,
|
||||||
return false;
|
out, out_nbytes_avail,
|
||||||
|
actual_out_nbytes_ret);
|
||||||
|
if (result != DECOMPRESS_SUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
if (actual_out_nbytes_ret)
|
if (actual_out_nbytes_ret)
|
||||||
actual_out_nbytes = *actual_out_nbytes_ret;
|
actual_out_nbytes = *actual_out_nbytes_ret;
|
||||||
@ -62,7 +66,7 @@ zlib_decompress(struct deflate_decompressor *d,
|
|||||||
|
|
||||||
/* ADLER32 */
|
/* ADLER32 */
|
||||||
if (adler32(out, actual_out_nbytes) != get_unaligned_be32(in_next))
|
if (adler32(out, actual_out_nbytes) != get_unaligned_be32(in_next))
|
||||||
return false;
|
return DECOMPRESS_BAD_DATA;
|
||||||
|
|
||||||
return true;
|
return DECOMPRESS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#undef _ANSI_SOURCE
|
#undef _ANSI_SOURCE
|
||||||
#define _POSIX_C_SOURCE 199309L
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -181,14 +182,13 @@ compressor_destroy(struct compressor *c)
|
|||||||
|
|
||||||
struct decompressor {
|
struct decompressor {
|
||||||
void *private;
|
void *private;
|
||||||
bool (*decompress)(void *, const void *, size_t, void *, size_t, size_t *);
|
bool (*decompress)(void *, const void *, size_t, void *, size_t);
|
||||||
void (*free_private)(void *);
|
void (*free_private)(void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
libz_decompress(void *private, const void *in, size_t in_nbytes,
|
libz_decompress(void *private, const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail)
|
||||||
size_t *actual_out_nbytes_ret)
|
|
||||||
{
|
{
|
||||||
z_stream *z = private;
|
z_stream *z = private;
|
||||||
|
|
||||||
@ -209,6 +209,36 @@ libz_free_decompressor_private(void *private)
|
|||||||
free(private);
|
free(private);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
libdeflate_deflate_decompress(void *private, const void *in, size_t in_nbytes,
|
||||||
|
void *out, size_t out_nbytes_avail)
|
||||||
|
{
|
||||||
|
return 0 == deflate_decompress(private, in, in_nbytes,
|
||||||
|
out, out_nbytes_avail, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
libdeflate_zlib_decompress(void *private, const void *in, size_t in_nbytes,
|
||||||
|
void *out, size_t out_nbytes_avail)
|
||||||
|
{
|
||||||
|
return 0 == zlib_decompress(private, in, in_nbytes,
|
||||||
|
out, out_nbytes_avail, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
libdeflate_gzip_decompress(void *private, const void *in, size_t in_nbytes,
|
||||||
|
void *out, size_t out_nbytes_avail)
|
||||||
|
{
|
||||||
|
return 0 == gzip_decompress(private, in, in_nbytes,
|
||||||
|
out, out_nbytes_avail, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libdeflate_free_decompressor_private(void *private)
|
||||||
|
{
|
||||||
|
deflate_free_decompressor(private);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decompressor_init(struct decompressor *d, enum wrapper wrapper, bool use_libz)
|
decompressor_init(struct decompressor *d, enum wrapper wrapper, bool use_libz)
|
||||||
{
|
{
|
||||||
@ -236,16 +266,16 @@ decompressor_init(struct decompressor *d, enum wrapper wrapper, bool use_libz)
|
|||||||
ASSERT(d->private != NULL, "out of memory");
|
ASSERT(d->private != NULL, "out of memory");
|
||||||
switch (wrapper) {
|
switch (wrapper) {
|
||||||
case NO_WRAPPER:
|
case NO_WRAPPER:
|
||||||
d->decompress = (void *)deflate_decompress;
|
d->decompress = libdeflate_deflate_decompress;
|
||||||
break;
|
break;
|
||||||
case ZLIB_WRAPPER:
|
case ZLIB_WRAPPER:
|
||||||
d->decompress = (void *)zlib_decompress;
|
d->decompress = libdeflate_zlib_decompress;
|
||||||
break;
|
break;
|
||||||
case GZIP_WRAPPER:
|
case GZIP_WRAPPER:
|
||||||
d->decompress = (void *)gzip_decompress;
|
d->decompress = libdeflate_gzip_decompress;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
d->free_private = (void *)deflate_free_decompressor;
|
d->free_private = libdeflate_free_decompressor_private;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +284,7 @@ do_decompress(struct decompressor *d, const void *in, size_t in_nbytes,
|
|||||||
void *out, size_t out_nbytes_avail)
|
void *out, size_t out_nbytes_avail)
|
||||||
{
|
{
|
||||||
return (*d->decompress)(d->private, in, in_nbytes,
|
return (*d->decompress)(d->private, in, in_nbytes,
|
||||||
out, out_nbytes_avail, NULL);
|
out, out_nbytes_avail);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user