Fix truncated webp images
Bug: b/65290323
If a webp file is truncated such that no rows can be decoded,
WebPIDecGetRGB does not initialize its "last_y" parameter. We use
rowsDecoded (passed as last_y) to determine which remaining rows to
fill.
Check the return value of WebPIDecGetRGB. If it fails (returns null),
or rowsDecoded is <= 0 (matching Chromium's check), return
kInvalidInput, since there is nothing to draw.
Note that this is a change in behavior for Android. Previously we
would decode an empty webp to just a transparent/black rectangle,
whereas now we simply fail. I think this is a change for the better.
Add a test which truncates a file to have 0 rows available and attempts
to decode it. msan verifies that we no longer depend on the
uninitialized value.
Stop attempting to test decoding subsets from an incomplete webp (in
CodecTest.cpp). Unless we have decoded the portion covered by the
subset, this will fail.
Remove test images inc0.webp (from both dm/ and colorspace/) and
inc1.webp. These just decode to transparent rectangles. Replace them
with inc2.webp and inc3.webp, which decode part of the image and then
have to fill with transparent.
Change-Id: I64d40be91c574b45963f9a43d8dd8f4929dd2939
Reviewed-on: https://skia-review.googlesource.com/50303
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: James Zern <jzern@google.com>
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
index 864fa96..baf3468 100644
--- a/src/codec/SkWebpCodec.cpp
+++ b/src/codec/SkWebpCodec.cpp
@@ -549,7 +549,7 @@
return kInvalidInput;
}
- int rowsDecoded;
+ int rowsDecoded = 0;
SkCodec::Result result;
switch (WebPIUpdate(idec, frame.fragment.bytes, frame.fragment.size)) {
case VP8_STATUS_OK:
@@ -557,7 +557,10 @@
result = kSuccess;
break;
case VP8_STATUS_SUSPENDED:
- WebPIDecGetRGB(idec, &rowsDecoded, nullptr, nullptr, nullptr);
+ if (!WebPIDecGetRGB(idec, &rowsDecoded, nullptr, nullptr, nullptr)
+ || rowsDecoded <= 0) {
+ return kInvalidInput;
+ }
*rowsDecodedPtr = rowsDecoded + dstY;
result = kIncompleteInput;
break;