1 // Copyright 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 // The fuzzer takes as input a buffer of bytes. The buffer is read in as:
17 // <angle>, <x_center>, <y_center>, and the remaining bytes will be read
18 // in as a <pix>. The image is then rotated by angle around the center. All
19 // inputs should not result in undefined behavior.
20 #include <cmath>
21 #include <cstddef>
22 #include <cstdint>
23 #include <cstdlib>
24 #include <cstring>
25 #include "leptonica/allheaders.h"
26
27 // Set to true only for debugging; always false for production
28 static const bool DebugOutput = false;
29
30 namespace {
31
32 // Reads the front bytes of a data buffer containing `size` bytes as an int16_t,
33 // and advances the buffer forward [if there is sufficient capacity]. If there
34 // is insufficient capacity, this returns 0 and does not modify size or data.
ReadInt16(const uint8_t ** data,size_t * size)35 int16_t ReadInt16(const uint8_t** data, size_t* size) {
36 int16_t result = 0;
37 if (*size >= sizeof(result)) {
38 memcpy(&result, *data, sizeof(result));
39 *data += sizeof(result);
40 *size -= sizeof(result);
41 }
42 return result;
43 }
44
45 } // namespace
46
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)47 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
48 const int16_t angle = ReadInt16(&data, &size);
49 const int16_t x_center = ReadInt16(&data, &size);
50 const int16_t y_center = ReadInt16(&data, &size);
51
52 // Check for pnm format; this can cause timeouts.
53 // The format checker requires at least 12 bytes.
54 if (size < 12) return EXIT_SUCCESS;
55 int format;
56 findFileFormatBuffer(data, &format);
57 if (format == IFF_PNM) return EXIT_SUCCESS;
58
59 Pix* pix = pixReadMem(reinterpret_cast<const unsigned char*>(data), size);
60 if (pix == nullptr) {
61 return EXIT_SUCCESS;
62 }
63
64 // Never in production
65 if (DebugOutput) {
66 L_INFO("w = %d, h = %d, d = %d\n", "fuzzer",
67 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix));
68 }
69
70 constexpr float deg2rad = M_PI / 180.;
71 Pix* pix_rotated = pixRotateShear(pix, x_center, y_center, deg2rad * angle,
72 L_BRING_IN_WHITE);
73 if (pix_rotated) {
74 pixDestroy(&pix_rotated);
75 }
76
77 pixDestroy(&pix);
78 return EXIT_SUCCESS;
79 }
80