#ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include "cderror.h" #include "jpeglib.h" struct jpeg_decompress_struct cinfo; int null_fd = -1; struct jpegErrorManager { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; }; struct jpegErrorManager jerr; void jpegErrorExit(j_common_ptr cinfo) { struct jpegErrorManager* myerr = (struct jpegErrorManager*)cinfo->err; longjmp(myerr->setjmp_buffer, 1); } static const char* const cdjpeg_message_table[] = { #include "cderror.h" NULL}; static uint64_t max_hv_size = 10000; int LLVMFuzzerInitialize(int* argc, char*** argv) { null_fd = open("/dev/null", O_WRONLY); cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpegErrorExit; jerr.pub.addon_message_table = cdjpeg_message_table; jerr.pub.first_addon_message = JMSG_FIRSTADDONCODE; jerr.pub.last_addon_message = JMSG_LASTADDONCODE; jpeg_create_decompress(&cinfo); /* If there are any arguments provided, limit width and height to this value */ if (*argc > 1) { max_hv_size = strtoull((*argv)[1], NULL, 0); } return 0; } int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len) { if (setjmp(jerr.setjmp_buffer)) { goto out; } jpeg_mem_src(&cinfo, buf, len); jpeg_read_header(&cinfo, TRUE); /* Make sure the picture's resultion is reasonable */ if ((uint64_t)cinfo.output_height > max_hv_size) { goto out; } if ((uint64_t)cinfo.output_width > max_hv_size) { goto out; } cinfo.mem->max_memory_to_use = (1024ULL * 1024ULL * 1024ULL); cinfo.mem->max_alloc_chunk = (1024ULL * 1024ULL * 1024ULL); jpeg_start_decompress(&cinfo); int row_stride = cinfo.output_width * cinfo.output_components; JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1); while (cinfo.output_scanline < cinfo.output_height) { #if defined(__clang__) #if __has_feature(memory_sanitizer) __msan_poison(buffer[0], row_stride); #endif /* __has_feature(memory_sanitizer) */ #endif /* defined(__clang__) */ jpeg_read_scanlines(&cinfo, buffer, 1); write(null_fd, buffer[0], row_stride); } out: jpeg_abort_decompress(&cinfo); return 0; } #ifdef __cplusplus } #endif