Remove out-parameters from FlateUncompress()

Return a struct instead. Add struct DataAndBytesConsumed in its own file
for reuse by other codec decoders in the future.

Change-Id: Id66d1e253270b22b138de7dddc401d82eda6c97e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119133
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/BUILD.gn b/core/fxcodec/BUILD.gn
index 588cd2d..46bdb06 100644
--- a/core/fxcodec/BUILD.gn
+++ b/core/fxcodec/BUILD.gn
@@ -11,6 +11,8 @@
     "basic/basicmodule.h",
     "cfx_codec_memory.cpp",
     "cfx_codec_memory.h",
+    "data_and_bytes_consumed.cpp",
+    "data_and_bytes_consumed.h",
     "fax/faxmodule.cpp",
     "fax/faxmodule.h",
     "flate/flatemodule.cpp",
diff --git a/core/fxcodec/data_and_bytes_consumed.cpp b/core/fxcodec/data_and_bytes_consumed.cpp
new file mode 100644
index 0000000..6e83f34
--- /dev/null
+++ b/core/fxcodec/data_and_bytes_consumed.cpp
@@ -0,0 +1,25 @@
+// Copyright 2024 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcodec/data_and_bytes_consumed.h"
+
+#include <utility>
+
+namespace fxcodec {
+
+DataAndBytesConsumed::DataAndBytesConsumed(
+    std::unique_ptr<uint8_t, FxFreeDeleter> data,
+    uint32_t size,
+    uint32_t bytes_consumed)
+    : data(std::move(data)), size(size), bytes_consumed(bytes_consumed) {}
+
+DataAndBytesConsumed::DataAndBytesConsumed(DataAndBytesConsumed&&) noexcept =
+    default;
+
+DataAndBytesConsumed& DataAndBytesConsumed::operator=(
+    DataAndBytesConsumed&&) noexcept = default;
+
+DataAndBytesConsumed::~DataAndBytesConsumed() = default;
+
+}  // namespace fxcodec
diff --git a/core/fxcodec/data_and_bytes_consumed.h b/core/fxcodec/data_and_bytes_consumed.h
new file mode 100644
index 0000000..1aef085
--- /dev/null
+++ b/core/fxcodec/data_and_bytes_consumed.h
@@ -0,0 +1,37 @@
+// Copyright 2024 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CORE_FXCODEC_DATA_AND_BYTES_CONSUMED_H_
+#define CORE_FXCODEC_DATA_AND_BYTES_CONSUMED_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "core/fxcrt/fx_memory_wrappers.h"
+
+namespace fxcodec {
+
+struct DataAndBytesConsumed {
+  DataAndBytesConsumed(std::unique_ptr<uint8_t, FxFreeDeleter> data,
+                       uint32_t size,
+                       uint32_t bytes_consumed);
+  DataAndBytesConsumed(DataAndBytesConsumed&) = delete;
+  DataAndBytesConsumed& operator=(DataAndBytesConsumed&) = delete;
+  DataAndBytesConsumed(DataAndBytesConsumed&&) noexcept;
+  DataAndBytesConsumed& operator=(DataAndBytesConsumed&&) noexcept;
+  ~DataAndBytesConsumed();
+
+  // TODO(crbug.com/pdfium/1872): Replace with DataVector.
+  std::unique_ptr<uint8_t, FxFreeDeleter> data;
+  uint32_t size;
+  // TODO(thestig): Consider replacing with std::optional<size_t>.
+  uint32_t bytes_consumed;
+};
+
+}  // namespace fxcodec
+
+using DataAndBytesConsumed = fxcodec::DataAndBytesConsumed;
+
+#endif  // CORE_FXCODEC_DATA_AND_BYTES_CONSUMED_H_
diff --git a/core/fxcodec/flate/flatemodule.cpp b/core/fxcodec/flate/flatemodule.cpp
index 88a93c8..4933219 100644
--- a/core/fxcodec/flate/flatemodule.cpp
+++ b/core/fxcodec/flate/flatemodule.cpp
@@ -19,6 +19,7 @@
 #include <utility>
 #include <vector>
 
+#include "core/fxcodec/data_and_bytes_consumed.h"
 #include "core/fxcodec/scanlinedecoder.h"
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/data_vector.h"
@@ -549,17 +550,12 @@
   return true;
 }
 
