1 /* 2 * Copyright 2016 Mozilla Foundation 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 "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkImage.h" 12 #include "SkPath.h" 13 #include "SkSurface.h" 14 #include "SkTypeface.h" 15 #include "SkClipOpPriv.h" 16 17 static const int kBmpSize = 24; 18 static const int kMaxX = 250; 19 static const int kMaxY = 250; 20 static const int kPtsLen = 10; 21 static const int kTxtLen = 5; 22 23 static void init_string(Fuzz* fuzz, char* str, size_t bufSize) { 24 for (size_t i = 0; i < bufSize-1; ++i) { 25 fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII 26 } 27 str[bufSize-1] = '\0'; 28 } 29 30 // make_paint mostly borrowed from FilterFuzz.cpp 31 static void init_paint(Fuzz* fuzz, SkPaint* p) { 32 bool b; 33 fuzz->next(&b); 34 p->setAntiAlias(b); 35 36 uint8_t tmp_u8; 37 fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode); 38 p->setBlendMode(static_cast<SkBlendMode>(tmp_u8)); 39 40 SkColor co; 41 fuzz->next(&co); 42 p->setColor(co); 43 44 fuzz->next(&b); 45 p->setDither(b); 46 47 fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality); 48 p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8)); 49 50 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kFull_Hinting); 51 p->setHinting(static_cast<SkPaint::Hinting>(tmp_u8)); 52 53 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap); 54 p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8)); 55 56 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join); 57 p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8)); 58 59 SkScalar sc; 60 fuzz->next(&sc); 61 p->setStrokeMiter(sc); 62 63 fuzz->next(&sc); 64 p->setStrokeWidth(sc); 65 66 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style); 67 p->setStyle(static_cast<SkPaint::Style>(tmp_u8)); 68 } 69 70 static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) { 71 uint8_t colorType; 72 fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType); 73 // ColorType needs to match what the system configuration is. 74 if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) { 75 colorType = kN32_SkColorType; 76 } 77 bool b; 78 fuzz->next(&b); 79 SkImageInfo info = SkImageInfo::Make(kBmpSize, 80 kBmpSize, 81 (SkColorType)colorType, 82 b ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 83 if (!bmp->tryAllocPixels(info)) { 84 SkDEBUGF(("Bitmap not allocated\n")); 85 } 86 SkColor c; 87 fuzz->next(&c); 88 bmp->eraseColor(c); 89 90 fuzz->next(&b); 91 SkPaint p; 92 if (b) { 93 init_paint(fuzz, &p); 94 } 95 else { 96 fuzz->next(&c); 97 p.setColor(c); 98 } 99 } 100 101 static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) { 102 uint8_t x, y; 103 fuzz->nextRange(&x, 1, kMaxX); 104 fuzz->nextRange(&y, 1, kMaxY); 105 *s = SkSurface::MakeRasterN32Premul(x, y); 106 107 if (!*s) { 108 // Was possibly too big for the memory constrained fuzzing environments 109 *s = SkSurface::MakeNull(x, y); 110 } 111 } 112 113 114 static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> font) { 115 SkPaint p; 116 init_paint(fuzz, &p); 117 sk_sp<SkSurface> surface; 118 init_surface(fuzz, &surface); 119 120 char text[kTxtLen]; 121 init_string(fuzz, text, kTxtLen); 122 123 SkScalar x, y; 124 fuzz->next(&x, &y); 125 // populate pts array 126 SkPoint pts[kPtsLen]; 127 for (uint8_t i = 0; i < kPtsLen; ++i) { 128 pts[i].set(x, y); 129 x += p.getTextSize(); 130 } 131 132 p.setTypeface(font); 133 // set text related attributes 134 bool b; 135 fuzz->next(&b); 136 p.setAutohinted(b); 137 fuzz->next(&b); 138 p.setDevKernText(b); 139 fuzz->next(&b); 140 p.setEmbeddedBitmapText(b); 141 fuzz->next(&b); 142 p.setFakeBoldText(b); 143 fuzz->next(&b); 144 p.setLCDRenderText(b); 145 fuzz->next(&b); 146 p.setLinearText(b); 147 fuzz->next(&b); 148 p.setSubpixelText(b); 149 fuzz->next(&x); 150 p.setTextScaleX(x); 151 fuzz->next(&x); 152 p.setTextSkewX(x); 153 fuzz->next(&x); 154 p.setTextSize(x); 155 fuzz->next(&b); 156 p.setVerticalText(b); 157 158 SkCanvas* cnv = surface->getCanvas(); 159 cnv->drawPosText(text, (kTxtLen-1), pts, p); 160 161 fuzz->next(&x); 162 fuzz->next(&y); 163 cnv->drawText(text, (kTxtLen-1), x, y, p); 164 } 165 166 static void fuzz_drawCircle(Fuzz* fuzz) { 167 SkPaint p; 168 init_paint(fuzz, &p); 169 sk_sp<SkSurface> surface; 170 init_surface(fuzz, &surface); 171 172 SkScalar a, b, c; 173 fuzz->next(&a, &b, &c); 174 surface->getCanvas()->drawCircle(a, b, c, p); 175 } 176 177 static void fuzz_drawLine(Fuzz* fuzz) { 178 SkPaint p; 179 init_paint(fuzz, &p); 180 sk_sp<SkSurface> surface; 181 init_surface(fuzz, &surface); 182 183 SkScalar a, b, c, d; 184 fuzz->next(&a, &b, &c, &d); 185 surface->getCanvas()->drawLine(a, b, c, d, p); 186 } 187 188 static void fuzz_drawRect(Fuzz* fuzz) { 189 SkPaint p; 190 init_paint(fuzz, &p); 191 sk_sp<SkSurface> surface; 192 init_surface(fuzz, &surface); 193 194 SkScalar a, b, c, d; 195 fuzz->next(&a, &b, &c, &d); 196 SkRect r; 197 r = SkRect::MakeXYWH(a, b, c, d); 198 199 SkCanvas* cnv = surface->getCanvas(); 200 cnv->drawRect(r, p); 201 202 bool bl; 203 fuzz->next(&bl); 204 fuzz->next(&a, &b, &c, &d); 205 r = SkRect::MakeXYWH(a, b, c, d); 206 cnv->clipRect(r, kIntersect_SkClipOp, bl); 207 } 208 209 static void fuzz_drawPath(Fuzz* fuzz) { 210 SkPaint p; 211 init_paint(fuzz, &p); 212 sk_sp<SkSurface> surface; 213 init_surface(fuzz, &surface); 214 215 // TODO(kjlubick): put the ability to fuzz a path in shared file, with 216 // other common things (e.g. rects, lines) 217 uint8_t i, j; 218 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform 219 SkPath path; 220 SkScalar a, b, c, d, e, f; 221 for (int k = 0; k < i; ++k) { 222 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform 223 switch (j) { 224 case 0: 225 fuzz->next(&a, &b); 226 path.moveTo(a, b); 227 break; 228 case 1: 229 fuzz->next(&a, &b); 230 path.lineTo(a, b); 231 break; 232 case 2: 233 fuzz->next(&a, &b, &c, &d); 234 path.quadTo(a, b, c, d); 235 break; 236 case 3: 237 fuzz->next(&a, &b, &c, &d, &e); 238 path.conicTo(a, b, c, d, e); 239 break; 240 case 4: 241 fuzz->next(&a, &b, &c, &d, &e, &f); 242 path.cubicTo(a, b, c, d, e, f); 243 break; 244 case 5: 245 fuzz->next(&a, &b, &c, &d, &e); 246 path.arcTo(a, b, c, d, e); 247 break; 248 } 249 } 250 path.close(); 251 252 SkCanvas* cnv = surface->getCanvas(); 253 cnv->drawPath(path, p); 254 255 bool bl; 256 fuzz->next(&bl); 257 cnv->clipPath(path, kIntersect_SkClipOp, bl); 258 } 259 260 static void fuzz_drawBitmap(Fuzz* fuzz) { 261 SkPaint p; 262 init_paint(fuzz, &p); 263 sk_sp<SkSurface> surface; 264 init_surface(fuzz, &surface); 265 SkBitmap bmp; 266 init_bitmap(fuzz, &bmp); 267 268 SkScalar a, b; 269 fuzz->next(&a, &b); 270 surface->getCanvas()->drawBitmap(bmp, a, b, &p); 271 } 272 273 static void fuzz_drawImage(Fuzz* fuzz) { 274 SkPaint p; 275 init_paint(fuzz, &p); 276 sk_sp<SkSurface> surface; 277 init_surface(fuzz, &surface); 278 SkBitmap bmp; 279 init_bitmap(fuzz, &bmp); 280 281 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp)); 282 283 bool bl; 284 fuzz->next(&bl); 285 SkScalar a, b; 286 fuzz->next(&a, &b); 287 if (bl) { 288 surface->getCanvas()->drawImage(image, a, b, &p); 289 } 290 else { 291 SkRect dst = SkRect::MakeWH(a, b); 292 fuzz->next(&a, &b); 293 SkRect src = SkRect::MakeWH(a, b); 294 uint8_t x; 295 fuzz->nextRange(&x, 0, 1); 296 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x; 297 surface->getCanvas()->drawImageRect(image, src, dst, &p, cst); 298 } 299 } 300 301 static void fuzz_drawPaint(Fuzz* fuzz) { 302 SkPaint l, p; 303 init_paint(fuzz, &p); 304 sk_sp<SkSurface> surface; 305 init_surface(fuzz, &surface); 306 307 surface->getCanvas()->drawPaint(p); 308 } 309 310 DEF_FUZZ(DrawFunctions, fuzz) { 311 uint8_t i; 312 fuzz->next(&i); 313 314 switch(i) { 315 case 0: { 316 sk_sp<SkTypeface> f = SkTypeface::MakeDefault(); 317 if (f == nullptr) { 318 SkDebugf("Could not initialize font.\n"); 319 fuzz->signalBug(); 320 } 321 SkDEBUGF(("Fuzz DrawText\n")); 322 fuzz_drawText(fuzz, f); 323 return; 324 } 325 case 1: 326 SkDEBUGF(("Fuzz DrawRect\n")); 327 fuzz_drawRect(fuzz); 328 return; 329 case 2: 330 SkDEBUGF(("Fuzz DrawCircle\n")); 331 fuzz_drawCircle(fuzz); 332 return; 333 case 3: 334 SkDEBUGF(("Fuzz DrawLine\n")); 335 fuzz_drawLine(fuzz); 336 return; 337 case 4: 338 SkDEBUGF(("Fuzz DrawPath\n")); 339 fuzz_drawPath(fuzz); 340 return; 341 case 5: 342 SkDEBUGF(("Fuzz DrawImage/DrawImageRect\n")); 343 fuzz_drawImage(fuzz); 344 return; 345 case 6: 346 SkDEBUGF(("Fuzz DrawBitmap\n")); 347 fuzz_drawBitmap(fuzz); 348 return; 349 case 7: 350 SkDEBUGF(("Fuzz DrawPaint\n")); 351 fuzz_drawPaint(fuzz); 352 return; 353 } 354 } 355