1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Takes an Input protobuf message from libprotobuf-mutator, converts it to an
6 // actual skia image filter and then applies it to a canvas for the purpose of
7 // fuzzing skia. This should uncover bugs that could be used by a compromised
8 // renderer to exploit the browser process.
9
10 #include <stdlib.h>
11
12 #include <iostream>
13 #include <string>
14
15 #include "testing/libfuzzer/proto/skia_image_filter_proto_converter.h"
16
17 #include "base/memory/raw_ptr.h"
18 #include "base/process/memory.h"
19 #include "base/test/test_discardable_memory_allocator.h"
20 #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "third_party/skia/include/core/SkCanvas.h"
23 #include "third_party/skia/include/core/SkImage.h"
24 #include "third_party/skia/include/core/SkImageFilter.h"
25
26 protobuf_mutator::protobuf::LogSilencer log_silencer;
27
28 using skia_image_filter_proto_converter::Input;
29 using skia_image_filter_proto_converter::Converter;
30
31 static const int kBitmapSize = 24;
32
33 struct Environment {
34 raw_ptr<base::TestDiscardableMemoryAllocator> discardable_memory_allocator;
EnvironmentEnvironment35 Environment() {
36 base::EnableTerminationOnOutOfMemory();
37 discardable_memory_allocator = new base::TestDiscardableMemoryAllocator();
38 base::DiscardableMemoryAllocator::SetInstance(discardable_memory_allocator);
39 }
40 };
41
DEFINE_PROTO_FUZZER(const Input & input)42 DEFINE_PROTO_FUZZER(const Input& input) {
43 [[maybe_unused]] static Environment environment = Environment();
44
45 static Converter converter = Converter();
46 std::string ipc_filter_message = converter.Convert(input);
47
48 // Allow the flattened skia filter to be retrieved easily.
49 if (getenv("LPM_DUMP_NATIVE_INPUT")) {
50 // Don't write a newline since it will make the output invalid (so that it
51 // cannot be fed to filter_fuzz_stub) Flush instead.
52 std::cout << ipc_filter_message << std::flush;
53 }
54
55 sk_sp<SkImageFilter> flattenable = SkImageFilter::Deserialize(
56 ipc_filter_message.c_str(), ipc_filter_message.size());
57
58 if (!flattenable)
59 return;
60
61 SkBitmap bitmap;
62 bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
63 SkCanvas canvas(bitmap);
64 canvas.clear(0x00000000);
65 SkPaint paint;
66 paint.setImageFilter(flattenable);
67 canvas.save();
68 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(kBitmapSize),
69 SkIntToScalar(kBitmapSize)));
70 canvas.drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
71 canvas.restore();
72 }
73