mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-12-09 19:48:23 +00:00
184 lines
4.2 KiB
C
184 lines
4.2 KiB
C
#include "../spng/spng.h"
|
|
|
|
#include <string.h>
|
|
|
|
struct buf_state
|
|
{
|
|
const uint8_t *data;
|
|
size_t bytes_left;
|
|
};
|
|
|
|
static int stream_write_fn(spng_ctx *ctx, void *user, void *data, size_t length)
|
|
{
|
|
struct buf_state *state = (struct buf_state*)user;
|
|
(void)ctx;
|
|
|
|
if(length > state->bytes_left) return SPNG_IO_EOF;
|
|
|
|
state->bytes_left -= length;
|
|
|
|
if(state->data)
|
|
{
|
|
memcpy(data, state->data, length);
|
|
state->data += length;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define copy_val(val) \
|
|
if(size < sizeof(val)) goto err; \
|
|
memcpy(&val, data, sizeof(val)); \
|
|
data += sizeof(val); \
|
|
size -= sizeof(val)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
#endif
|
|
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|
{
|
|
uint8_t params[4];
|
|
|
|
if(size < sizeof(params)) return 0;
|
|
|
|
memcpy(params, data, sizeof(params));
|
|
|
|
size -= sizeof(params);
|
|
data += sizeof(params);
|
|
|
|
//int flags = params[0];
|
|
int fmt = params[2] | (params[1] << 8);
|
|
int stream = params[3] & 1;
|
|
int progressive = params[3] & 2;
|
|
//int file_stream = params[3] & 4;
|
|
int get_buffer = params[3] & 8;
|
|
|
|
int ret;
|
|
size_t png_size = 0;
|
|
void *png = NULL;
|
|
|
|
struct buf_state state;
|
|
unsigned char *img = NULL;
|
|
size_t img_size;
|
|
size_t pixel_bits = 0;
|
|
|
|
spng_ctx *ctx = spng_ctx_new(SPNG_CTX_ENCODER);
|
|
if(ctx == NULL) return 0;
|
|
|
|
spng_set_image_limits(ctx, 200000, 200000);
|
|
spng_set_chunk_limits(ctx, 4 * 1000 * 1000, 8 * 1000 * 1000);
|
|
|
|
state.data = NULL;
|
|
state.bytes_left = SIZE_MAX;
|
|
|
|
spng_set_option(ctx, SPNG_IMG_COMPRESSION_LEVEL, 0);
|
|
|
|
if(stream) ret = spng_set_png_stream(ctx, stream_write_fn, &state);
|
|
else ret = spng_set_option(ctx, SPNG_ENCODE_TO_BUFFER, 1);
|
|
|
|
if(ret) goto err;
|
|
|
|
struct spng_ihdr ihdr;
|
|
struct spng_plte plte;
|
|
struct spng_trns trns;
|
|
struct spng_chrm chrm;
|
|
struct spng_chrm_int chrm_int;
|
|
double gamma;
|
|
struct spng_sbit sbit;
|
|
uint8_t srgb_rendering_intent;
|
|
struct spng_bkgd bkgd;
|
|
struct spng_hist hist;
|
|
struct spng_phys phys;
|
|
struct spng_time time;
|
|
|
|
copy_val(ihdr);
|
|
copy_val(plte);
|
|
copy_val(trns);
|
|
copy_val(chrm);
|
|
copy_val(chrm_int);
|
|
copy_val(gamma);
|
|
copy_val(sbit);
|
|
copy_val(srgb_rendering_intent);
|
|
copy_val(bkgd);
|
|
copy_val(hist);
|
|
copy_val(phys);
|
|
copy_val(time);
|
|
|
|
if(spng_set_ihdr(ctx, &ihdr)) goto err;
|
|
|
|
spng_set_plte(ctx, &plte);
|
|
spng_set_trns(ctx, &trns);
|
|
spng_set_chrm(ctx, &chrm);
|
|
spng_set_chrm_int(ctx, &chrm_int);
|
|
spng_set_gama(ctx, gamma);
|
|
spng_set_sbit(ctx, &sbit);
|
|
spng_set_srgb(ctx, srgb_rendering_intent);
|
|
spng_set_bkgd(ctx, &bkgd);
|
|
spng_set_hist(ctx, &hist);
|
|
spng_set_phys(ctx, &phys);
|
|
spng_set_time(ctx, &time);
|
|
|
|
switch(ihdr.color_type)
|
|
{
|
|
case SPNG_COLOR_TYPE_GRAYSCALE:
|
|
case SPNG_COLOR_TYPE_INDEXED:
|
|
pixel_bits = ihdr.bit_depth;
|
|
break;
|
|
case SPNG_COLOR_TYPE_TRUECOLOR:
|
|
pixel_bits = ihdr.bit_depth * 3;
|
|
break;
|
|
case SPNG_COLOR_TYPE_GRAYSCALE_ALPHA:
|
|
pixel_bits = ihdr.bit_depth * 2;
|
|
break;
|
|
case SPNG_COLOR_TYPE_TRUECOLOR_ALPHA:
|
|
pixel_bits = ihdr.bit_depth * 4;
|
|
break;
|
|
default: goto err;
|
|
}
|
|
|
|
img_size = ihdr.width * pixel_bits + 7;
|
|
|
|
img_size /= 8;
|
|
|
|
img_size *= ihdr.height;
|
|
|
|
if(img_size > size) goto err;
|
|
|
|
if(img_size > 80000000) goto err;
|
|
|
|
img = (unsigned char*)data;
|
|
|
|
if(progressive)
|
|
{
|
|
if(spng_encode_image(ctx, NULL, 0, fmt, SPNG_ENCODE_PROGRESSIVE | SPNG_ENCODE_FINALIZE)) goto err;
|
|
|
|
size_t ioffset, img_width = img_size / ihdr.height;
|
|
struct spng_row_info ri;
|
|
|
|
do
|
|
{
|
|
if(spng_get_row_info(ctx, &ri)) break;
|
|
|
|
ioffset = ri.row_num * img_width;
|
|
|
|
}while(!spng_encode_row(ctx, img + ioffset, img_size));
|
|
}
|
|
else if(spng_encode_image(ctx, img, img_size, fmt, SPNG_ENCODE_FINALIZE)) goto err;
|
|
|
|
if(get_buffer)
|
|
{
|
|
png = spng_get_png_buffer(ctx, &png_size, &ret);
|
|
|
|
// These are potential vulnerabilities
|
|
if(png && !png_size) return 1;
|
|
if(!png && png_size) return 1;
|
|
if(ret && (png || png_size)) return 1;
|
|
}
|
|
|
|
err:
|
|
spng_ctx_free(ctx);
|
|
free(png);
|
|
|
|
return 0;
|
|
}
|