Fix unsafe buffer issues in fxcodec/gif

-- Convert to std::array<> and pdfium::span<>
-- Mark remaining regions UNSAFE_TODO().

Bug: 42271175
Change-Id: I31c18c081f678f5aa1fafda4ec6806664ea14a17
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119713
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp
index 0be2a41..71c9e66 100644
--- a/core/fxcodec/gif/cfx_gifcontext.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext.cpp
@@ -4,17 +4,13 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2154): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "core/fxcodec/gif/cfx_gifcontext.h"
 
 #include <stdint.h>
 #include <string.h>
 
 #include <algorithm>
+#include <array>
 #include <iterator>
 #include <utility>
 
@@ -27,7 +23,7 @@
 
 namespace {
 
-constexpr int32_t kGifInterlaceStep[4] = {8, 8, 4, 2};
+constexpr std::array<const int32_t, 4> kGifInterlaceStep = {{8, 8, 4, 2}};
 
 }  // namespace
 
@@ -247,8 +243,10 @@
       SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
       img_row_offset_ += img_row_avail_size_;
       img_row_avail_size_ = gif_img_row_bytes - img_row_offset_;
-      LZWDecompressor::Status ret = lzw_decompressor_->Decode(
-          gif_image->row_buffer.data() + img_row_offset_, &img_row_avail_size_);
+      auto img_row_span = pdfium::make_span(gif_image->row_buffer)
+                              .subspan(img_row_offset_, img_row_avail_size_);
+      LZWDecompressor::Status ret =
+          lzw_decompressor_->Decode(img_row_span.data(), &img_row_avail_size_);
       if (ret == LZWDecompressor::Status::kError) {
         DecodingFailureAtTailCleanup(gif_image);
         return GifDecoder::Status::kError;
@@ -278,9 +276,10 @@
             SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
             img_row_offset_ += img_row_avail_size_;
             img_row_avail_size_ = gif_img_row_bytes - img_row_offset_;
-            ret = lzw_decompressor_->Decode(
-                gif_image->row_buffer.data() + img_row_offset_,
-                &img_row_avail_size_);
+            img_row_span = pdfium::make_span(gif_image->row_buffer)
+                               .subspan(img_row_offset_, img_row_avail_size_);
+            ret = lzw_decompressor_->Decode(img_row_span.data(),
+                                            &img_row_avail_size_);
           }
         }
 
@@ -303,9 +302,10 @@
 
           img_row_offset_ = 0;
           img_row_avail_size_ = gif_img_row_bytes;
-          ret = lzw_decompressor_->Decode(
-              gif_image->row_buffer.data() + img_row_offset_,
-              &img_row_avail_size_);
+          img_row_span = pdfium::make_span(gif_image->row_buffer)
+                             .subspan(img_row_offset_, img_row_avail_size_);
+          ret = lzw_decompressor_->Decode(img_row_span.data(),
+                                          &img_row_avail_size_);
         }
 
         if (ret == LZWDecompressor::Status::kError) {
diff --git a/core/fxcodec/gif/lzw_decompressor.cpp b/core/fxcodec/gif/lzw_decompressor.cpp
index 45fd974..85f0a29 100644
--- a/core/fxcodec/gif/lzw_decompressor.cpp
+++ b/core/fxcodec/gif/lzw_decompressor.cpp
@@ -4,11 +4,6 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2154): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "core/fxcodec/gif/lzw_decompressor.h"
 
 #include <algorithm>
@@ -16,6 +11,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/numerics/safe_conversions.h"
 #include "core/fxcrt/ptr_util.h"
@@ -63,11 +59,11 @@
   FX_SAFE_UINT32 i = 0;
   if (decompressed_next_ != 0) {
     size_t extracted_size =
-        ExtractData(pdfium::make_span(dest_buf, *dest_size));
+        ExtractData(UNSAFE_TODO(pdfium::make_span(dest_buf, *dest_size)));
     if (decompressed_next_ != 0)
       return Status::kInsufficientDestSize;
 
-    dest_buf += extracted_size;
+    UNSAFE_TODO(dest_buf += extracted_size);
     i += extracted_size;
   }
 
@@ -80,7 +76,7 @@
       if (bits_left_ > 31)
         return Status::kError;
 
-      FX_SAFE_UINT32 safe_code = *next_in_++;
+      FX_SAFE_UINT32 safe_code = UNSAFE_TODO(*next_in_++);
       safe_code <<= bits_left_;
       safe_code |= code_store_;
       if (!safe_code.IsValid())
@@ -127,12 +123,12 @@
       }
 
       code_old_ = code;
-      size_t extracted_size = ExtractData(
-          pdfium::make_span(dest_buf, (*dest_size - i).ValueOrDie()));
+      size_t extracted_size = ExtractData(UNSAFE_TODO(
+          pdfium::make_span(dest_buf, (*dest_size - i).ValueOrDie())));
       if (decompressed_next_ != 0) {
         return Status::kInsufficientDestSize;
       }
-      dest_buf += extracted_size;
+      UNSAFE_TODO(dest_buf += extracted_size);
       i += extracted_size;
     }
   }
@@ -195,9 +191,9 @@
     return 0;
   }
   size_t copy_size = std::min(dest_span.size(), decompressed_next_);
-  std::reverse_copy(decompressed_.data() + decompressed_next_ - copy_size,
-                    decompressed_.data() + decompressed_next_,
-                    dest_span.data());
+  UNSAFE_TODO(std::reverse_copy(
+      decompressed_.data() + decompressed_next_ - copy_size,
+      decompressed_.data() + decompressed_next_, dest_span.data()));
   decompressed_next_ -= copy_size;
   return copy_size;
 }
diff --git a/core/fxcodec/gif/lzw_decompressor.h b/core/fxcodec/gif/lzw_decompressor.h
index a58b25e..131d327 100644
--- a/core/fxcodec/gif/lzw_decompressor.h
+++ b/core/fxcodec/gif/lzw_decompressor.h
@@ -10,6 +10,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 
 #include "core/fxcodec/gif/cfx_gif.h"
@@ -71,7 +72,7 @@
   uint32_t avail_in_ = 0;
   uint8_t bits_left_ = 0;
   uint32_t code_store_ = 0;
-  CodeEntry code_table_[GIF_MAX_LZW_CODE];
+  std::array<CodeEntry, GIF_MAX_LZW_CODE> code_table_;
 };
 
 }  // namespace fxcodec