/src/leptonica/prog/fuzzing/pix_rotate_shear_fuzzer.cc
Line | Count | Source |
1 | | // The fuzzer takes as input a buffer of bytes. The buffer is read in as: |
2 | | // <angle>, <x_center>, <y_center>, and the remaining bytes will be read |
3 | | // in as a <pix>. The image is then rotated by angle around the center. All |
4 | | // inputs should not result in undefined behavior. |
5 | | #include <cmath> |
6 | | #include <cstddef> |
7 | | #include <cstdint> |
8 | | #include <cstdlib> |
9 | | #include <cstring> |
10 | | #include "leptfuzz.h" |
11 | | |
12 | | // Set to true only for debugging; always false for production |
13 | | static const bool DebugOutput = false; |
14 | | |
15 | | namespace { |
16 | | |
17 | | // Reads the front bytes of a data buffer containing `size` bytes as an int16_t, |
18 | | // and advances the buffer forward [if there is sufficient capacity]. If there |
19 | | // is insufficient capacity, this returns 0 and does not modify size or data. |
20 | 18.3k | int16_t ReadInt16(const uint8_t** data, size_t* size) { |
21 | 18.3k | int16_t result = 0; |
22 | 18.3k | if (*size >= sizeof(result)) { |
23 | 18.3k | memcpy(&result, *data, sizeof(result)); |
24 | 18.3k | *data += sizeof(result); |
25 | 18.3k | *size -= sizeof(result); |
26 | 18.3k | } |
27 | 18.3k | return result; |
28 | 18.3k | } |
29 | | |
30 | | } // namespace |
31 | | |
32 | 6.10k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
33 | 6.10k | const int16_t angle = ReadInt16(&data, &size); |
34 | 6.10k | const int16_t x_center = ReadInt16(&data, &size); |
35 | 6.10k | const int16_t y_center = ReadInt16(&data, &size); |
36 | | |
37 | 6.10k | leptSetStdNullHandler(); |
38 | | |
39 | | // Don't do pnm format (which can cause timeouts) or |
40 | | // jpeg format (which can have uninitialized variables). |
41 | | // tiff and png can also take too much memory in this test, |
42 | | // but not in applications because they abort quickly after |
43 | | // reading the header and computing the size of the data. |
44 | | // Note that the format checker requires at least 12 bytes. |
45 | 6.10k | if (size < 12) return EXIT_SUCCESS; |
46 | 6.09k | int format; |
47 | 6.09k | findFileFormatBuffer(data, &format); |
48 | 6.09k | if (format == IFF_PNM || format == IFF_JFIF_JPEG || |
49 | 6.08k | format == IFF_TIFF || format == IFF_PNG) return EXIT_SUCCESS; |
50 | | |
51 | 6.07k | Pix* pix = pixReadMem(reinterpret_cast<const unsigned char*>(data), size); |
52 | 6.07k | if (pix == nullptr) { |
53 | 4.82k | return EXIT_SUCCESS; |
54 | 4.82k | } |
55 | | |
56 | | // Never in production |
57 | 1.24k | if (DebugOutput) { |
58 | 0 | L_INFO("w = %d, h = %d, d = %d\n", "fuzzer", |
59 | 0 | pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix)); |
60 | 0 | } |
61 | | |
62 | 1.24k | constexpr float deg2rad = M_PI / 180.; |
63 | 1.24k | Pix* pix_rotated = pixRotateShear(pix, x_center, y_center, deg2rad * angle, |
64 | 1.24k | L_BRING_IN_WHITE); |
65 | 1.24k | if (pix_rotated) { |
66 | 820 | pixDestroy(&pix_rotated); |
67 | 820 | } |
68 | | |
69 | 1.24k | pixDestroy(&pix); |
70 | | return EXIT_SUCCESS; |
71 | 6.07k | } |