SkVertices: Fix out-of-memory errors in deserialization

It was easy to construct a buffer that indicated enormous amounts of
memory had to be allocated. An easy guard is to bail out if the buffer
can't possibly fill those buffers.

Simplify the code a bit: Four years ago (well past the earliest
supported SKP version), we stopped writing out triangle fan data (by
converting to tri-lists at construction time). Remove the
deserialization support, which makes the code easier to follow.

Bug: oss-fuzz:48228
Bug: oss-fuzz:48231
Change-Id: I941da595a250f940316a48cb54caeaec47768973
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/556021
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2022-07-06 13:13:47 -04:00 committed by SkCQ
parent 32871e6901
commit ad62d59450

View File

@ -279,13 +279,16 @@ sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
// Check that the header fields and buffer are valid. If this is data with the experimental
// custom attributes feature - we don't support that any more.
if (!safe || !buffer.isValid() || attrCount) {
// We also don't support serialized triangle-fan data. We stopped writing that long ago,
// so it should never appear in valid encoded data.
if (!safe || !buffer.isValid() || attrCount ||
mode == SkVertices::kTriangleFan_VertexMode) {
return nullptr;
}
const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
SkVertices::Sizes sizes(desc);
if (!sizes.isValid()) {
if (!sizes.isValid() || sizes.fArrays > buffer.available()) {
return nullptr;
}
@ -304,9 +307,7 @@ sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
}
buffer.readByteArray(builder.texCoords(), sizes.fTSize);
buffer.readByteArray(builder.colors(), sizes.fCSize);
size_t isize = (mode == SkVertices::kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
: sizes.fISize;
buffer.readByteArray(builder.indices(), isize);
buffer.readByteArray(builder.indices(), sizes.fISize);
if (!buffer.isValid()) {
return nullptr;