/* * Copyright 2019 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkTypes.h" #include "include/private/chromium/SkChromeRemoteGlyphCache.h" #include "src/core/SkDescriptor.h" #include "src/core/SkFontPriv.h" #include "src/core/SkReadBuffer.h" #include "src/core/SkScalerContext.h" #include "src/core/SkWriteBuffer.h" #include "src/gpu/ganesh/GrResourceProvider.h" #include "tests/Test.h" #include class SkDescriptorTestHelper { public: static void SetLength(SkDescriptor* desc, size_t length) { desc->fLength = length; } static void SetCount(SkDescriptor* desc, uint32_t count) { desc->fCount = count; } }; DEF_TEST(Descriptor_empty, r) { const size_t size = sizeof(SkDescriptor); auto desc = SkDescriptor::Alloc(size); REPORTER_ASSERT(r, desc->isValid()); REPORTER_ASSERT(r, desc->getLength() == size); } DEF_TEST(Descriptor_valid_simple, r) { const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec); auto desc = SkDescriptor::Alloc(size); SkScalerContextRec rec; desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); REPORTER_ASSERT(r, desc->isValid()); REPORTER_ASSERT(r, desc->getLength() == size); SkDescriptorTestHelper::SetLength(desc.get(), size - 4); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_valid_simple_extra_space, r) { const size_t extra_space = 100; const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec); auto desc = SkDescriptor::Alloc(size + extra_space); SkScalerContextRec rec; desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); REPORTER_ASSERT(r, desc->isValid()); REPORTER_ASSERT(r, desc->getLength() == size); SkDescriptorTestHelper::SetLength(desc.get(), size - 4); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_valid_more_tags, r) { const size_t effectSize = 16; const size_t testSize = 32; const size_t size = sizeof(SkDescriptor) + 3 * sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec) + effectSize + testSize; auto desc = SkDescriptor::Alloc(size); SkScalerContextRec rec; desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); desc->addEntry(kEffects_SkDescriptorTag, effectSize, nullptr); desc->addEntry(SkSetFourByteTag('t', 'e', 's', 't'), testSize, nullptr); REPORTER_ASSERT(r, desc->isValid()); REPORTER_ASSERT(r, desc->getLength() == size); SkDescriptorTestHelper::SetLength(desc.get(), size - 4); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_invalid_rec_size, r) { const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec) - 4; auto desc = SkDescriptor::Alloc(size); SkScalerContextRec rec; desc->addEntry(kRec_SkDescriptorTag, sizeof(rec) - 4, &rec); REPORTER_ASSERT(r, desc->getLength() == size); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_invalid_length, r) { const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry); const size_t effect_size = 1000; auto desc = SkDescriptor::Alloc(size); desc->addEntry(kEffects_SkDescriptorTag, effect_size, nullptr); SkDescriptorTestHelper::SetLength(desc.get(), size); REPORTER_ASSERT(r, !desc->isValid()); SkDescriptorTestHelper::SetLength(desc.get(), size + effect_size); REPORTER_ASSERT(r, desc->isValid()); } DEF_TEST(Descriptor_entry_too_big, r) { const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + 4; // Must be less than fLength, but big enough to be bigger then fLength when added. const size_t effect_size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry); auto desc = SkDescriptor::Alloc(size); desc->addEntry(kEffects_SkDescriptorTag, effect_size, nullptr); SkDescriptorTestHelper::SetLength(desc.get(), size); SkDescriptorTestHelper::SetCount(desc.get(), 2); REPORTER_ASSERT(r, !desc->isValid()); SkDescriptorTestHelper::SetLength(desc.get(), size); SkDescriptorTestHelper::SetCount(desc.get(), 1); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_entry_over_end, r) { auto desc = SkDescriptor::Alloc(36); // Make the start of the Entry be in the SkDescriptor, but the second half falls out side the // SkDescriptor. So: 12 (for descriptor) + 8 (for entry) + 12 (for entry length) = 32. An // An Entry is 8 bytes, so 4 bytes are < 36 and 4 bytes > 36. desc->addEntry(kEffects_SkDescriptorTag, 12, nullptr); SkDescriptorTestHelper::SetLength(desc.get(), 36); SkDescriptorTestHelper::SetCount(desc.get(), 2); REPORTER_ASSERT(r, !desc->isValid()); } DEF_TEST(Descriptor_flatten_unflatten, r) { { SkBinaryWriteBuffer writer; auto desc = SkDescriptor::Alloc(sizeof(SkDescriptor)); desc->computeChecksum(); desc->flatten(writer); auto data = writer.snapshotAsData(); SkReadBuffer reader{data->data(), data->size()}; auto ad = SkAutoDescriptor::MakeFromBuffer(reader); REPORTER_ASSERT(r, ad.has_value()); REPORTER_ASSERT(r, ad->getDesc()->isValid()); } { // broken header SkBinaryWriteBuffer writer; writer.writeInt(0); // fChecksum auto data = writer.snapshotAsData(); SkReadBuffer reader{data->data(), data->size()}; auto ad = SkAutoDescriptor::MakeFromBuffer(reader); REPORTER_ASSERT(r, !ad.has_value()); } { // length too big SkBinaryWriteBuffer writer; // Simulate a broken header writer.writeInt(0); // fChecksum writer.writeInt(4000); // fLength writer.writeInt(0); // fCount auto data = writer.snapshotAsData(); SkReadBuffer reader{data->data(), data->size()}; auto ad = SkAutoDescriptor::MakeFromBuffer(reader); REPORTER_ASSERT(r, !ad.has_value()); } { // length too small SkBinaryWriteBuffer writer; // Simulate a broken header writer.writeInt(0); // fChecksum writer.writeInt(3); // fLength writer.writeInt(0); // fCount auto data = writer.snapshotAsData(); SkReadBuffer reader{data->data(), data->size()}; auto ad = SkAutoDescriptor::MakeFromBuffer(reader); REPORTER_ASSERT(r, !ad.has_value()); } { // garbage in count SkBinaryWriteBuffer writer; // Simulate a broken header writer.writeInt(0); // fChecksum writer.writeInt(20); // fLength writer.writeInt(10); // fCount writer.writeInt(0); writer.writeInt(0); auto data = writer.snapshotAsData(); SkReadBuffer reader{data->data(), data->size()}; auto ad = SkAutoDescriptor::MakeFromBuffer(reader); REPORTER_ASSERT(r, !ad.has_value()); } }