Add more guards to deserializing SkCustomTypeface
A well-defined font shouldn't have glyphs with infinite bounds nor
try to allocate more memory for path data than exists in the stream.
Change-Id: I3fc8ae83958acbb2d1ad28a5fcf63162253c14fd
Bug: oss-fuzz:49770
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/585956
Owners-Override: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 32dfff2..768de9b 100644
--- a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -122,7 +122,7 @@
}
//SkStreamSeekable
- /** Returns true if this stream can report it's current position. */
+ /** Returns true if this stream can report its current position. */
virtual bool hasPosition() const { return false; }
/** Returns the current position in the stream. If this cannot be done, returns 0. */
virtual size_t getPosition() const { return 0; }
@@ -140,7 +140,7 @@
virtual bool move(long /*offset*/) { return false; }
//SkStreamAsset
- /** Returns true if this stream can report it's total length. */
+ /** Returns true if this stream can report its total length. */
virtual bool hasLength() const { return false; }
/** Returns the total length of the stream. If this cannot be done, returns 0. */
virtual size_t getLength() const { return 0; }
diff --git a/src/utils/SkCustomTypeface.cpp b/src/utils/SkCustomTypeface.cpp
index 456d645..79470f0 100644
--- a/src/utils/SkCustomTypeface.cpp
+++ b/src/utils/SkCustomTypeface.cpp
@@ -458,7 +458,8 @@
for (int i = 0; i < glyphCount; ++i) {
uint32_t gtype;
- if (!stream->readU32(>ype)) {
+ if (!stream->readU32(>ype) ||
+ (gtype != GlyphType::kDrawable && gtype != GlyphType::kPath)) {
return nullptr;
}
@@ -468,7 +469,7 @@
}
SkRect bounds;
- if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds)) {
+ if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds) || !bounds.isFinite()) {
return nullptr;
}
@@ -477,6 +478,17 @@
if (stream->read(&sz, sizeof(sz)) != sizeof(sz)) {
return nullptr;
}
+
+ // The amount of bytes in the stream must be at least as big as sz, otherwise
+ // sz is invalid.
+ if (stream->hasLength() && stream->hasPosition()) {
+ SkASSERT(stream->getLength() >= stream->getPosition());
+ size_t remainingBytes = stream->getLength() - stream->getPosition();
+ if (sz > remainingBytes) {
+ return nullptr;
+ }
+ }
+
auto data = SkData::MakeUninitialized(sz);
if (stream->read(data->writable_data(), sz) != sz) {
return nullptr;