1 /*
2 # Copyright 2018 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 ################################################################################
17 */
18
19 #include <cstdint>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23
24 #include "jbig2.h"
25
26 #define ALIGNMENT ((size_t) 16)
27 #define KBYTE ((size_t) 1024)
28 #define MBYTE (1024 * KBYTE)
29 #define GBYTE (1024 * MBYTE)
30 #define MAX_ALLOCATION (1 * GBYTE)
31
32 static size_t used;
33
jbig2_fuzzer_reached_limit(size_t oldsize,size_t size)34 static void *jbig2_fuzzer_reached_limit(size_t oldsize, size_t size)
35 {
36 if (oldsize == 0)
37 fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte allocation: %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, size);
38 else
39 fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte reallocation: %zu -> %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, oldsize, size);
40 fflush(0);
41 return NULL;
42 }
43
jbig2_fuzzer_alloc(Jbig2Allocator * allocator,size_t size)44 static void *jbig2_fuzzer_alloc(Jbig2Allocator *allocator, size_t size)
45 {
46 char *ptr = NULL;
47
48 if (size == 0)
49 return NULL;
50 if (size > SIZE_MAX - ALIGNMENT)
51 return NULL;
52 if (size + ALIGNMENT > MAX_ALLOCATION - used)
53 return jbig2_fuzzer_reached_limit(0, size + ALIGNMENT);
54
55 ptr = (char *) malloc(size + ALIGNMENT);
56 if (ptr == NULL)
57 return NULL;
58
59 memcpy(ptr, &size, sizeof(size));
60 used += size + ALIGNMENT;
61
62 return ptr + ALIGNMENT;
63 }
64
jbig2_fuzzer_free(Jbig2Allocator * allocator,void * ptr)65 static void jbig2_fuzzer_free(Jbig2Allocator *allocator, void *ptr)
66 {
67 size_t size;
68
69 if (ptr == NULL)
70 return;
71 if (ptr < (void *) ALIGNMENT)
72 return;
73
74 ptr = (char *) ptr - ALIGNMENT;
75 memcpy(&size, ptr, sizeof(size));
76
77 used -= size + ALIGNMENT;
78 free(ptr);
79 }
80
jbig2_fuzzer_realloc(Jbig2Allocator * allocator,void * old,size_t size)81 static void *jbig2_fuzzer_realloc(Jbig2Allocator *allocator, void *old, size_t size)
82 {
83 size_t oldsize;
84 char *ptr;
85
86 if (old == NULL)
87 return jbig2_fuzzer_alloc(allocator, size);
88 if (old < (void *) ALIGNMENT)
89 return NULL;
90
91 if (size == 0) {
92 jbig2_fuzzer_free(allocator, old);
93 return NULL;
94 }
95 if (size > SIZE_MAX - ALIGNMENT)
96 return NULL;
97
98 old = (char *) old - ALIGNMENT;
99 memcpy(&oldsize, old, sizeof(oldsize));
100
101 if (size + ALIGNMENT > MAX_ALLOCATION - used + oldsize + ALIGNMENT)
102 return jbig2_fuzzer_reached_limit(oldsize + ALIGNMENT, size + ALIGNMENT);
103
104 ptr = (char *) realloc(old, size + ALIGNMENT);
105 if (ptr == NULL)
106 return NULL;
107
108 used -= oldsize + ALIGNMENT;
109 memcpy(ptr, &size, sizeof(size));
110 used += size + ALIGNMENT;
111
112 return ptr + ALIGNMENT;
113 }
114
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)115 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
116 Jbig2Allocator allocator;
117 Jbig2Ctx *ctx = NULL;
118
119 used = 0;
120
121 allocator.alloc = jbig2_fuzzer_alloc;
122 allocator.free = jbig2_fuzzer_free;
123 allocator.realloc = jbig2_fuzzer_realloc;
124
125 ctx = jbig2_ctx_new(&allocator, (Jbig2Options) 0, NULL, NULL, NULL);
126 if (jbig2_data_in(ctx, data, size) == 0)
127 {
128 if (jbig2_complete_page(ctx) == 0)
129 {
130 Jbig2Image *image = jbig2_page_out(ctx);
131 if (image != NULL)
132 {
133 int sum = 0;
134 for (int i = 0; i < image->height * image->stride; i++)
135 sum += image->data[i];
136 printf("sum of image data bytes: %d\n", sum);
137 }
138 jbig2_release_page(ctx, image);
139 }
140 }
141 jbig2_ctx_free(ctx);
142
143 return 0;
144 }
145