-void FlateUncompress(pdfium::span<const uint8_t> src_buf,
-                     uint32_t orig_size,
-                     std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
-                     uint32_t* dest_size,
-                     uint32_t* offset) {
-  dest_buf->reset();
-  *dest_size = 0;
-
+DataAndBytesConsumed FlateUncompress(pdfium::span<const uint8_t> src_buf,
+                                     uint32_t orig_size) {
   std::unique_ptr<z_stream, FlateDeleter> context(FlateInit());
-  if (!context)
-    return;
+  if (!context) {
+    return {nullptr, 0u, 0u};
+  }
 
   FlateInput(context.get(), src_buf);
 
@@ -574,7 +570,6 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
       FX_Alloc(uint8_t, guess_size + 1));
   guess_buf.get()[guess_size] = '\0';
-
   std::vector<std::unique_ptr<uint8_t, FxFreeDeleter>> result_tmp_bufs;
   {
     std::unique_ptr<uint8_t, FxFreeDeleter> cur_buf = std::move(guess_buf);
@@ -595,17 +590,16 @@
   // The TotalOut size returned from the library may not be big enough to
   // handle the content the library returns. We can only handle items
   // up to 4GB in size.
-  *dest_size = FlateGetPossiblyTruncatedTotalOut(context.get());
-  *offset = FlateGetPossiblyTruncatedTotalIn(context.get());
+  const uint32_t dest_size = FlateGetPossiblyTruncatedTotalOut(context.get());
+  const uint32_t offset = FlateGetPossiblyTruncatedTotalIn(context.get());
   if (result_tmp_bufs.size() == 1) {
-    *dest_buf = std::move(result_tmp_bufs[0]);
-    return;
+    return {std::move(result_tmp_bufs.front()), dest_size, offset};
   }
 
   std::unique_ptr<uint8_t, FxFreeDeleter> result_buf(
-      FX_Alloc(uint8_t, *dest_size));
+      FX_Alloc(uint8_t, dest_size));
   uint32_t result_pos = 0;
-  uint32_t remaining = *dest_size;
+  uint32_t remaining = dest_size;
   for (size_t i = 0; i < result_tmp_bufs.size(); i++) {
     std::unique_ptr<uint8_t, FxFreeDeleter> tmp_buf =
         std::move(result_tmp_bufs[i]);
@@ -618,7 +612,7 @@
     result_pos += cp_size;
     remaining -= cp_size;
   }
-  *dest_buf = std::move(result_buf);
+  return {std::move(result_buf), dest_size, offset};
 }
 
 enum class PredictorType : uint8_t { kNone, kFlate, kPng };
@@ -857,25 +851,29 @@
     std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
     uint32_t* dest_size) {
   dest_buf->reset();
-  uint32_t offset = 0;
+  uint32_t bytes_consumed = 0;
   PredictorType predictor_type = GetPredictor(predictor);
 
   if (bLZW) {
     auto decoder = std::make_unique<CLZWDecoder>(src_span, bEarlyChange);
-    if (!decoder->Decode())
+    if (!decoder->Decode()) {
       return FX_INVALID_OFFSET;
+    }
 
-    offset = decoder->GetSrcSize();
+    bytes_consumed = decoder->GetSrcSize();
     *dest_size = decoder->GetDestSize();
     *dest_buf = decoder->TakeDestBuf();
   } else {
-    FlateUncompress(src_span, estimated_size, dest_buf, dest_size, &offset);
+    DataAndBytesConsumed result = FlateUncompress(src_span, estimated_size);
+    *dest_buf = std::move(result.data);
+    *dest_size = result.size;
+    bytes_consumed = result.bytes_consumed;
   }
 
   bool ret = false;
   switch (predictor_type) {
     case PredictorType::kNone:
-      return offset;
+      return bytes_consumed;
     case PredictorType::kPng:
       ret =
           PNG_Predictor(Colors, BitsPerComponent, Columns, dest_buf, dest_size);
@@ -885,7 +883,7 @@
                            dest_size);
       break;
   }
-  return ret ? offset : FX_INVALID_OFFSET;
+  return ret ? bytes_consumed : FX_INVALID_OFFSET;
 }
 
 // static