Index: testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc |
diff --git a/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc b/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..850f73f4679501ed7129417070bc9b82c88ff9fe |
--- /dev/null |
+++ b/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc |
@@ -0,0 +1,89 @@ |
+// Copyright 2017 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 <cstddef> |
+#include <cstdint> |
+#include <random> |
+ |
+#include "base/logging.h" |
+#include "base/strings/string_piece.h" |
+#include "testing/libfuzzer/fuzzers/color_space_data.h" |
+#include "third_party/skia/include/core/SkColorSpace.h" |
+#include "third_party/skia/include/core/SkColorSpaceXform.h" |
+ |
+static constexpr size_t kPixels = 2048 / 4; |
+ |
+static uint32_t pixels[kPixels * 4]; |
+ |
+static void GeneratePixels(size_t hash) { |
+ static std::uniform_int_distribution<uint32_t> uniform(0u, ~0u); |
+ |
+ std::mt19937_64 random(hash); |
+ for (size_t i = 0; i < arraysize(pixels); ++i) |
+ pixels[i] = uniform(random); |
+} |
+ |
+static sk_sp<SkColorSpace> test; |
+static sk_sp<SkColorSpace> srgb; |
+ |
+static void ColorTransform(size_t hash, bool input) { |
+ if (!test.get()) |
+ return; |
+ |
+ auto transform = input ? SkColorSpaceXform::New(test.get(), srgb.get()) |
+ : SkColorSpaceXform::New(srgb.get(), test.get()); |
+ if (!transform) |
+ return; |
+ |
+ static uint32_t output[kPixels * 4]; |
+ |
+ const auto color = SkColorSpaceXform::ColorFormat(hash & 7); |
+ const auto alpha = SkAlphaType(hash >> 3 & 3); |
+ |
+ transform->apply(color, output, color, pixels, kPixels, alpha); |
+} |
+ |
+static sk_sp<SkColorSpace> SelectProfile(size_t hash) { |
+ static sk_sp<SkColorSpace> profiles[8] = { |
+ SkColorSpace::MakeSRGB(), |
+ SkColorSpace::MakeICC(kSRGBData, arraysize(kSRGBData)), |
+ SkColorSpace::MakeICC(kSRGBPara, arraysize(kSRGBPara)), |
+ SkColorSpace::MakeICC(kAdobeData, arraysize(kAdobeData)), |
+ SkColorSpace::MakeSRGBLinear(), |
+ SkColorSpace::MakeRGB( |
+ SkColorSpace::RenderTargetGamma::kLinear_RenderTargetGamma, |
+ SkColorSpace::Gamut::kAdobeRGB_Gamut), |
+ SkColorSpace::MakeRGB( |
+ SkColorSpace::RenderTargetGamma::kSRGB_RenderTargetGamma, |
+ SkColorSpace::Gamut::kDCIP3_D65_Gamut), |
+ SkColorSpace::MakeSRGB(), |
+ }; |
+ |
+ return profiles[hash & 7]; |
+} |
+ |
+inline size_t Hash(const char* data, size_t size) { |
+ return base::StringPieceHash()(base::StringPiece(data, size)); |
+} |
+ |
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
+ constexpr size_t kSizeLimit = 4 * 1024 * 1024; |
+ if (size < 128 || size > kSizeLimit) |
+ return 0; |
+ |
+ test = SkColorSpace::MakeICC(data, size); |
+ if (!test.get()) |
+ return 0; |
+ |
+ const size_t hash = Hash(reinterpret_cast<const char*>(data), size); |
+ srgb = SelectProfile(hash); |
+ GeneratePixels(hash); |
+ |
+ ColorTransform(hash, true); |
+ ColorTransform(hash, false); |
+ |
+ test.reset(); |
+ srgb.reset(); |
+ return 0; |
+} |