1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "Fuzz.h"
9 #include "SkString.h"
10 #include "SkParsePath.h"
11 #include <stdlib.h>
12
13 // Most of this is taken from random_parse_path.cpp and adapted to use the Fuzz
14 // instead of SKRandom
15
16 static const struct Legal {
17 char fSymbol;
18 int fScalars;
19 } gLegal[] = {
20 { 'M', 2 },
21 { 'H', 1 },
22 { 'V', 1 },
23 { 'L', 2 },
24 { 'Q', 4 },
25 { 'T', 2 },
26 { 'C', 6 },
27 { 'S', 4 },
28 { 'A', 4 },
29 { 'Z', 0 },
30 };
31
32 static bool gEasy = false; // set to true while debugging to suppress unusual whitespace
33
34 // mostly do nothing, then bias towards spaces
35 static const char gWhiteSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', ' ', ' ', 0x09, 0x0D, 0x0A };
36
add_white(Fuzz * fuzz,SkString * atom)37 static void add_white(Fuzz* fuzz, SkString* atom) {
38 if (gEasy) {
39 atom->append(" ");
40 return;
41 }
42 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
43 // smaller, which leads to more efficient fuzzing.
44 uint8_t reps;
45 fuzz->nextRange(&reps, 0, 2);
46 for (uint8_t rep = 0; rep < reps; ++rep) {
47 uint8_t index;
48 fuzz->nextRange(&index, 0, (int) SK_ARRAY_COUNT(gWhiteSpace) - 1);
49 if (gWhiteSpace[index]) {
50 atom->append(&gWhiteSpace[index], 1);
51 }
52 }
53 }
54
add_some_white(Fuzz * fuzz,SkString * atom)55 static void add_some_white(Fuzz* fuzz, SkString* atom) {
56 for(int i = 0; i < 10; i++) {
57 add_white(fuzz, atom);
58 }
59 }
60
add_comma(Fuzz * fuzz,SkString * atom)61 static void add_comma(Fuzz* fuzz, SkString* atom) {
62 if (gEasy) {
63 atom->append(",");
64 return;
65 }
66 add_white(fuzz, atom);
67 bool b;
68 fuzz->next(&b);
69 if (b) {
70 atom->append(",");
71 }
72 add_some_white(fuzz, atom);
73 }
74
MakeRandomParsePathPiece(Fuzz * fuzz)75 SkString MakeRandomParsePathPiece(Fuzz* fuzz) {
76 SkString atom;
77 uint8_t index;
78 fuzz->nextRange(&index, 0, (int) SK_ARRAY_COUNT(gLegal) - 1);
79 const Legal& legal = gLegal[index];
80 gEasy ? atom.append("\n") : add_white(fuzz, &atom);
81 bool b;
82 fuzz->next(&b);
83 char symbol = legal.fSymbol | (b ? 0x20 : 0);
84 atom.append(&symbol, 1);
85 uint8_t reps;
86 fuzz->nextRange(&reps, 1, 3);
87 for (int rep = 0; rep < reps; ++rep) {
88 for (int index = 0; index < legal.fScalars; ++index) {
89 SkScalar coord;
90 fuzz->nextRange(&coord, 0.0f, 100.0f);
91 add_white(fuzz, &atom);
92 atom.appendScalar(coord);
93 if (rep < reps - 1 && index < legal.fScalars - 1) {
94 add_comma(fuzz, &atom);
95 } else {
96 add_some_white(fuzz, &atom);
97 }
98 if ('A' == legal.fSymbol && 1 == index) {
99 SkScalar s;
100 fuzz->nextRange(&s, -720.0f, 720.0f);
101 atom.appendScalar(s);
102 add_comma(fuzz, &atom);
103 fuzz->next(&b);
104 atom.appendU32(b);
105 add_comma(fuzz, &atom);
106 fuzz->next(&b);
107 atom.appendU32(b);
108 add_comma(fuzz, &atom);
109 }
110 }
111 }
112 return atom;
113 }
114
DEF_FUZZ(ParsePath,fuzz)115 DEF_FUZZ(ParsePath, fuzz) {
116 SkPath path;
117 SkString spec;
118 uint8_t count;
119 fuzz->nextRange(&count, 0, 40);
120 for (uint8_t i = 0; i < count; ++i) {
121 spec.append(MakeRandomParsePathPiece(fuzz));
122 }
123 SkDebugf("SkParsePath::FromSVGString(%s, &path);\n",spec.c_str());
124 if (!SkParsePath::FromSVGString(spec.c_str(), &path)){
125 SkDebugf("Could not decode path\n");
126 }
127 }
128