Check ANSDec status earlier in DecodeLZW()

Otherwise it might try to read data from the output buffer
which may have been deallocated before calling the Decoder
destructor which swaps to the context of any started partial
tile decoding. Here it was resuming inside InitializeLZW(),
storing segments with invalid pointers that were written in
EmitRows(), triggering asan.

Change-Id: I17f01f189cee4c0bb2345d3189792deba1d9899f
Reviewed-on: https://chromium-review.googlesource.com/c/codecs/libwebp2/+/3796812
Tested-by: WebM Builds <builds@webmproject.org>
Reviewed-by: James Zern <jzern@google.com>
diff --git a/src/dec/lossless/lzw_dec.cc b/src/dec/lossless/lzw_dec.cc
index b003b26..d29db6c 100644
--- a/src/dec/lossless/lzw_dec.cc
+++ b/src/dec/lossless/lzw_dec.cc
@@ -42,16 +42,18 @@
 }
 
 // Initializes code table for the first pixel or when clear cache signal.
-void InitializeLZW(uint32_t num_colors, const int16_t* const src_end,
-                   WP2::Vector<ColorSegment>* const segments,
-                   WP2::ANSDec* const dec, ColorSegment* const seg,
-                   int16_t** src) {
+WP2Status InitializeLZW(uint32_t num_colors, const int16_t* const src_end,
+                        WP2::Vector<ColorSegment>* const segments,
+                        WP2::ANSDec* const dec, ColorSegment* const seg,
+                        int16_t** src) {
   segments->resize_no_check(num_colors + 1);
   // Exclude the possibility of receiving clear code.
   static_assert(kClearCode == 0, "kClearCode must be 0.");
   const int32_t cur_code = dec->ReadRange(1, num_colors, "code");
+  WP2_CHECK_STATUS(dec->GetStatus());
   *seg = {*src, 1};
   PushSegmentToVector((*segments)[cur_code], src_end, src);
+  return WP2_STATUS_OK;
 }
 }  // namespace
 
@@ -70,7 +72,8 @@
 
   if (last_pixel_ == 0) {
     // Initialize output as the first code segment.
-    InitializeLZW(num_colors_, src_end, &lzw_segments_, dec_, &prev_seg, &src);
+    WP2_CHECK_STATUS(InitializeLZW(num_colors_, src_end, &lzw_segments_, dec_,
+                                   &prev_seg, &src));
   } else {
     prev_seg = lzw_last_seg_;
   }
@@ -81,14 +84,16 @@
       // Segments must be restarted.
       // Next code is necessarily of a simple single color segment.
       // Behaviour should be similar to starting code.
-      InitializeLZW(num_colors_, src_end, &lzw_segments_, dec_, &cur_seg, &src);
+      WP2_CHECK_STATUS(InitializeLZW(num_colors_, src_end, &lzw_segments_, dec_,
+                                     &cur_seg, &src));
     } else {
       // The range can go up to segments size (inclusive),
       // since code read might be of a new code.
       const int32_t cur_code = dec_->ReadRange(0, lzw_segments_.size(), "code");
+      WP2_CHECK_STATUS(dec_->GetStatus());
       if (cur_code == kClearCode) {
-        InitializeLZW(num_colors_, src_end, &lzw_segments_, dec_, &cur_seg,
-                      &src);
+        WP2_CHECK_STATUS(InitializeLZW(num_colors_, src_end, &lzw_segments_,
+                                       dec_, &cur_seg, &src));
       } else if (cur_code == static_cast<int32_t>(lzw_segments_.size())) {
         // New code.
         lzw_segments_.push_back_no_resize({src, prev_seg.num_pixels + 1});
@@ -114,7 +119,6 @@
     prev_seg = cur_seg;
   }
   lzw_last_seg_ = prev_seg;
-  WP2_CHECK_STATUS(dec_->GetStatus());
   if (src_out != nullptr) *src_out = src;
   return WP2_STATUS_OK;
 }