• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
jpegErrorExit(j_common_ptr cinfo)29 void jpegErrorExit(j_common_ptr cinfo) {
30     struct jpegErrorManager* myerr = (struct jpegErrorManager*)cinfo->err;
31     longjmp(myerr->setjmp_buffer, 1);
32 }
33 
34 static const char* const cdjpeg_message_table[] = {
35 #include "cderror.h"
36     NULL};
37 
38 static uint64_t max_total_pixels = 1000000000ULL; /* 1G */
LLVMFuzzerInitialize(int * argc,char *** argv)39 int LLVMFuzzerInitialize(int* argc, char*** argv) {
40     null_fd = open("/dev/null", O_WRONLY);
41 
42     cinfo.err = jpeg_std_error(&jerr.pub);
43     jerr.pub.error_exit = jpegErrorExit;
44 
45     jerr.pub.addon_message_table = cdjpeg_message_table;
46     jerr.pub.first_addon_message = JMSG_FIRSTADDONCODE;
47     jerr.pub.last_addon_message = JMSG_LASTADDONCODE;
48 
49     jpeg_create_decompress(&cinfo);
50 
51     /* If there are any arguments provided, limit width*height to this value */
52     if (*argc > 1) {
53         max_total_pixels = strtoull((*argv)[1], NULL, 0);
54     }
55     return 0;
56 }
57 
LLVMFuzzerTestOneInput(const uint8_t * buf,size_t len)58 int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len) {
59     if (setjmp(jerr.setjmp_buffer)) {
60         goto out;
61     }
62 
63     jpeg_mem_src(&cinfo, buf, len);
64     jpeg_read_header(&cinfo, TRUE);
65 
66     /* Limit total number of pixels to decode to 50M */
67     uint64_t total_pix = (uint64_t)cinfo.output_height * (uint64_t)cinfo.output_width;
68     if (total_pix > max_total_pixels) {
69         goto out;
70     }
71 
72     cinfo.mem->max_memory_to_use = (1024ULL * 1024ULL * 1024ULL);
73     cinfo.mem->max_alloc_chunk = (1024ULL * 1024ULL * 1024ULL);
74 
75     jpeg_start_decompress(&cinfo);
76 
77     int row_stride = cinfo.output_width * cinfo.output_components;
78     JSAMPARRAY buffer =
79         (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
80     while (cinfo.output_scanline < cinfo.output_height) {
81 #if defined(__clang__)
82 #if __has_feature(memory_sanitizer)
83         __msan_poison(buffer[0], row_stride);
84 #endif /* __has_feature(memory_sanitizer) */
85 #endif /* defined(__clang__) */
86         jpeg_read_scanlines(&cinfo, buffer, 1);
87         write(null_fd, buffer[0], row_stride);
88     }
89 
90 out:
91     jpeg_abort_decompress(&cinfo);
92     return 0;
93 }
94 
95 #ifdef __cplusplus
96 }
97 #endif
98