Home | History | Annotate | Download | only in libpng
      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