SkWuffsCodec: Initialize memory when incomplete
Bug: oss-fuzz:11800
We already had code that initialized the output memory, but it assumed
that we would later copy from wuffs' work buffer. If the dirty rect is
empty, we don't do that. Rearrange the wuffs decode so we can know that
the dirty rect is empty when we decide whether to initialize.
Change-Id: I45fdd4270906b4c240ec087d20c24fb107a1dc07
Reviewed-on: https://skia-review.googlesource.com/c/189866
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Nigel Tao <nigeltao@google.com>
diff --git a/src/codec/SkWuffsCodec.cpp b/src/codec/SkWuffsCodec.cpp
index 74e6b14..669862f 100644
--- a/src/codec/SkWuffsCodec.cpp
+++ b/src/codec/SkWuffsCodec.cpp
@@ -432,12 +432,30 @@
return SkCodec::kInternalError;
}
+ SkCodec::Result result = SkCodec::kSuccess;
+ const char* status = this->decodeFrame();
+ const bool independent = independent_frame(this, options().fFrameIndex);
+ if (status != nullptr) {
+ if (status == wuffs_base__suspension__short_read) {
+ result = SkCodec::kIncompleteInput;
+ } else {
+ SkCodecPrintf("decodeFrame: %s", status);
+ result = SkCodec::kErrorInInput;
+ }
+
+ if (!independent) {
+ // For a dependent frame, we cannot blend the partial result, since
+ // that will overwrite the contribution from prior frames.
+ return result;
+ }
+ }
+
// In Wuffs, a paletted image is always 1 byte per pixel.
static constexpr size_t src_bpp = 1;
wuffs_base__table_u8 pixels = fPixelBuffer.plane(0);
int scaledHeight = dstInfo().height();
- const bool independent = independent_frame(this, options().fFrameIndex);
wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
+ wuffs_base__rect_ie_u32 dirty_rect = fDecoder->frame_dirty_rect();
if (!fSwizzler) {
auto bounds = SkIRect::MakeLTRB(frame_rect.min_incl_x, frame_rect.min_incl_y,
frame_rect.max_excl_x, frame_rect.max_excl_y);
@@ -457,7 +475,7 @@
// If the frame rect does not fill the output, ensure that those pixels are not
// left uninitialized either.
- if (independent && bounds != this->bounds()) {
+ if (independent && (bounds != this->bounds() || dirty_rect.is_empty())) {
auto fillInfo = dstInfo().makeWH(fSwizzler->fillWidth(), scaledHeight);
SkSampler::Fill(fillInfo, fIncrDecDst, fIncrDecRowBytes, options().fZeroInitialized);
}
@@ -484,26 +502,7 @@
*rowsDecoded = scaledHeight;
}
- SkCodec::Result result = SkCodec::kSuccess;
- const char* status = this->decodeFrame();
- if (status != nullptr) {
- if (status == wuffs_base__suspension__short_read) {
- result = SkCodec::kIncompleteInput;
- } else {
- SkCodecPrintf("decodeFrame: %s", status);
- result = SkCodec::kErrorInInput;
- }
-
- if (!independent) {
- // For a dependent frame, we cannot blend the partial result, since
- // that will overwrite the contribution from prior frames with all
- // zeroes that were written to |pixels| above.
- return result;
- }
- }
-
// If the frame's dirty rect is empty, no need to swizzle.
- wuffs_base__rect_ie_u32 dirty_rect = fDecoder->frame_dirty_rect();
if (!dirty_rect.is_empty()) {
if (!fColorTableFilled) {
fColorTableFilled = true;