1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Fuzz.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCodec.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCommandLineFlags.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkData.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImage.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImageEncoder.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImageFilter.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMallocPixelRef.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSFile.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSPath.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPicture.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPipe.h"
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h"
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRegion.h"
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h"
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSurface.h"
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextBlob.h"
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSLCompiler.h"
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <iostream>
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <signal.h>
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h"
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string2(bytes, b, "", "A path to a file or a directory. If a file, the "
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "contents will be used as the fuzz bytes. If a directory, all files "
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "in the directory will be used as fuzz bytes for the fuzzer, one at a "
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "time.");
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name.");
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a "
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "PNG with this name.");
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_bool2(verbose, v, false, "Print more information while fuzzing.");
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string2(type, t, "", "How to interpret --bytes, one of:\n"
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "api\n"
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "color_deserialize\n"
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "filter_fuzz (equivalent to Chrome's filter_fuzz_stub)\n"
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "icc\n"
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "image_mode\n"
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "image_scale\n"
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "path_deserialize\n"
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "pipe\n"
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "region_deserialize\n"
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "region_set_path\n"
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "skp\n"
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "sksl2glsl\n"
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "textblob");
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int fuzz_file(const char* path);
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint8_t calculate_option(SkData*);
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_api(sk_sp<SkData>);
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_color_deserialize(sk_sp<SkData>);
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_filter_fuzz(sk_sp<SkData>);
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_icc(sk_sp<SkData>);
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_img(sk_sp<SkData>, uint8_t, uint8_t);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_path_deserialize(sk_sp<SkData>);
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_region_deserialize(sk_sp<SkData>);
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_region_set_path(sk_sp<SkData>);
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_skp(sk_sp<SkData>);
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_skpipe(sk_sp<SkData>);
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_textblob_deserialize(sk_sp<SkData>);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_sksl2glsl(sk_sp<SkData>);
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint main(int argc, char** argv) {
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCommandLineFlags::SetUsage("Usage: fuzz -t <type> -b <path/to/file> [-n api-to-fuzz]\n"
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                 "--help lists the valid types\n");
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCommandLineFlags::Parse(argc, argv);
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0];
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!sk_isdir(path)) {
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fuzz_file(path);
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkOSFile::Iter it(path);
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (SkString file; it.next(&file); ) {
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString p = SkOSPath::Join(path, file.c_str());
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Fuzzing %s\n", p.c_str());
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int rv = fuzz_file(p.c_str());
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (rv != 0) {
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return rv;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return 0;
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int fuzz_file(const char* path) {
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkData> bytes(SkData::MakeFromFileName(path));
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!bytes) {
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Could not read %s\n", path);
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 1;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!FLAGS_type.isEmpty()) {
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("api", FLAGS_type[0])) {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_api(bytes);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("color_deserialize", FLAGS_type[0])) {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_color_deserialize(bytes);
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("icc", FLAGS_type[0])) {
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_icc(bytes);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("image_scale", FLAGS_type[0])) {
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            uint8_t option = calculate_option(bytes.get());
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_img(bytes, option, 0);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("image_mode", FLAGS_type[0])) {
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            uint8_t option = calculate_option(bytes.get());
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_img(bytes, 0, option);
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("path_deserialize", FLAGS_type[0])) {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_path_deserialize(bytes);
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("region_deserialize", FLAGS_type[0])) {
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_region_deserialize(bytes);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("region_set_path", FLAGS_type[0])) {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_region_set_path(bytes);
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("pipe", FLAGS_type[0])) {
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_skpipe(bytes);
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("skp", FLAGS_type[0])) {
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_skp(bytes);
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("filter_fuzz", FLAGS_type[0])) {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_filter_fuzz(bytes);
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("textblob", FLAGS_type[0])) {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_textblob_deserialize(bytes);
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp("sksl2glsl", FLAGS_type[0])) {
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzz_sksl2glsl(bytes);
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 0;
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCommandLineFlags::PrintUsage();
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return 1;
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This adds up the first 1024 bytes and returns it as an 8 bit integer.  This allows afl-fuzz to
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// deterministically excercise different paths, or *options* (such as different scaling sizes or
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// different image modes) without needing to introduce a parameter.  This way we don't need a
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a image_scale fuzzer.
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Clients are expected to transform this number into a different range, e.g. with modulo (%).
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint8_t calculate_option(SkData* bytes) {
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint8_t total = 0;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const uint8_t* data = bytes->bytes();
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (size_t i = 0; i < 1024 && i < bytes->size(); i++) {
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        total += data[i];
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return total;
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_api(sk_sp<SkData> bytes) {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name = FLAGS_name.isEmpty() ? "" : FLAGS_name[0];
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto r = sk_tools::Registry<Fuzzable>::Head(); r; r = r->next()) {
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto fuzzable = r->factory();
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == strcmp(name, fuzzable.name)) {
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("Fuzzing %s...\n", fuzzable.name);
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Fuzz fuzz(std::move(bytes));
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fuzzable.fn(&fuzz);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Success!\n");
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("When using --type api, please choose an API to fuzz with --name/-n:\n");
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto r = sk_tools::Registry<Fuzzable>::Head(); r; r = r->next()) {
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto fuzzable = r->factory();
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("\t%s\n", fuzzable.name);
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void dump_png(SkBitmap bitmap) {
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!FLAGS_dump.isEmpty()) {
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_tool_utils::EncodeImageToFile(FLAGS_dump[0], bitmap, SkEncodedImageFormat::kPNG, 100);
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Dumped to %s\n", FLAGS_dump[0]);
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_img(sk_sp<SkData> bytes, uint8_t scale, uint8_t mode) {
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We can scale 1x, 2x, 4x, 8x, 16x
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scale = scale % 5;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    float fscale = (float)pow(2.0f, scale);
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Scaling factor: %f\n", fscale);
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We have 5 different modes of decoding.
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    mode = mode % 5;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Mode: %d\n", mode);
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This is mostly copied from DMSrcSink's CodecSrc::draw method.
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Decoding\n");
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(bytes));
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (nullptr == codec.get()) {
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't create codec.\n");
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkImageInfo decodeInfo = codec->getInfo();
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize size = codec->getScaledDimensions(fscale);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCodec::Options options;
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!bitmap.tryAllocPixelsFlags(decodeInfo, SkBitmap::kZeroPixels_AllocFlag)) {
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Could not allocate memory.  Image might be too large (%d x %d)",
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                 decodeInfo.width(), decodeInfo.height());
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (mode) {
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case 0: {//kCodecZeroInit_Mode, kCodec_Mode
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options)) {
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kSuccess:
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] Success!\n");
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kIncompleteInput:
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] Partial Success\n");
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kErrorInInput:
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] Partial Success with error\n");
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kInvalidConversion:
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("Incompatible colortype conversion\n");
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // Crash to allow afl-fuzz to know this was a bug.
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    raise(SIGSEGV);
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] Couldn't getPixels.\n");
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return;
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case 1: {//kScanline_Mode
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[terminated] Could not start scanline decoder\n");
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            void* dst = bitmap.getAddr(0, 0);
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t rowBytes = bitmap.rowBytes();
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            uint32_t height = decodeInfo.height();
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (codec->getScanlineOrder()) {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kTopDown_SkScanlineOrder:
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkCodec::kBottomUp_SkScanlineOrder:
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // We do not need to check the return value.  On an incomplete
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // image, memory will be filled with a default value.
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    codec->getScanlines(dst, height, rowBytes);
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Success!\n");
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case 2: { //kStripe_Mode
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int height = decodeInfo.height();
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // does not align with image blocks.
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int stripeHeight = 37;
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Decode odd stripes
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOrder()) {
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // to run this test for image types that do not have this scanline ordering.
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[terminated] Could not start top-down scanline decoder\n");
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < numStripes; i += 2) {
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Skip a stripe
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                codec->skipScanlines(linesToSkip);
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Read a stripe
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int startY = (i + 1) * stripeHeight;
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int linesToRead = SkTMin(stripeHeight, height - startY);
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (linesToRead > 0) {
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Decode even stripes
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkCodec::kSuccess != startResult) {
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[terminated] Failed to restart scanline decoder with same parameters.\n");
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < numStripes; i += 2) {
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Read a stripe
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int startY = i * stripeHeight;
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int linesToRead = SkTMin(stripeHeight, height - startY);
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Skip a stripe
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (linesToSkip > 0) {
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    codec->skipScanlines(linesToSkip);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Success!\n");
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case 3: { //kSubset_Mode
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Arbitrarily choose a divisor.
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int divisor = 2;
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Total width/height of the image.
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int W = codec->getInfo().width();
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int H = codec->getInfo().height();
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (divisor > W || divisor > H) {
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[terminated] Cannot codec subset: divisor %d is too big "
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         "with dimensions (%d x %d)\n", divisor, W, H);
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // subset dimensions
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int w = SkAlign2(W / divisor);
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int h = SkAlign2(H / divisor);
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkIRect subset;
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkCodec::Options opts;
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            opts.fSubset = &subset;
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkBitmap subsetBm;
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // We will reuse pixel memory from bitmap.
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            void* pixels = bitmap.getPixels();
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Keep track of left and top (for drawing subsetBm into canvas). We could use
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // fscale * x and fscale * y, but we want integers such that the next subset will start
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // where the last one ended. So we'll add decodeInfo.width() and height().
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int left = 0;
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int x = 0; x < W; x += w) {
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                int top = 0;
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int y = 0; y < H; y+= h) {
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // Do not make the subset go off the edge of the image.
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const int preScaleW = SkTMin(w, W - x);
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const int preScaleH = SkTMin(h, H - y);
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    subset.setXYWH(x, y, preScaleW, preScaleH);
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // And fscale
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // FIXME: Should we have a version of getScaledDimensions that takes a subset
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // into account?
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    decodeInfo = decodeInfo.makeWH(
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkTMax(1, SkScalarRoundToInt(preScaleW * fscale)),
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkTMax(1, SkScalarRoundToInt(preScaleH * fscale)));
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    size_t rowBytes = decodeInfo.minRowBytes();
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes)) {
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkDebugf("[terminated] Could not install pixels.\n");
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return;
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            &opts);
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    switch (result) {
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkCodec::kSuccess:
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkCodec::kIncompleteInput:
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkCodec::kErrorInInput:
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDebugf("okay\n");
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkCodec::kInvalidConversion:
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            if (0 == (x|y)) {
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                // First subset is okay to return unimplemented.
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                SkDebugf("[terminated] Incompatible colortype conversion\n");
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                return;
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            }
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            // If the first subset succeeded, a later one should not fail.
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            // fall through to failure
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkCodec::kUnimplemented:
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            if (0 == (x|y)) {
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                // First subset is okay to return unimplemented.
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                SkDebugf("[terminated] subset codec not supported\n");
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                return;
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            }
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            // If the first subset succeeded, why would a later one fail?
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            // fall through to failure
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        default:
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDebugf("[terminated] subset codec failed to decode (%d, %d, %d, %d) "
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                  "with dimensions (%d x %d)\t error %d\n",
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                  x, y, decodeInfo.width(), decodeInfo.height(),
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                  W, H, result);
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            return;
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // translate by the scaled height.
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    top += decodeInfo.height();
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // translate by the scaled width.
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                left += decodeInfo.width();
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Success!\n");
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case 4: { //kAnimated_Mode
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (frameInfos.size() == 0) {
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[terminated] Not an animated image\n");
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (size_t i = 0; i < frameInfos.size(); i++) {
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                options.fFrameIndex = i;
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto result = codec->startIncrementalDecode(decodeInfo, bitmap.getPixels(),
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        bitmap.rowBytes(), &options);
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (SkCodec::kSuccess != result) {
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] failed to start incremental decode "
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             "in frame %d with error %d\n", i, result);
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return;
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result = codec->incrementalDecode();
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (result == SkCodec::kIncompleteInput || result == SkCodec::kErrorInInput) {
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("okay\n");
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // Frames beyond this one will not decode.
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (result == SkCodec::kSuccess) {
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("okay - decoded frame %d\n", i);
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("[terminated] incremental decode failed with "
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             "error %d\n", result);
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return;
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Success!\n");
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        default:
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[terminated] Mode not implemented yet\n");
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    dump_png(bitmap);
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_skp(sk_sp<SkData> bytes) {
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkReadBuffer buf(bytes->data(), bytes->size());
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Decoding\n");
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkPicture> pic(SkPicture::MakeFromBuffer(buf));
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!pic) {
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't decode as a picture.\n");
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Rendering\n");
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!FLAGS_dump.isEmpty()) {
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkIRect size = pic->cullRect().roundOut();
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bitmap.allocN32Pixels(size.width(), size.height());
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCanvas canvas(bitmap);
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPicture(pic);
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Decoded and rendered an SkPicture!\n");
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    dump_png(bitmap);
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_skpipe(sk_sp<SkData> bytes) {
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPipeDeserializer d;
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Decoding\n");
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkPicture> pic(d.readPicture(bytes.get()));
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!pic) {
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't decode picture via SkPipe.\n");
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("Rendering\n");
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCanvas canvas(bitmap);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPicture(pic);
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Decoded and rendered an SkPicture from SkPipe!\n");
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_icc(sk_sp<SkData> bytes) {
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkColorSpace> space(SkColorSpace::MakeICC(bytes->data(), bytes->size()));
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!space) {
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't decode ICC.\n");
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Decoded ICC.\n");
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_color_deserialize(sk_sp<SkData> bytes) {
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkColorSpace> space(SkColorSpace::Deserialize(bytes->data(), bytes->size()));
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!space) {
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't deserialize Colorspace.\n");
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! deserialized Colorspace.\n");
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_path_deserialize(sk_sp<SkData> bytes) {
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath path;
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkReadBuffer buf(bytes->data(), bytes->size());
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buf.readPath(&path);
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!buf.isValid()) {
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't deserialize SkPath.\n");
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto s = SkSurface::MakeRasterN32Premul(1024, 1024);
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    s->getCanvas()->drawPath(path, SkPaint());
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Initialized SkPath.\n");
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool FuzzRegionDeserialize(sk_sp<SkData> bytes);
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_region_deserialize(sk_sp<SkData> bytes) {
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!FuzzRegionDeserialize(bytes)) {
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't initialize SkRegion.\n");
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Initialized SkRegion.\n");
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_textblob_deserialize(sk_sp<SkData> bytes) {
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkReadBuffer buf(bytes->data(), bytes->size());
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto tb = SkTextBlob::MakeFromBuffer(buf);
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!buf.isValid()) {
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't deserialize SkTextBlob.\n");
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto s = SkSurface::MakeRasterN32Premul(512, 512);
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    s->getCanvas()->drawTextBlob(tb, 200, 200, SkPaint());
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Initialized SkTextBlob.\n");
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid FuzzRegionSetPath(Fuzz* fuzz);
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_region_set_path(sk_sp<SkData> bytes) {
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Fuzz fuzz(bytes);
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    FuzzRegionSetPath(&fuzz);
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] region_set_path didn't crash!\n");
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_filter_fuzz(sk_sp<SkData> bytes) {
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int BitmapSize = 24;
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bitmap.allocN32Pixels(BitmapSize, BitmapSize);
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCanvas canvas(bitmap);
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.clear(0x00000000);
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto flattenable = SkImageFilter::Deserialize(bytes->data(), bytes->size());
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Adding some info, but the test passed if we got here without any trouble
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (flattenable != nullptr) {
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Valid stream detected.\n");
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Let's see if using the filters can cause any trouble...
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setImageFilter(flattenable);
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas.save();
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas.clipRect(SkRect::MakeXYWH(
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            0, 0, SkIntToScalar(BitmapSize), SkIntToScalar(BitmapSize)));
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // This call shouldn't crash or cause ASAN to flag any memory issues
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // If nothing bad happens within this call, everything is fine
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas.drawBitmap(bitmap, 0, 0, &paint);
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Filter DAG rendered successfully\n");
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas.restore();
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Invalid stream detected.\n");
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Done\n");
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void fuzz_sksl2glsl(sk_sp<SkData> bytes) {
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSL::Compiler compiler;
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSL::String output;
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSL::Program::Settings settings;
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    settings.fCaps = caps.get();
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kFragment_Kind,
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                          SkSL::String((const char*) bytes->data()),
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                          settings);
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!program || !compiler.toGLSL(*program, &output)) {
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[terminated] Couldn't compile input.\n");
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("[terminated] Success! Compiled input.\n");
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
610