Chromium Code Reviews| Index: skia/tools/path_fuzzer/path_fuzzer.cc |
| diff --git a/skia/tools/path_fuzzer/path_fuzzer.cc b/skia/tools/path_fuzzer/path_fuzzer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..dcda0bf2a2bba1c309ee0e4427665ee98862f5f7 |
| --- /dev/null |
| +++ b/skia/tools/path_fuzzer/path_fuzzer.cc |
| @@ -0,0 +1,113 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <stddef.h> |
| +#include <stdint.h> |
| + |
| +#include "third_party/skia/include/core/SkCanvas.h" |
| +#include "third_party/skia/include/core/SkPaint.h" |
| +#include "third_party/skia/include/core/SkPath.h" |
| +#include "third_party/skia/include/core/SkSurface.h" |
| + |
| +const int OPERATION_COUNT = 9; |
| + |
| +template <typename T> |
|
Martin Barbella
2016/06/01 23:43:36
I'm assuming this comes up a lot in other fuzzers
mmoroz
2016/06/02 10:05:22
I've seen a similar thing in some of networking fu
|
| +static bool read(uint8_t** data, size_t* size, T* value) { |
| + if (*size < sizeof(value)) |
| + return false; |
| + |
| + *value = *reinterpret_cast<T*>(*data); |
| + *data += sizeof(value); |
| + *size -= sizeof(value); |
| + return true; |
| +} |
| + |
| +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { |
| + SkPath path; |
|
Martin Barbella
2016/06/01 23:43:36
SkPath::readFromMemory actually looks takes data a
|
| + uint8_t operation; |
| + SkScalar a, b, c, d, e, f; |
| + |
| + while (read<uint8_t>(&data, &size, &operation)) { |
| + bool result = true; |
| + switch (operation % OPERATION_COUNT) { |
| + // Path building. |
| + case 0: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b); |
| + if (result) |
| + path.lineTo(a, b); |
| + break; |
| + |
| + case 1: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b) && |
| + read<SkScalar>(&data, &size, &c) && |
| + read<SkScalar>(&data, &size, &d); |
| + if (result) |
| + path.quadTo(a, b, c, d); |
| + break; |
| + |
| + case 2: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b) && |
| + read<SkScalar>(&data, &size, &c) && |
| + read<SkScalar>(&data, &size, &d) && |
| + read<SkScalar>(&data, &size, &e); |
| + if (result) |
| + path.conicTo(a, b, c, d, e); |
| + break; |
| + |
| + case 3: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b) && |
| + read<SkScalar>(&data, &size, &c) && |
| + read<SkScalar>(&data, &size, &d) && |
| + read<SkScalar>(&data, &size, &e) && |
| + read<SkScalar>(&data, &size, &f); |
| + if (result) |
| + path.cubicTo(a, b, c, d, e, f); |
| + break; |
| + |
| + case 5: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b); |
| + if (result) |
| + path.moveTo(a, b); |
| + break; |
| + |
| + case 6: |
| + path.close(); |
| + break; |
| + |
| + // Potentially interesting calls using the current path. |
| + case 7: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b); |
| + if (result) |
| + path.contains(a, b); |
| + break; |
| + |
| + case 8: |
| + result = read<SkScalar>(&data, &size, &a) && |
| + read<SkScalar>(&data, &size, &b) && |
| + read<SkScalar>(&data, &size, &c) && |
| + read<SkScalar>(&data, &size, &d); |
| + if (result) { |
| + SkRect rect = SkRect::MakeLTRB(a, b, c, d); |
| + path.conservativelyContainsRect(rect); |
| + } |
| + break; |
| + } |
| + |
| + if (!result) |
| + break; |
| + } |
| + |
| + SkPaint paint; |
| + auto surface(SkSurface::MakeRasterN32Premul(128, 128)); |
| + SkCanvas* canvas = surface->getCanvas(); |
| + canvas->drawPath(path, paint); |
| + |
| + return 0; |
| +} |