• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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