aboutsummaryrefslogtreecommitdiffhomepage
path: root/fuzz/FuzzEncoders.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz/FuzzEncoders.cpp')
-rw-r--r--fuzz/FuzzEncoders.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/fuzz/FuzzEncoders.cpp b/fuzz/FuzzEncoders.cpp
new file mode 100644
index 0000000000..7ca4a48d9c
--- /dev/null
+++ b/fuzz/FuzzEncoders.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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.h"
+#include "SkBitmap.h"
+#include "SkImage.h"
+#include "SkImageInfo.h"
+#include "SkJpegEncoder.h"
+#include "SkPixmap.h"
+#include "SkPngEncoder.h"
+#include "SkRandom.h"
+#include "SkWebpEncoder.h"
+#include "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);
+}