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