1 #ifdef __cplusplus 2 extern "C" { 3 #endif 4 5 #include <fcntl.h> 6 #include <inttypes.h> 7 #include <stdarg.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <sys/stat.h> 12 #include <sys/types.h> 13 #include <unistd.h> 14 15 #include <libhfuzz/libhfuzz.h> 16 17 #include "png.h" 18 #include "pngpriv.h" 19 #include "pngstruct.h" 20 21 #if defined(__clang__) 22 #if __has_feature(memory_sanitizer) 23 #include <sanitizer/msan_interface.h> 24 #endif /* __has_feature(memory_sanitizer) */ 25 #endif /* defined(__clang__) */ 26 27 void fatal(const char* s, ...) 28 { 29 va_list args; 30 va_start(args, s); 31 vfprintf(stderr, s, args); 32 fprintf(stderr, "\n"); 33 va_end(args); 34 _exit(EXIT_FAILURE); 35 } 36 37 typedef struct { 38 const uint8_t* ptr; 39 size_t len; 40 size_t off; 41 } user_file_t; 42 43 size_t total_alloc = 0ULL; 44 int null_fd = -1; 45 46 void png_user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) 47 { 48 #if defined(__clang__) 49 #if __has_feature(memory_sanitizer) 50 __msan_poison(data, length); 51 #endif /* __has_feature(memory_sanitizer) */ 52 #endif /* defined(__clang__) */ 53 54 user_file_t* f = (user_file_t*)png_ptr->io_ptr; 55 56 if (length > f->len) { 57 png_error(png_ptr, "Read Error"); 58 return; 59 } 60 memcpy(data, &f->ptr[f->off], length); 61 f->len -= length; 62 f->off += length; 63 } 64 65 int LLVMFuzzerInitialize(int* argc, char*** argv) 66 { 67 null_fd = open("/dev/null", O_WRONLY); 68 return 0; 69 } 70 71 int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len) 72 { 73 png_structp png_ptr = NULL; 74 png_infop info_ptr = NULL; 75 76 total_alloc = 0ULL; 77 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 78 if (!png_ptr) { 79 fatal("png_create_read_struct"); 80 } 81 82 info_ptr = png_create_info_struct(png_ptr); 83 if (!info_ptr) { 84 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); 85 fatal("png_create_info_struct()"); 86 } 87 88 if (setjmp(png_jmpbuf(png_ptr))) { 89 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 90 return 0; 91 } 92 93 png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); 94 png_set_user_limits(png_ptr, 10000U, 10000U); 95 png_set_chunk_cache_max(png_ptr, 1024ULL * 1024ULL * 64ULL); 96 png_set_chunk_malloc_max(png_ptr, 1024ULL * 1024ULL * 128ULL); 97 98 user_file_t f = { 99 .ptr = buf, 100 .len = len, 101 .off = 0UL, 102 }; 103 png_set_read_fn(png_ptr, (void*)&f, png_user_read_data); 104 105 png_read_png(png_ptr, info_ptr, ~(0), NULL); 106 107 png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); 108 png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr); 109 png_uint_32 height = png_get_image_height(png_ptr, info_ptr); 110 111 for (png_uint_32 i = 0; i < height; i++) { 112 write(null_fd, row_pointers[i], row_bytes); 113 } 114 115 /* Addtional API calls */ 116 png_uint_32 width, ret, res_x, res_y; 117 double file_gamma; 118 png_uint_16p hist; 119 int bit_depth, color_type, interlace_method, compression_method, filter_method, unit_type, num_palette, num_text; 120 png_textp text_ptr; 121 png_colorp palette; 122 png_timep mod_time; 123 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, 124 &compression_method, &filter_method); 125 ret = png_get_gAMA(png_ptr, info_ptr, &file_gamma); 126 ret = png_get_hIST(png_ptr, info_ptr, &hist); 127 ret = png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type); 128 ret = png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); 129 ret = png_get_text(png_ptr, info_ptr, &text_ptr, &num_text); 130 ret = png_get_tIME(png_ptr, info_ptr, &mod_time); 131 png_voidp vp = png_get_progressive_ptr(png_ptr); 132 133 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 134 135 return 0; 136 } 137 138 #ifdef __cplusplus 139 } 140 #endif 141