Coverage Report

Created: 2024-05-20 06:23

/src/pdf_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
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
676M
#define ALIGNMENT ((size_t) 16)
27
84.1M
#define KBYTE ((size_t) 1024)
28
84.1M
#define MBYTE (1024 * KBYTE)
29
84.1M
#define GBYTE (1024 * MBYTE)
30
84.1M
#define MAX_ALLOCATION (1 * GBYTE)
31
32
static size_t used;
33
34
static void *fz_limit_reached_ossfuzz(size_t oldsize, size_t size)
35
130
{
36
130
  if (oldsize == 0)
37
130
    fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte allocation: %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, size);
38
0
  else
39
0
    fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte reallocation: %zu -> %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, oldsize, size);
40
130
  fflush(0);
41
130
  return NULL;
42
130
}
43
44
static void *fz_malloc_ossfuzz(void *opaque, size_t size)
45
80.9M
{
46
80.9M
  char *ptr = NULL;
47
48
80.9M
  if (size == 0)
49
0
    return NULL;
50
80.9M
  if (size > SIZE_MAX - ALIGNMENT)
51
0
    return NULL;
52
80.9M
  if (size + ALIGNMENT > MAX_ALLOCATION - used)
53
130
    return fz_limit_reached_ossfuzz(0, size + ALIGNMENT);
54
55
80.9M
  ptr = (char *) malloc(size + ALIGNMENT);
56
80.9M
  if (ptr == NULL)
57
0
    return NULL;
58
59
80.9M
  memcpy(ptr, &size, sizeof(size));
60
80.9M
  used += size + ALIGNMENT;
61
62
80.9M
  return ptr + ALIGNMENT;
63
80.9M
}
64
65
static void fz_free_ossfuzz(void *opaque, void *ptr)
66
80.9M
{
67
80.9M
  size_t size;
68
69
80.9M
  if (ptr == NULL)
70
0
    return;
71
80.9M
  if (ptr < (void *) ALIGNMENT)
72
0
    return;
73
74
80.9M
  ptr = (char *) ptr - ALIGNMENT;
75
80.9M
  memcpy(&size, ptr, sizeof(size));
76
77
80.9M
  used -= size + ALIGNMENT;
78
80.9M
  free(ptr);
79
80.9M
}
80
81
static void *fz_realloc_ossfuzz(void *opaque, void *old, size_t size)
82
5.96M
{
83
5.96M
  size_t oldsize;
84
5.96M
  char *ptr;
85
86
5.96M
  if (old == NULL)
87
2.82M
    return fz_malloc_ossfuzz(opaque, size);
88
3.14M
  if (old < (void *) ALIGNMENT)
89
0
    return NULL;
90
91
3.14M
  if (size == 0) {
92
0
    fz_free_ossfuzz(opaque, old);
93
0
    return NULL;
94
0
  }
95
3.14M
  if (size > SIZE_MAX - ALIGNMENT)
96
0
    return NULL;
97
98
3.14M
  old = (char *) old - ALIGNMENT;
99
3.14M
  memcpy(&oldsize, old, sizeof(oldsize));
100
101
3.14M
  if (size + ALIGNMENT > MAX_ALLOCATION - used + oldsize + ALIGNMENT)
102
0
    return fz_limit_reached_ossfuzz(oldsize + ALIGNMENT, size + ALIGNMENT);
103
104
3.14M
  ptr = (char *) realloc(old, size + ALIGNMENT);
105
3.14M
  if (ptr == NULL)
106
0
    return NULL;
107
108
3.14M
  used -= oldsize + ALIGNMENT;
109
3.14M
  memcpy(ptr, &size, sizeof(size));
110
3.14M
  used += size + ALIGNMENT;
111
112
3.14M
  return ptr + ALIGNMENT;
113
3.14M
}
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
123
15.6k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
124
15.6k
  fz_context *ctx;
125
15.6k
  fz_stream *stream;
126
15.6k
  fz_document *doc;
127
15.6k
  fz_pixmap *pix;
128
129
15.6k
  used = 0;
130
131
15.6k
  ctx = fz_new_context(&fz_alloc_ossfuzz, nullptr, FZ_STORE_DEFAULT);
132
15.6k
  stream = NULL;
133
15.6k
  doc = NULL;
134
15.6k
  pix = NULL;
135
136
15.6k
  fz_var(stream);
137
15.6k
  fz_var(doc);
138
15.6k
  fz_var(pix);
139
140
31.2k
  fz_try(ctx) {
141
15.6k
    fz_register_document_handlers(ctx);
142
15.6k
    stream = fz_open_memory(ctx, data, size);
143
15.6k
    doc = fz_open_document_with_stream(ctx, "pdf", stream);
144
145
31.8k
    for (int i = 0; i < fz_count_pages(ctx, doc); i++) {
146
16.2k
      pix = fz_new_pixmap_from_page_number(ctx, doc, i, fz_identity, fz_device_rgb(ctx), 0);
147
16.2k
      fz_drop_pixmap(ctx, pix);
148
16.2k
      pix = NULL;
149
16.2k
    }
150
15.6k
  }
151
31.2k
  fz_always(ctx) {
152
15.6k
    fz_drop_pixmap(ctx, pix);
153
15.6k
    fz_drop_document(ctx, doc);
154
15.6k
    fz_drop_stream(ctx, stream);
155
15.6k
  }
156
15.6k
  fz_catch(ctx) {
157
2.08k
    fz_report_error(ctx);
158
2.08k
    fz_log_error(ctx, "error rendering pages");
159
2.08k
  }
160
161
15.6k
  fz_flush_warnings(ctx);
162
15.6k
  fz_drop_context(ctx);
163
164
15.6k
  return 0;
165
15.6k
}