• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <inttypes.h>
23 
24 #include <mupdf/fitz.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 
fz_limit_reached_ossfuzz(size_t oldsize,size_t size)34 static void *fz_limit_reached_ossfuzz(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 
fz_malloc_ossfuzz(void * opaque,size_t size)44 static void *fz_malloc_ossfuzz(void *opaque, 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 fz_limit_reached_ossfuzz(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 
fz_free_ossfuzz(void * opaque,void * ptr)65 static void fz_free_ossfuzz(void *opaque, 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 
fz_realloc_ossfuzz(void * opaque,void * old,size_t size)81 static void *fz_realloc_ossfuzz(void *opaque, void *old, size_t size)
82 {
83   size_t oldsize;
84   char *ptr;
85 
86   if (old == NULL)
87     return fz_malloc_ossfuzz(opaque, size);
88   if (old < (void *) ALIGNMENT)
89     return NULL;
90 
91   if (size == 0) {
92     fz_free_ossfuzz(opaque, 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 fz_limit_reached_ossfuzz(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 
115 static fz_alloc_context fz_alloc_ossfuzz =
116 {
117   NULL,
118   fz_malloc_ossfuzz,
119   fz_realloc_ossfuzz,
120   fz_free_ossfuzz
121 };
122 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)123 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
124   fz_context *ctx;
125   fz_stream *stream;
126   fz_document *doc;
127   fz_pixmap *pix;
128 
129   used = 0;
130 
131   ctx = fz_new_context(&fz_alloc_ossfuzz, nullptr, FZ_STORE_DEFAULT);
132   stream = NULL;
133   doc = NULL;
134   pix = NULL;
135 
136   fz_var(stream);
137   fz_var(doc);
138   fz_var(pix);
139 
140   fz_try(ctx) {
141     fz_register_document_handlers(ctx);
142     stream = fz_open_memory(ctx, data, size);
143     doc = fz_open_document_with_stream(ctx, "pdf", stream);
144 
145     for (int i = 0; i < fz_count_pages(ctx, doc); i++) {
146       pix = fz_new_pixmap_from_page_number(ctx, doc, i, fz_identity, fz_device_rgb(ctx), 0);
147       fz_drop_pixmap(ctx, pix);
148       pix = NULL;
149     }
150   }
151   fz_always(ctx) {
152     fz_drop_pixmap(ctx, pix);
153     fz_drop_document(ctx, doc);
154     fz_drop_stream(ctx, stream);
155   }
156   fz_catch(ctx) {
157   }
158 
159   fz_drop_context(ctx);
160 
161   return 0;
162 }
163