blob: 1a8411a8381a02059110591485b02f28daf71f50 [file] [log] [blame]
#ifdef __cplusplus
extern "C" {
#endif
#include <fcntl.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libhfuzz/libhfuzz.h>
#include "png.h"
#include "pngpriv.h"
#include "pngstruct.h"
#if defined(__clang__)
#if __has_feature(memory_sanitizer)
#include <sanitizer/msan_interface.h>
#endif /* __has_feature(memory_sanitizer) */
#endif /* defined(__clang__) */
void fatal(const char* s, ...)
{
va_list args;
va_start(args, s);
vfprintf(stderr, s, args);
fprintf(stderr, "\n");
va_end(args);
_exit(EXIT_FAILURE);
}
typedef struct {
const uint8_t* ptr;
size_t len;
size_t off;
} user_file_t;
size_t total_alloc = 0ULL;
int null_fd = -1;
void png_user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
#if defined(__clang__)
#if __has_feature(memory_sanitizer)
__msan_poison(data, length);
#endif /* __has_feature(memory_sanitizer) */
#endif /* defined(__clang__) */
user_file_t* f = (user_file_t*)png_ptr->io_ptr;
if (length > f->len) {
png_error(png_ptr, "Read Error");
return;
}
memcpy(data, &f->ptr[f->off], length);
f->len -= length;
f->off += length;
}
int LLVMFuzzerInitialize(int* argc, char*** argv)
{
null_fd = open("/dev/null", O_WRONLY);
return 0;
}
int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len)
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
total_alloc = 0ULL;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fatal("png_create_read_struct");
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
fatal("png_create_info_struct()");
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 0;
}
png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
png_set_user_limits(png_ptr, 10000U, 10000U);
png_set_chunk_cache_max(png_ptr, 1024ULL * 1024ULL * 64ULL);
png_set_chunk_malloc_max(png_ptr, 1024ULL * 1024ULL * 128ULL);
user_file_t f = {
.ptr = buf,
.len = len,
.off = 0UL,
};
png_set_read_fn(png_ptr, (void*)&f, png_user_read_data);
png_read_png(png_ptr, info_ptr, ~(0), NULL);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr);
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
for (png_uint_32 i = 0; i < height; i++) {
write(null_fd, row_pointers[i], row_bytes);
}
/* Addtional API calls */
png_uint_32 width, ret, res_x, res_y;
double file_gamma;
png_uint_16p hist;
int bit_depth, color_type, interlace_method, compression_method, filter_method, unit_type, num_palette, num_text;
png_textp text_ptr;
png_colorp palette;
png_timep mod_time;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method,
&compression_method, &filter_method);
ret = png_get_gAMA(png_ptr, info_ptr, &file_gamma);
ret = png_get_hIST(png_ptr, info_ptr, &hist);
ret = png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);
ret = png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
ret = png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
ret = png_get_tIME(png_ptr, info_ptr, &mod_time);
png_voidp vp = png_get_progressive_ptr(png_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 0;
}
#ifdef __cplusplus
}
#endif