FuzzEncoders.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright 2018 Google LLC
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "fuzz/Fuzz.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkImage.h"
  10. #include "include/core/SkImageInfo.h"
  11. #include "include/core/SkPixmap.h"
  12. #include "include/encode/SkJpegEncoder.h"
  13. #include "include/encode/SkPngEncoder.h"
  14. #include "include/encode/SkWebpEncoder.h"
  15. #include "include/utils/SkRandom.h"
  16. #include "src/core/SkOSFile.h"
  17. #include <vector>
  18. // These values were picked arbitrarily to hopefully limit the size of the
  19. // serialized SkPixmaps.
  20. constexpr int MAX_WIDTH = 512;
  21. constexpr int MAX_HEIGHT = 512;
  22. static SkBitmap make_fuzzed_bitmap(Fuzz* fuzz) {
  23. SkBitmap bm;
  24. uint32_t w, h;
  25. fuzz->nextRange(&w, 1, MAX_WIDTH);
  26. fuzz->nextRange(&h, 1, MAX_HEIGHT);
  27. if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(w, h))) {
  28. return bm;
  29. }
  30. uint32_t n = w * h;
  31. fuzz->nextN((SkPMColor*)bm.getPixels(), n);
  32. return bm;
  33. }
  34. DEF_FUZZ(PNGEncoder, fuzz) {
  35. auto bm = make_fuzzed_bitmap(fuzz);
  36. auto opts = SkPngEncoder::Options{};
  37. fuzz->nextRange(&opts.fZLibLevel, 0, 9);
  38. SkDynamicMemoryWStream dest;
  39. SkPngEncoder::Encode(&dest, bm.pixmap(), opts);
  40. }
  41. DEF_FUZZ(JPEGEncoder, fuzz) {
  42. auto bm = make_fuzzed_bitmap(fuzz);
  43. auto opts = SkJpegEncoder::Options{};
  44. fuzz->nextRange(&opts.fQuality, 0, 100);
  45. SkDynamicMemoryWStream dest;
  46. (void)SkJpegEncoder::Encode(&dest, bm.pixmap(), opts);
  47. }
  48. DEF_FUZZ(WEBPEncoder, fuzz) {
  49. auto bm = make_fuzzed_bitmap(fuzz);
  50. auto opts = SkWebpEncoder::Options{};
  51. fuzz->nextRange(&opts.fQuality, 0.0f, 100.0f);
  52. bool lossy;
  53. fuzz->next(&lossy);
  54. if (lossy) {
  55. opts.fCompression = SkWebpEncoder::Compression::kLossy;
  56. } else {
  57. opts.fCompression = SkWebpEncoder::Compression::kLossless;
  58. }
  59. SkDynamicMemoryWStream dest;
  60. (void)SkWebpEncoder::Encode(&dest, bm.pixmap(), opts);
  61. }
  62. // Not a real fuzz endpoint, but a helper to take in real, good images
  63. // and dump out a corpus for this fuzzer.
  64. DEF_FUZZ(_MakeEncoderCorpus, fuzz) {
  65. auto bytes = fuzz->fBytes;
  66. SkDebugf("bytes %d\n", bytes->size());
  67. auto img = SkImage::MakeFromEncoded(bytes);
  68. if (nullptr == img.get()) {
  69. SkDebugf("invalid image, could not decode\n");
  70. return;
  71. }
  72. if (img->width() > MAX_WIDTH || img->height() > MAX_HEIGHT) {
  73. SkDebugf("Too big (%d x %d)\n", img->width(), img->height());
  74. return;
  75. }
  76. std::vector<int32_t> dstPixels;
  77. int rowBytes = img->width() * 4;
  78. dstPixels.resize(img->height() * rowBytes);
  79. SkPixmap pm(SkImageInfo::MakeN32Premul(img->width(), img->height()),
  80. &dstPixels.front(), rowBytes);
  81. if (!img->readPixels(pm, 0, 0)) {
  82. SkDebugf("Could not read pixmap\n");
  83. return;
  84. }
  85. SkString s("./encoded_corpus/enc_");
  86. static SkRandom rand;
  87. s.appendU32(rand.nextU());
  88. auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
  89. if (!file) {
  90. SkDebugf("Can't initialize file\n");
  91. return;
  92. }
  93. auto total = pm.info().bytesPerPixel() * pm.width() * pm.height();
  94. SkDebugf("Writing %d (%d x %d) bytes\n", total, pm.width(), pm.height());
  95. // Write out the size in two bytes since that's what the fuzzer will
  96. // read first.
  97. uint32_t w = pm.width();
  98. sk_fwrite(&w, sizeof(uint32_t), file);
  99. uint32_t h = pm.height();
  100. sk_fwrite(&h, sizeof(uint32_t), file);
  101. sk_fwrite(pm.addr(), total, file);
  102. sk_fclose(file);
  103. }