From 5a35ec74c9b547756fc643ca5832e22a0efefc4b Mon Sep 17 00:00:00 2001 From: Eugene Kliuchnikov Date: Thu, 7 Dec 2023 20:29:02 +0100 Subject: [PATCH] Do not store buffers on stack (#11330) Drive-by: reformat and use more clear variable names --- projects/lzo/lzo_compress_target.c | 137 +++++++++++++++------------ projects/lzo/lzo_decompress_target.c | 113 +++++++++++----------- 2 files changed, 131 insertions(+), 119 deletions(-) diff --git a/projects/lzo/lzo_compress_target.c b/projects/lzo/lzo_compress_target.c index c258975d6..19d3de5f0 100644 --- a/projects/lzo/lzo_compress_target.c +++ b/projects/lzo/lzo_compress_target.c @@ -16,78 +16,93 @@ ################################################################################ */ +#include +#include +#include #include #include -#include -#include -#include + #include "lzo1x.h" +#include "lzoconf.h" /* Work-memory needed for compression. Allocate memory in units * of 'lzo_align_t' (instead of 'char') to make sure it is properly aligned. */ -#define HEAP_ALLOC(var,size) \ - lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] +#define HEAP_ALLOC(var, size) \ + lzo_align_t __LZO_MMODEL \ + var[((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)] static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); -extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - int r; - lzo_uint out_len; - lzo_uint new_len; +extern int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + int r; + lzo_uint compressed_len; + lzo_uint decompressed_len; - /* Since we allocate in/out on the stack, - * we can't handle too large size. - */ - if (size > (1 << 20)) - size = 1 << 20; + /* Since we allocate in/out on the stack, + * we can't handle too large size. + */ + if (size > (1 << 20)) { + size = 1 << 20; + } - /* We want to compress the data block at 'in' with length 'IN_LEN' to - * the block at 'out'. Because the input block may be incompressible, - * we must provide a little more output space in case that compression - * is not possible. - */ - unsigned char __LZO_MMODEL in[size > 0 ? size : 1]; - unsigned char __LZO_MMODEL out[size + size/16 + 64 + 3]; - - static bool isInit = false; - if (!isInit) - { - if (lzo_init() != LZO_E_OK) - { -#ifdef __DEBUG__ - printf("internal error - lzo_init() failed !!!\n"); -#endif - return 0; - } - isInit = true; - } - - /* Compress with LZO1X-1. */ - r = lzo1x_1_compress(data, size, out, &out_len, wrkmem); - assert(r == LZO_E_OK); -#ifdef __DEBUG__ - printf("compressed %lu bytes into %lu bytes\n", - (unsigned long) size, (unsigned long) out_len); -#endif - - /* check for an incompressible block */ - if (out_len >= size) - { -#ifdef __DEBUG__ - printf("This block contains incompressible data.\n"); -#endif - return 0; - } - - // Decompress - new_len = size; - r = lzo1x_decompress(out, out_len, in, &new_len,/*wrkmem=*/NULL); - assert(r == LZO_E_OK && new_len == size); -#ifdef __DEBUG__ - printf("decompressed %lu bytes back into %lu bytes\n", - (unsigned long) out_len, (unsigned long) size); -#endif + /* We want to compress the data block at 'in' with length 'IN_LEN' to + * the block at 'out'. Because the input block may be incompressible, + * we must provide a little more output space in case that compression + * is not possible. + */ + unsigned char* __LZO_MMODEL decompressed = malloc(size + 1); + if (!decompressed) { return 0; + } + unsigned char* __LZO_MMODEL compressed = malloc(size + size / 16 + 64 + 3); + if (!compressed) { + free(decompressed); + return 0; + } + + static bool isInit = false; + if (!isInit) { + if (lzo_init() != LZO_E_OK) { +#ifdef __DEBUG__ + printf("internal error - lzo_init() failed !!!\n"); +#endif + free(compressed); + free(decompressed); + return 0; + } + isInit = true; + } + + /* Compress with LZO1X-1. */ + r = lzo1x_1_compress(data, size, compressed, &compressed_len, wrkmem); + assert(r == LZO_E_OK); +#ifdef __DEBUG__ + printf("compressed %lu bytes into %lu bytes\n", (unsigned long)size, + (unsigned long)out_len); +#endif + + /* check for an incompressible block */ + if (compressed_len >= size) { +#ifdef __DEBUG__ + printf("This block contains incompressible data.\n"); +#endif + free(compressed); + free(decompressed); + return 0; + } + + // Decompress; allow 1 extra byte of output to make sure decoder does not + // produce unexpected output. + decompressed_len = size + 1; + r = lzo1x_decompress(compressed, compressed_len, decompressed, + &decompressed_len, /*wrkmem=*/NULL); + assert(r == LZO_E_OK && decompressed_len == size); +#ifdef __DEBUG__ + printf("decompressed %lu bytes back into %lu bytes\n", (unsigned long)out_len, + (unsigned long)size); +#endif + free(compressed); + free(decompressed); + return 0; } diff --git a/projects/lzo/lzo_decompress_target.c b/projects/lzo/lzo_decompress_target.c index 5b742c1ca..b133835a1 100644 --- a/projects/lzo/lzo_decompress_target.c +++ b/projects/lzo/lzo_decompress_target.c @@ -16,11 +16,12 @@ ################################################################################ */ +#include +#include +#include #include #include -#include -#include -#include + #include "lzo1b.h" #include "lzo1c.h" #include "lzo1f.h" @@ -28,68 +29,64 @@ #include "lzo1y.h" #include "lzo1z.h" #include "lzo2a.h" +#include "lzoconf.h" -typedef int (*decompress_function)( const lzo_bytep, lzo_uint , - lzo_bytep, lzo_uintp, - lzo_voidp ); +typedef int (*decompress_function)(const lzo_bytep, lzo_uint, lzo_bytep, + lzo_uintp, lzo_voidp); -#define NUM_DECOMP 7 +#define NUM_DECOMP 7 -static decompress_function funcArr[NUM_DECOMP] = -{ - &lzo1b_decompress_safe, - &lzo1c_decompress_safe, - &lzo1f_decompress_safe, - &lzo1x_decompress_safe, - &lzo1y_decompress_safe, - &lzo1z_decompress_safe, - &lzo2a_decompress_safe -}; +static decompress_function funcArr[NUM_DECOMP] = { + &lzo1b_decompress_safe, &lzo1c_decompress_safe, &lzo1f_decompress_safe, + &lzo1x_decompress_safe, &lzo1y_decompress_safe, &lzo1z_decompress_safe, + &lzo2a_decompress_safe}; /* lzo (de)compresses data in blocks. Block size is the * size of one such block. This size has a default value of 256KB. */ -static const size_t bufSize = 256 * 1024L; +static const size_t kBufSize = 256 * 1024L; -extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - int r; - lzo_uint new_len; - if (size < 1){ - return 0; - } - /* Buffer into which compressed data provided by the fuzzer - * is going to be decompressed. The buffer size is chosen - * to be equal to the default block size (256KB) for - * (de)compression. - */ - unsigned char __LZO_MMODEL out[bufSize]; - - static bool isInit = false; - if (!isInit) - { - if (lzo_init() != LZO_E_OK) - { -#ifdef __DEBUG__ - printf("internal error - lzo_init() failed !!!\n"); -#endif - return 0; - } - isInit = true; - } - - // Decompress. - int idx = size % NUM_DECOMP; - new_len = bufSize; - // Work memory not necessary for decompression - r = (*funcArr[idx])(data, size, out, &new_len, /*wrkmem=*/NULL); -#ifdef __DEBUG__ - if (r != LZO_E_OK) - { - printf("error thrown by lzo1x_decompress_safe: %d\n", r); - } - printf("decompressed %lu bytes back into %lu bytes\n", - (unsigned long) size, (unsigned long) new_len); -#endif +extern int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + int r; + lzo_uint new_len; + if (size < 1) { return 0; + } + /* Buffer into which compressed data provided by the fuzzer + * is going to be decompressed. The buffer size is chosen + * to be equal to the default block size (256KB) for + * (de)compression. + */ + unsigned char* __LZO_MMODEL buf = malloc(kBufSize); + if (!buf) { + // OOM here is out of scope. + return 0; + } + + static bool isInit = false; + if (!isInit) { + if (lzo_init() != LZO_E_OK) { +#ifdef __DEBUG__ + printf("internal error - lzo_init() failed !!!\n"); +#endif + free(buf); + return 0; + } + isInit = true; + } + + // Decompress. + int idx = size % NUM_DECOMP; + new_len = kBufSize; + // Work memory not necessary for decompression + r = (*funcArr[idx])(data, size, buf, &new_len, /*wrkmem=*/NULL); +#ifdef __DEBUG__ + if (r != LZO_E_OK) { + printf("error thrown by lzo1x_decompress_safe: %d\n", r); + } + printf("decompressed %lu bytes back into %lu bytes\n", (unsigned long)size, + (unsigned long)new_len); +#endif + free(buf); + return 0; }