1/* 2 * Copyright 2011 Google Inc. 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 8#include "include/core/SkMallocPixelRef.h" 9 10#include "include/core/SkData.h" 11#include "include/core/SkImageInfo.h" 12#include "include/private/SkMalloc.h" 13 14static bool is_valid(const SkImageInfo& info) { 15 if (info.width() < 0 || info.height() < 0 || 16 (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType || 17 (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) 18 { 19 return false; 20 } 21 return true; 22} 23 24sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, size_t rowBytes) { 25 if (rowBytes == 0) { 26 rowBytes = info.minRowBytes(); 27 // rowBytes can still be zero, if it overflowed (width * bytesPerPixel > size_t) 28 // or if colortype is unknown 29 } 30 if (!is_valid(info) || !info.validRowBytes(rowBytes)) { 31 return nullptr; 32 } 33 size_t size = info.computeByteSize(rowBytes); 34 if (SkImageInfo::ByteSizeOverflowed(size)) { 35 return nullptr; 36 } 37#if defined(SK_BUILD_FOR_FUZZER) 38 if (size > 100000) { 39 return nullptr; 40 } 41#endif 42 void* addr = sk_calloc_canfail(size); 43 if (nullptr == addr) { 44 return nullptr; 45 } 46 47 struct PixelRef final : public SkPixelRef { 48 PixelRef(int w, int h, void* s, size_t r) : SkPixelRef(w, h, s, r) {} 49 ~PixelRef() override { sk_free(this->pixels()); } 50 }; 51 return sk_sp<SkPixelRef>(new PixelRef(info.width(), info.height(), addr, rowBytes)); 52} 53 54sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info, 55 size_t rowBytes, 56 sk_sp<SkData> data) { 57 SkASSERT(data != nullptr); 58 if (!is_valid(info)) { 59 return nullptr; 60 } 61 // TODO: what should we return if computeByteSize returns 0? 62 // - the info was empty? 63 // - we overflowed computing the size? 64 if ((rowBytes < info.minRowBytes()) || (data->size() < info.computeByteSize(rowBytes))) { 65 return nullptr; 66 } 67 struct PixelRef final : public SkPixelRef { 68 sk_sp<SkData> fData; 69 PixelRef(int w, int h, void* s, size_t r, sk_sp<SkData> d) 70 : SkPixelRef(w, h, s, r), fData(std::move(d)) {} 71 }; 72 void* pixels = const_cast<void*>(data->data()); 73 sk_sp<SkPixelRef> pr(new PixelRef(info.width(), info.height(), pixels, rowBytes, 74 std::move(data))); 75 pr->setImmutable(); // since we were created with (immutable) data 76 return pr; 77} 78