Validate gradient DescriptorScope size during deserialization

Check that the reader has sufficient data before allocating buffers.

Bug: skia:7937
Change-Id: I2352d9a5cbace77b77c150a3a6439e8ac18b0dc5
Reviewed-on: https://skia-review.googlesource.com/127132
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
Florin Malita 2018-05-10 09:52:27 -04:00 committed by Skia Commit-Bot
parent ff6a7cd4d2
commit f77db110e1
2 changed files with 25 additions and 19 deletions

View File

@ -17,6 +17,7 @@
#include "SkMallocPixelRef.h"
#include "SkRadialGradient.h"
#include "SkReadBuffer.h"
#include "SkSafeMath.h"
#include "SkSweepGradient.h"
#include "SkTwoPointConicalGradient.h"
#include "SkWriteBuffer.h"
@ -71,6 +72,19 @@ void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
}
}
template <int N, typename T, bool MEM_MOVE>
static bool validate_array(SkReadBuffer& buffer, size_t count, SkSTArray<N, T, MEM_MOVE>* array) {
SkSafeMath safe;
const auto expectedSize = safe.mul(sizeof(T), count);
if (!buffer.validate(safe && expectedSize <= buffer.available())) {
return false;
}
array->resize_back(count);
return true;
}
bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
// New gradient format. Includes floating point color, color space, densely packed flags
uint32_t flags = buffer.readUInt();
@ -79,18 +93,13 @@ bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
fGradFlags = (flags >> kGradFlagsShift_GSF) & kGradFlagsMask_GSF;
fCount = buffer.getArrayCount();
if (fCount > kStorageCount) {
size_t allocSize = (sizeof(SkColor4f) + sizeof(SkScalar)) * fCount;
fDynamicStorage.reset(allocSize);
fColors = (SkColor4f*)fDynamicStorage.get();
fPos = (SkScalar*)(fColors + fCount);
} else {
fColors = fColorStorage;
fPos = fPosStorage;
}
if (!buffer.readColor4fArray(mutableColors(), fCount)) {
if (!(validate_array(buffer, fCount, &fColorStorage) &&
buffer.readColor4fArray(fColorStorage.begin(), fCount))) {
return false;
}
fColors = fColorStorage.begin();
if (SkToBool(flags & kHasColorSpace_GSF)) {
sk_sp<SkData> data = buffer.readByteArrayAsData();
fColorSpace = SkColorSpace::Deserialize(data->data(), data->size());
@ -98,9 +107,11 @@ bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
fColorSpace = nullptr;
}
if (SkToBool(flags & kHasPosition_GSF)) {
if (!buffer.readScalarArray(mutablePos(), fCount)) {
if (!(validate_array(buffer, fCount, &fPosStorage) &&
buffer.readScalarArray(fPosStorage.begin(), fCount))) {
return false;
}
fPos = fPosStorage.begin();
} else {
fPos = nullptr;
}

View File

@ -11,7 +11,6 @@
#include "SkGradientShader.h"
#include "SkArenaAlloc.h"
#include "SkAutoMalloc.h"
#include "SkMatrix.h"
#include "SkShaderBase.h"
#include "SkTArray.h"
@ -54,13 +53,9 @@ public:
SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
private:
enum {
kStorageCount = 16
};
SkColor4f fColorStorage[kStorageCount];
SkScalar fPosStorage[kStorageCount];
SkMatrix fLocalMatrixStorage;
SkAutoMalloc fDynamicStorage;
SkSTArray<16, SkColor4f, true> fColorStorage;
SkSTArray<16, SkScalar , true> fPosStorage;
SkMatrix fLocalMatrixStorage;
};
SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);