Home | History | Annotate | Download | only in libjpeg
      1 #ifdef __cplusplus
      2 extern "C" {
      3 #endif
      4 
      5 #include <fcntl.h>
      6 #include <setjmp.h>
      7 #include <stdint.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <sys/stat.h>
     11 #include <sys/types.h>
     12 #include <unistd.h>
     13 
     14 #include <libhfuzz/libhfuzz.h>
     15 
     16 #include "cderror.h"
     17 #include "jpeglib.h"
     18 
     19 struct jpeg_decompress_struct cinfo;
     20 int null_fd = -1;
     21 
     22 struct jpegErrorManager {
     23     struct jpeg_error_mgr pub;
     24     jmp_buf setjmp_buffer;
     25 };
     26 
     27 struct jpegErrorManager jerr;
     28 
     29 void jpegErrorExit(j_common_ptr cinfo)
     30 {
     31     struct jpegErrorManager* myerr = (struct jpegErrorManager*)cinfo->err;
     32     longjmp(myerr->setjmp_buffer, 1);
     33 }
     34 
     35 static const char* const cdjpeg_message_table[] = {
     36 #include "cderror.h"
     37     NULL
     38 };
     39 
     40 int LLVMFuzzerInitialize(int* argc, char*** argv)
     41 {
     42     null_fd = open("/dev/null", O_WRONLY);
     43 
     44     cinfo.err = jpeg_std_error(&jerr.pub);
     45     jerr.pub.error_exit = jpegErrorExit;
     46 
     47     jerr.pub.addon_message_table = cdjpeg_message_table;
     48     jerr.pub.first_addon_message = JMSG_FIRSTADDONCODE;
     49     jerr.pub.last_addon_message = JMSG_LASTADDONCODE;
     50 
     51     jpeg_create_decompress(&cinfo);
     52     return 0;
     53 }
     54 
     55 int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len)
     56 {
     57     if (setjmp(jerr.setjmp_buffer)) {
     58         goto out;
     59     }
     60 
     61     jpeg_mem_src(&cinfo, buf, len);
     62 
     63     if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
     64         goto out;
     65     }
     66 
     67     if (cinfo.output_height > 10000 || cinfo.output_width > 10000) {
     68         goto out;
     69     }
     70 
     71     cinfo.mem->max_memory_to_use = (1024 * 1024 * 1024);
     72     cinfo.mem->max_alloc_chunk = (1024 * 128 * 256);
     73 
     74     jpeg_start_decompress(&cinfo);
     75 
     76     int row_stride = cinfo.output_width * cinfo.output_components;
     77     JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
     78     while (cinfo.output_scanline < cinfo.output_height) {
     79 #if defined(__clang__)
     80 #if __has_feature(memory_sanitizer)
     81         __msan_poison(buffer[0], row_stride);
     82 #endif /* __has_feature(memory_sanitizer) */
     83 #endif /* defined(__clang__) */
     84         jpeg_read_scanlines(&cinfo, buffer, 1);
     85         write(null_fd, buffer[0], row_stride);
     86     }
     87 
     88 out:
     89     jpeg_abort_decompress(&cinfo);
     90     return 0;
     91 }
     92 
     93 #ifdef __cplusplus
     94 }
     95 #endif
     96