1// rasterfuzzer.cc
2//
3//   A fuzzing function to test FreeType's rasterizers with libFuzzer.
4//
5// Copyright 2016-2018 by
6// David Turner, Robert Wilhelm, and Werner Lemberg.
7//
8// This file is part of the FreeType project, and may only be used,
9// modified, and distributed under the terms of the FreeType project
10// license, LICENSE.TXT.  By continuing to use, modify, or distribute
11// this file you indicate that you have read the license and
12// understand and accept it fully.
13
14
15#include <stdint.h>
16
17#include <vector>
18
19
20  using namespace std;
21
22
23#include <ft2build.h>
24
25#include FT_FREETYPE_H
26#include FT_IMAGE_H
27#include FT_OUTLINE_H
28
29
30  static FT_Library  library;
31  static int         InitResult;
32
33
34  struct FT_Global {
35    FT_Global() {
36      InitResult = FT_Init_FreeType( &library );
37    }
38    ~FT_Global() {
39      FT_Done_FreeType( library );
40    }
41  };
42
43  FT_Global  global_ft;
44
45
46  extern "C" int
47  LLVMFuzzerTestOneInput( const uint8_t*  data,
48                          size_t          size_ )
49  {
50    unsigned char  pixels[4];
51
52    FT_Bitmap  bitmap_mono = {
53      1,                  // rows
54      1,                  // width
55      4,                  // pitch
56      pixels,             // buffer
57      2,                  // num_grays
58      FT_PIXEL_MODE_MONO, // pixel_mode
59      0,                  // palette_mode
60      NULL                // palette
61    };
62
63    FT_Bitmap  bitmap_gray = {
64      1,                  // rows
65      1,                  // width
66      4,                  // pitch
67      pixels,             // buffer
68      256,                // num_grays
69      FT_PIXEL_MODE_GRAY, // pixel_mode
70      0,                  // palette_mode
71      NULL                // palette
72    };
73
74    const size_t vsize = sizeof ( FT_Vector );
75    const size_t tsize = sizeof ( char );
76
77    // we use the input data for both points and tags
78    short  n_points = short( size_ / ( vsize + tsize ) );
79    if ( n_points <= 2 )
80      return 0;
81
82    FT_Vector*  points = reinterpret_cast<FT_Vector*>(
83                           const_cast<uint8_t*>(
84                             data ) );
85    char*       tags   = reinterpret_cast<char*>(
86                           const_cast<uint8_t*>(
87                             data + size_t( n_points ) * vsize ) );
88
89    // to reduce the number of invalid outlines that are immediately
90    // rejected in `FT_Outline_Render', limit values to 2^18 pixels
91    // (i.e., 2^24 bits)
92    for ( short  i = 0; i < n_points; i++ )
93    {
94      if ( points[i].x == LONG_MIN )
95        points[i].x = 0;
96      else if ( points[i].x < 0 )
97        points[i].x = -( -points[i].x & 0xFFFFFF ) - 1;
98      else
99        points[i].x = ( points[i].x & 0xFFFFFF ) + 1;
100
101      if ( points[i].y == LONG_MIN )
102        points[i].y = 0;
103      else if ( points[i].y < 0 )
104        points[i].y = -( -points[i].y & 0xFFFFFF ) - 1;
105      else
106        points[i].y = ( points[i].y & 0xFFFFFF ) + 1;
107    }
108
109    short  contours[1];
110    contours[0] = n_points - 1;
111
112    FT_Outline  outline =
113    {
114      1,               // n_contours
115      n_points,        // n_points
116      points,          // points
117      tags,            // tags
118      contours,        // contours
119      FT_OUTLINE_NONE  // flags
120    };
121
122    FT_Outline_Get_Bitmap( library, &outline, &bitmap_mono );
123    FT_Outline_Get_Bitmap( library, &outline, &bitmap_gray );
124
125    return 0;
126  }
127
128
129// END
130