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 = ⊂ 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