tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SkReadBuffer.cpp (17025B)


      1 /*
      2 * Copyright 2012 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 "src/core/SkReadBuffer.h"
      9 
     10 #include "include/core/SkAlphaType.h"
     11 #include "include/core/SkData.h"
     12 #include "include/core/SkImage.h"
     13 #include "include/core/SkImageGenerator.h"
     14 #include "include/core/SkImageInfo.h"
     15 #include "include/core/SkM44.h"
     16 #include "include/core/SkMatrix.h"
     17 #include "include/core/SkPath.h"
     18 #include "include/core/SkPixmap.h"
     19 #include "include/core/SkPoint3.h"
     20 #include "include/core/SkRRect.h"
     21 #include "include/core/SkRegion.h"
     22 #include "include/core/SkSize.h"
     23 #include "include/core/SkString.h"
     24 #include "include/core/SkTypeface.h"
     25 #include "include/private/base/SkMalloc.h"
     26 #include "src/base/SkAutoMalloc.h"
     27 #include "src/base/SkMathPriv.h"
     28 #include "src/base/SkSafeMath.h"
     29 #include "src/core/SkMatrixPriv.h"
     30 #include "src/core/SkMipmapBuilder.h"
     31 #include "src/core/SkWriteBuffer.h"
     32 
     33 #include <memory>
     34 #include <optional>
     35 #include <utility>
     36 
     37 namespace {
     38    // This generator intentionally should always fail on all attempts to get its pixels,
     39    // simulating a bad or empty codec stream.
     40    class EmptyImageGenerator final : public SkImageGenerator {
     41    public:
     42        EmptyImageGenerator(const SkImageInfo& info) : SkImageGenerator(info) { }
     43 
     44    };
     45 
     46    static sk_sp<SkImage> MakeEmptyImage(int width, int height) {
     47        return SkImages::DeferredFromGenerator(
     48                std::make_unique<EmptyImageGenerator>(SkImageInfo::MakeN32Premul(width, height)));
     49    }
     50 
     51 } // anonymous namespace
     52 
     53 void SkReadBuffer::setMemory(const void* data, size_t size) {
     54    this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
     55    if (!fError) {
     56        fBase = fCurr = (const char*)data;
     57        fStop = fBase + size;
     58    }
     59 }
     60 
     61 void SkReadBuffer::setInvalid() {
     62    if (!fError) {
     63        // When an error is found, send the read cursor to the end of the stream
     64        fCurr = fStop;
     65        fError = true;
     66    }
     67 }
     68 
     69 const void* SkReadBuffer::skip(size_t size) {
     70    size_t inc = SkAlign4(size);
     71    this->validate(inc >= size);
     72    const void* addr = fCurr;
     73    this->validate(IsPtrAlign4(addr) && this->isAvailable(inc));
     74    if (fError) {
     75        return nullptr;
     76    }
     77 
     78    fCurr += inc;
     79    return addr;
     80 }
     81 
     82 const void* SkReadBuffer::skip(size_t count, size_t size) {
     83    return this->skip(SkSafeMath::Mul(count, size));
     84 }
     85 
     86 void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
     87    fProcs = procs;
     88    this->setAllowSkSL(procs.fAllowSkSL);
     89 }
     90 
     91 bool SkReadBuffer::readBool() {
     92    uint32_t value = this->readUInt();
     93    // Boolean value should be either 0 or 1
     94    this->validate(!(value & ~1));
     95    return value != 0;
     96 }
     97 
     98 SkColor SkReadBuffer::readColor() {
     99    return this->readUInt();
    100 }
    101 
    102 int32_t SkReadBuffer::readInt() {
    103    const size_t inc = sizeof(int32_t);
    104    if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
    105        return 0;
    106    }
    107    int32_t value = *((const int32_t*)fCurr);
    108    fCurr += inc;
    109    return value;
    110 }
    111 
    112 SkScalar SkReadBuffer::readScalar() {
    113    const size_t inc = sizeof(SkScalar);
    114    if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
    115        return 0;
    116    }
    117    SkScalar value = *((const SkScalar*)fCurr);
    118    fCurr += inc;
    119    return value;
    120 }
    121 
    122 uint32_t SkReadBuffer::readUInt() {
    123    return this->readInt();
    124 }
    125 
    126 int32_t SkReadBuffer::read32() {
    127    return this->readInt();
    128 }
    129 
    130 uint8_t SkReadBuffer::peekByte() {
    131    if (this->available() <= 0) {
    132        fError = true;
    133        return 0;
    134    }
    135    return *((const uint8_t*)fCurr);
    136 }
    137 
    138 bool SkReadBuffer::readPad32(void* buffer, size_t bytes) {
    139    if (const void* src = this->skip(bytes)) {
    140        // buffer might be null if bytes is zero (see SkAutoMalloc), hence we call
    141        // the careful version of memcpy.
    142        sk_careful_memcpy(buffer, src, bytes);
    143        return true;
    144    }
    145    return false;
    146 }
    147 
    148 const char* SkReadBuffer::readString(size_t* len) {
    149    *len = this->readUInt();
    150 
    151    // The string is len characters and a terminating \0.
    152    const char* c_str = this->skipT<char>(*len+1);
    153 
    154    if (this->validate(c_str && c_str[*len] == '\0')) {
    155        return c_str;
    156    }
    157    return nullptr;
    158 }
    159 
    160 void SkReadBuffer::readString(SkString* string) {
    161    size_t len;
    162    if (const char* c_str = this->readString(&len)) {
    163        string->set(c_str, len);
    164        return;
    165    }
    166    string->reset();
    167 }
    168 
    169 void SkReadBuffer::readColor4f(SkColor4f* color) {
    170    if (!this->readPad32(color, sizeof(SkColor4f))) {
    171        *color = {0, 0, 0, 0};
    172    }
    173 }
    174 
    175 void SkReadBuffer::readPoint(SkPoint* point) {
    176    point->fX = this->readScalar();
    177    point->fY = this->readScalar();
    178 }
    179 
    180 void SkReadBuffer::readPoint3(SkPoint3* point) {
    181    this->readPad32(point, sizeof(SkPoint3));
    182 }
    183 
    184 void SkReadBuffer::read(SkM44* matrix) {
    185    if (this->isValid()) {
    186        if (const float* m = (const float*)this->skip(sizeof(float) * 16)) {
    187            *matrix = SkM44::ColMajor(m);
    188        }
    189    }
    190    if (!this->isValid()) {
    191        *matrix = SkM44();
    192    }
    193 }
    194 
    195 void SkReadBuffer::readMatrix(SkMatrix* matrix) {
    196    size_t size = 0;
    197    if (this->isValid()) {
    198        size = SkMatrixPriv::ReadFromMemory(matrix, fCurr, this->available());
    199        (void)this->validate((SkAlign4(size) == size) && (0 != size));
    200    }
    201    if (!this->isValid()) {
    202        matrix->reset();
    203    }
    204    (void)this->skip(size);
    205 }
    206 
    207 void SkReadBuffer::readIRect(SkIRect* rect) {
    208    if (!this->readPad32(rect, sizeof(SkIRect))) {
    209        rect->setEmpty();
    210    }
    211 }
    212 
    213 void SkReadBuffer::readRect(SkRect* rect) {
    214    if (!this->readPad32(rect, sizeof(SkRect))) {
    215        rect->setEmpty();
    216    }
    217 }
    218 
    219 SkRect SkReadBuffer::readRect() {
    220    SkRect r;
    221    if (!this->readPad32(&r, sizeof(SkRect))) {
    222        r.setEmpty();
    223    }
    224    return r;
    225 }
    226 
    227 SkSamplingOptions SkReadBuffer::readSampling() {
    228    if (!this->isVersionLT(SkPicturePriv::kAnisotropicFilter)) {
    229        int maxAniso = this->readInt();
    230        if (maxAniso != 0) {
    231            return SkSamplingOptions::Aniso(maxAniso);
    232        }
    233    }
    234    if (this->readBool()) {
    235        float B = this->readScalar();
    236        float C = this->readScalar();
    237        return SkSamplingOptions({B, C});
    238    } else {
    239        SkFilterMode filter = this->read32LE(SkFilterMode::kLinear);
    240        SkMipmapMode mipmap = this->read32LE(SkMipmapMode::kLinear);
    241        return SkSamplingOptions(filter, mipmap);
    242    }
    243 }
    244 
    245 void SkReadBuffer::readRRect(SkRRect* rrect) {
    246    size_t size = 0;
    247    if (!fError) {
    248        size = rrect->readFromMemory(fCurr, this->available());
    249        if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
    250            rrect->setEmpty();
    251        }
    252    }
    253    (void)this->skip(size);
    254 }
    255 
    256 void SkReadBuffer::readRegion(SkRegion* region) {
    257    size_t size = 0;
    258    if (!fError) {
    259        size = region->readFromMemory(fCurr, this->available());
    260        if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
    261            region->setEmpty();
    262        }
    263    }
    264    (void)this->skip(size);
    265 }
    266 
    267 std::optional<SkPath> SkReadBuffer::readPath() {
    268    if (fError) {
    269        return {};
    270    }
    271 
    272    size_t size = 0;
    273    auto path = SkPath::ReadFromMemory(fCurr, this->available(), &size);
    274 
    275    // todo: consider moving this 4-byte-alignment check elsewhere
    276    //       i.e. why is that a burden on SkPath?
    277    //            why don't we just skipAlign4() or something?
    278    (void)this->validate(SkAlign4(size) == size && path.has_value());
    279 
    280    // we move forward, regardless of if the path succeeded
    281    (void)this->skip(size);
    282 
    283    return path;
    284 }
    285 
    286 bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
    287    const uint32_t count = this->readUInt();
    288    return this->validate(size == count) &&
    289           this->readPad32(value, SkSafeMath::Mul(size, elementSize));
    290 }
    291 
    292 bool SkReadBuffer::readByteArray(void* value, size_t size) {
    293    return this->readArray(value, size, sizeof(uint8_t));
    294 }
    295 
    296 bool SkReadBuffer::readColorArray(SkSpan<SkColor> colors) {
    297    return this->readArray(colors.data(), colors.size(), sizeof(SkColor));
    298 }
    299 
    300 bool SkReadBuffer::readColor4fArray(SkSpan<SkColor4f> colors) {
    301    return this->readArray(colors.data(), colors.size(), sizeof(SkColor4f));
    302 }
    303 
    304 bool SkReadBuffer::readIntArray(SkSpan<int32_t> values) {
    305    return this->readArray(values.data(), values.size(), sizeof(int32_t));
    306 }
    307 
    308 bool SkReadBuffer::readPointArray(SkSpan<SkPoint> points) {
    309    return this->readArray(points.data(), points.size(), sizeof(SkPoint));
    310 }
    311 
    312 bool SkReadBuffer::readScalarArray(SkSpan<SkScalar> values) {
    313    return this->readArray(values.data(), values.size(), sizeof(SkScalar));
    314 }
    315 
    316 const void* SkReadBuffer::skipByteArray(size_t* size) {
    317    const uint32_t count = this->readUInt();
    318    const void* buf = this->skip(count);
    319    if (size) {
    320        *size = this->isValid() ? count : 0;
    321    }
    322    return buf;
    323 }
    324 
    325 sk_sp<SkData> SkReadBuffer::readByteArrayAsData() {
    326    size_t numBytes = this->getArrayCount();
    327    if (!this->validate(this->isAvailable(numBytes))) {
    328        return nullptr;
    329    }
    330 
    331    SkAutoMalloc buffer(numBytes);
    332    if (!this->readByteArray(buffer.get(), numBytes)) {
    333        return nullptr;
    334    }
    335    return SkData::MakeFromMalloc(buffer.release(), numBytes);
    336 }
    337 
    338 uint32_t SkReadBuffer::getArrayCount() {
    339    const size_t inc = sizeof(uint32_t);
    340    if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
    341        return 0;
    342    }
    343    return *((const uint32_t*)fCurr);
    344 }
    345 
    346 static sk_sp<SkImage> deserialize_image(sk_sp<SkData> data, SkDeserialProcs dProcs,
    347                                        std::optional<SkAlphaType> alphaType) {
    348    sk_sp<SkImage> image;
    349    if (dProcs.fImageDataProc) {
    350        image = dProcs.fImageDataProc(data, alphaType, dProcs.fImageCtx);
    351    } else if (dProcs.fImageProc) {
    352 #if !defined(SK_LEGACY_DESERIAL_IMAGE_PROC)
    353        image = dProcs.fImageProc(data->data(), data->size(), dProcs.fImageCtx);
    354 #else
    355        image = dProcs.fImageProc(data->data(), data->size(), alphaType, dProcs.fImageCtx);
    356 #endif
    357    }
    358    if (image) {
    359        return image;
    360    }
    361 #if !defined(SK_DISABLE_LEGACY_IMAGE_READBUFFER)
    362    // The default implementation will encode to PNG unless the input SkImages came from
    363    // a codec that was built-in (e.g. JPEG/WEBP). Thus, we should be sure to try all
    364    // available codecs when reading images out of an SKP.
    365    return SkImages::DeferredFromEncodedData(std::move(data), alphaType);
    366 #else
    367    SkDEBUGFAIL("Need to set image proc in SkDeserialProcs");
    368    return nullptr;
    369 #endif
    370 }
    371 
    372 static sk_sp<SkImage> add_mipmaps(sk_sp<SkImage> img, sk_sp<SkData> data,
    373                                  SkDeserialProcs dProcs, std::optional<SkAlphaType> alphaType) {
    374    SkMipmapBuilder builder(img->imageInfo());
    375 
    376    SkReadBuffer buffer(data->data(), data->size());
    377    int count = buffer.read32();
    378    if (builder.countLevels() != count) {
    379        return img;
    380    }
    381    for (int i = 0; i < count; ++i) {
    382        size_t size = buffer.read32();
    383        const void* ptr = buffer.skip(size);
    384        if (!ptr) {
    385            return img;
    386        }
    387        // This use of SkData::MakeWithoutCopy is safe because the image goes
    388        // out of scope after we read the pixels from it, so we are sure the
    389        // data (from buffer) outlives the image.
    390        sk_sp<SkImage> mip = deserialize_image(SkData::MakeWithoutCopy(ptr, size), dProcs,
    391                                               alphaType);
    392        if (!mip) {
    393            return img;
    394        }
    395 
    396        SkPixmap pm = builder.level(i);
    397        if (mip->dimensions() != pm.dimensions()) {
    398            return img;
    399        }
    400        if (!mip->readPixels(nullptr, pm, 0, 0)) {
    401            return img;
    402        }
    403    }
    404    if (!buffer.isValid()) {
    405        return img;
    406    }
    407    sk_sp<SkImage> raster = img->makeRasterImage(nullptr);
    408    if (!raster) {
    409        return img;
    410    }
    411    sk_sp<SkImage> rasterWithMips = builder.attachTo(raster);
    412    SkASSERT(rasterWithMips); // attachTo should never return null
    413    return rasterWithMips;
    414 }
    415 
    416 
    417 // If we see a corrupt stream, we return null (fail). If we just fail trying to decode
    418 // the image, we don't fail, but return a 1x1 empty image.
    419 sk_sp<SkImage> SkReadBuffer::readImage() {
    420    uint32_t flags = this->read32();
    421 
    422    std::optional<SkAlphaType> alphaType = std::nullopt;
    423    if (flags & SkWriteBufferImageFlags::kUnpremul) {
    424        alphaType = kUnpremul_SkAlphaType;
    425    }
    426    sk_sp<SkImage> image;
    427    {
    428        sk_sp<SkData> data = this->readByteArrayAsData();
    429        if (!data) {
    430            this->validate(false);
    431            return nullptr;
    432        }
    433        image = deserialize_image(data, fProcs, alphaType);
    434    }
    435 
    436    // This flag is not written by new SKPs anymore.
    437    if (flags & SkWriteBufferImageFlags::kHasSubsetRect) {
    438        SkIRect subset;
    439        this->readIRect(&subset);
    440        if (image) {
    441            image = image->makeSubset(nullptr, subset, {});
    442        }
    443    }
    444 
    445    if (flags & SkWriteBufferImageFlags::kHasMipmap) {
    446        sk_sp<SkData> data = this->readByteArrayAsData();
    447        if (!data) {
    448            this->validate(false);
    449            return nullptr;
    450        }
    451        if (image) {
    452            image = add_mipmaps(image, std::move(data), fProcs, alphaType);
    453        }
    454    }
    455    return image ? image : MakeEmptyImage(1, 1);
    456 }
    457 
    458 sk_sp<SkTypeface> SkReadBuffer::readTypeface() {
    459    // Read 32 bits (signed)
    460    //   0 -- return null (empty font)
    461    //  >0 -- index
    462    //  <0 -- custom (serial procs) : negative size in bytes
    463 
    464    int32_t index = this->read32();
    465    if (index == 0) {
    466        return nullptr;
    467    } else if (index > 0) {
    468        if (!this->validate(index <= fTFCount)) {
    469            return nullptr;
    470        }
    471        return fTFArray[index - 1];
    472    } else {    // custom
    473        size_t size = sk_negate_to_size_t(index);
    474        const void* data = this->skip(size);
    475        if (!this->validate(data != nullptr && fProcs.fTypefaceProc)) {
    476            return nullptr;
    477        }
    478        return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx);
    479    }
    480 }
    481 
    482 SkFlattenable* SkReadBuffer::readRawFlattenable() {
    483    SkFlattenable::Factory factory = nullptr;
    484 
    485    if (fFactoryCount > 0) {
    486        int32_t index = this->read32();
    487        if (0 == index || !this->isValid()) {
    488            return nullptr; // writer failed to give us the flattenable
    489        }
    490        if (index < 0) {
    491            this->validate(false);
    492            return nullptr;
    493        }
    494        index -= 1;     // we stored the index-base-1
    495        if ((unsigned)index >= (unsigned)fFactoryCount) {
    496            this->validate(false);
    497            return nullptr;
    498        }
    499        factory = fFactoryArray[index];
    500    } else {
    501        if (this->peekByte() != 0) {
    502            // If the first byte is non-zero, the flattenable is specified by a string.
    503            size_t ignored_length;
    504            if (const char* name = this->readString(&ignored_length)) {
    505                factory = SkFlattenable::NameToFactory(name);
    506                fFlattenableDict.set(fFlattenableDict.count() + 1, factory);
    507            }
    508        } else {
    509            // Read the index.  We are guaranteed that the first byte
    510            // is zeroed, so we must shift down a byte.
    511            uint32_t index = this->readUInt() >> 8;
    512            if (index == 0) {
    513                return nullptr; // writer failed to give us the flattenable
    514            }
    515 
    516            if (SkFlattenable::Factory* found = fFlattenableDict.find(index)) {
    517                factory = *found;
    518            }
    519        }
    520 
    521        if (!this->validate(factory != nullptr)) {
    522            return nullptr;
    523        }
    524    }
    525 
    526    // if we get here, factory may still be null, but if that is the case, the
    527    // failure was ours, not the writer.
    528    sk_sp<SkFlattenable> obj;
    529    uint32_t sizeRecorded = this->read32();
    530    if (factory) {
    531        size_t offset = this->offset();
    532        obj = (*factory)(*this);
    533        // check that we read the amount we expected
    534        size_t sizeRead = this->offset() - offset;
    535        if (sizeRecorded != sizeRead) {
    536            this->validate(false);
    537            return nullptr;
    538        }
    539    } else {
    540        // we must skip the remaining data
    541        this->skip(sizeRecorded);
    542    }
    543    if (!this->isValid()) {
    544        return nullptr;
    545    }
    546    return obj.release();
    547 }
    548 
    549 SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
    550    SkFlattenable* obj = this->readRawFlattenable();
    551    if (obj && obj->getFlattenableType() != ft) {
    552        this->validate(false);
    553        obj->unref();
    554        return nullptr;
    555    }
    556    return obj;
    557 }
    558 
    559 ///////////////////////////////////////////////////////////////////////////////////////////////////
    560 
    561 int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) {
    562    SkASSERT(min <= max);
    563    int32_t value = this->read32();
    564    if (value < min || value > max) {
    565        this->validate(false);
    566        value = min;
    567    }
    568    return value;
    569 }
    570 
    571 SkLegacyFQ SkReadBuffer::checkFilterQuality() {
    572    return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ);
    573 }