| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "base/check.h" |
| #include "skia/ext/image_operations.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkImageInfo.h" |
| #include "third_party/skia/include/core/SkPixmap.h" |
| #include "third_party/skia/include/core/SkRect.h" |
| #include "third_party/skia/include/core/SkRefCnt.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| |
| // TODO(crbug.com/351564777): Remove this and convert code to safer constructs. |
| #pragma allow_unsafe_buffers |
| |
| template <typename T> |
| static bool read(const uint8_t** data, size_t* size, T* value) { |
| if (*size < sizeof(T)) { |
| return false; |
| } |
| |
| *value = *reinterpret_cast<const T*>(*data); |
| *data += sizeof(T); |
| *size -= sizeof(T); |
| return true; |
| } |
| |
| #define READ_INT(output) \ |
| if (!read<int>(&data, &size, &output)) \ |
| return 0; |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| int iMethod, srcW, srcH, dstW, dstH, subsetX, subsetY, subsetR, subsetB; |
| READ_INT(iMethod) |
| READ_INT(srcW) |
| READ_INT(srcH) |
| READ_INT(dstW) |
| READ_INT(dstH) |
| READ_INT(subsetX) |
| READ_INT(subsetY) |
| READ_INT(subsetR) |
| READ_INT(subsetB) |
| |
| skia::ImageOperations::ResizeMethod method = |
| skia::ImageOperations::RESIZE_GOOD; |
| switch (iMethod) { |
| case 1: |
| method = skia::ImageOperations::RESIZE_BETTER; |
| break; |
| case 2: |
| method = skia::ImageOperations::RESIZE_BEST; |
| break; |
| case 3: |
| method = skia::ImageOperations::RESIZE_BOX; |
| break; |
| case 4: |
| method = skia::ImageOperations::RESIZE_HAMMING1; |
| break; |
| case 5: |
| method = skia::ImageOperations::RESIZE_LANCZOS3; |
| break; |
| default: |
| break; // RESIZE_GOOD |
| } |
| if (srcW < 0 || srcH < 0 || srcW > 300 || srcH > 300) { |
| return 0; |
| } |
| if (dstW <= 0 || dstH <= 0 || dstW > srcW || dstH > srcH) { |
| return 0; |
| } |
| if (dstW == 0 && dstH == 0) { |
| return 0; |
| } |
| SkIRect subset = SkIRect{subsetX, subsetY, subsetR, subsetB}; |
| if (subset.isEmpty()) { |
| return 0; |
| } |
| SkIRect dest = {0, 0, dstW, dstH}; |
| if (!dest.contains(subset)) { |
| return 0; |
| } |
| sk_sp<SkSurface> surface = |
| SkSurfaces::Raster(SkImageInfo::MakeN32(srcW, srcH, kOpaque_SkAlphaType)); |
| if (!surface) { |
| return 0; |
| } |
| SkPixmap input; |
| if (!surface->peekPixels(&input)) { |
| return 0; |
| } |
| |
| SkBitmap bitmap = |
| skia::ImageOperations::Resize(input, method, dstW, dstH, subset); |
| return 0; |
| } |