123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "fuzz/Fuzz.h"
- #include "include/core/SkBitmap.h"
- #include "include/core/SkImage.h"
- #include "include/core/SkImageInfo.h"
- #include "include/core/SkPixmap.h"
- #include "include/encode/SkJpegEncoder.h"
- #include "include/encode/SkPngEncoder.h"
- #include "include/encode/SkWebpEncoder.h"
- #include "include/utils/SkRandom.h"
- #include "src/core/SkOSFile.h"
- #include <vector>
- // These values were picked arbitrarily to hopefully limit the size of the
- // serialized SkPixmaps.
- constexpr int MAX_WIDTH = 512;
- constexpr int MAX_HEIGHT = 512;
- static SkBitmap make_fuzzed_bitmap(Fuzz* fuzz) {
- SkBitmap bm;
- uint32_t w, h;
- fuzz->nextRange(&w, 1, MAX_WIDTH);
- fuzz->nextRange(&h, 1, MAX_HEIGHT);
- if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(w, h))) {
- return bm;
- }
- uint32_t n = w * h;
- fuzz->nextN((SkPMColor*)bm.getPixels(), n);
- return bm;
- }
- DEF_FUZZ(PNGEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
- auto opts = SkPngEncoder::Options{};
- fuzz->nextRange(&opts.fZLibLevel, 0, 9);
- SkDynamicMemoryWStream dest;
- SkPngEncoder::Encode(&dest, bm.pixmap(), opts);
- }
- DEF_FUZZ(JPEGEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
- auto opts = SkJpegEncoder::Options{};
- fuzz->nextRange(&opts.fQuality, 0, 100);
- SkDynamicMemoryWStream dest;
- (void)SkJpegEncoder::Encode(&dest, bm.pixmap(), opts);
- }
- DEF_FUZZ(WEBPEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
- auto opts = SkWebpEncoder::Options{};
- fuzz->nextRange(&opts.fQuality, 0.0f, 100.0f);
- bool lossy;
- fuzz->next(&lossy);
- if (lossy) {
- opts.fCompression = SkWebpEncoder::Compression::kLossy;
- } else {
- opts.fCompression = SkWebpEncoder::Compression::kLossless;
- }
- SkDynamicMemoryWStream dest;
- (void)SkWebpEncoder::Encode(&dest, bm.pixmap(), opts);
- }
- // Not a real fuzz endpoint, but a helper to take in real, good images
- // and dump out a corpus for this fuzzer.
- DEF_FUZZ(_MakeEncoderCorpus, fuzz) {
- auto bytes = fuzz->fBytes;
- SkDebugf("bytes %d\n", bytes->size());
- auto img = SkImage::MakeFromEncoded(bytes);
- if (nullptr == img.get()) {
- SkDebugf("invalid image, could not decode\n");
- return;
- }
- if (img->width() > MAX_WIDTH || img->height() > MAX_HEIGHT) {
- SkDebugf("Too big (%d x %d)\n", img->width(), img->height());
- return;
- }
- std::vector<int32_t> dstPixels;
- int rowBytes = img->width() * 4;
- dstPixels.resize(img->height() * rowBytes);
- SkPixmap pm(SkImageInfo::MakeN32Premul(img->width(), img->height()),
- &dstPixels.front(), rowBytes);
- if (!img->readPixels(pm, 0, 0)) {
- SkDebugf("Could not read pixmap\n");
- return;
- }
- SkString s("./encoded_corpus/enc_");
- static SkRandom rand;
- s.appendU32(rand.nextU());
- auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
- if (!file) {
- SkDebugf("Can't initialize file\n");
- return;
- }
- auto total = pm.info().bytesPerPixel() * pm.width() * pm.height();
- SkDebugf("Writing %d (%d x %d) bytes\n", total, pm.width(), pm.height());
- // Write out the size in two bytes since that's what the fuzzer will
- // read first.
- uint32_t w = pm.width();
- sk_fwrite(&w, sizeof(uint32_t), file);
- uint32_t h = pm.height();
- sk_fwrite(&h, sizeof(uint32_t), file);
- sk_fwrite(pm.addr(), total, file);
- sk_fclose(file);
- }
|