Make RunLengthDecode()'s buffer out parameter a unique_ptr.

Change-Id: I1dc99831a564e88035c317455411f1eba9aa41c4
Reviewed-on: https://pdfium-review.googlesource.com/41852
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index fe67634..69205cb 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -70,16 +70,6 @@
                             uint32_t* dest_size) {
   *dest_buf = nullptr;
   *dest_size = 0;
-  if (decoder == "CCITTFaxDecode" || decoder == "CCF") {
-    std::unique_ptr<CCodec_ScanlineDecoder> pDecoder =
-        CreateFaxDecoder(src_span, width, height, pParam);
-    return DecodeAllScanlines(std::move(pDecoder), dest_buf, dest_size);
-  }
-  std::unique_ptr<uint8_t, FxFreeDeleter> ignored_result;
-  if (decoder == "ASCII85Decode" || decoder == "A85")
-    return A85Decode(src_span, &ignored_result, dest_size);
-  if (decoder == "ASCIIHexDecode" || decoder == "AHx")
-    return HexDecode(src_span, &ignored_result, dest_size);
   if (decoder == "FlateDecode" || decoder == "Fl") {
     return FlateOrLZWDecode(false, src_span, pParam, *dest_size, dest_buf,
                             dest_size);
@@ -93,8 +83,19 @@
             !pParam || pParam->GetIntegerFor("ColorTransform", 1));
     return DecodeAllScanlines(std::move(pDecoder), dest_buf, dest_size);
   }
+  if (decoder == "CCITTFaxDecode" || decoder == "CCF") {
+    std::unique_ptr<CCodec_ScanlineDecoder> pDecoder =
+        CreateFaxDecoder(src_span, width, height, pParam);
+    return DecodeAllScanlines(std::move(pDecoder), dest_buf, dest_size);
+  }
+
+  std::unique_ptr<uint8_t, FxFreeDeleter> ignored_result;
+  if (decoder == "ASCII85Decode" || decoder == "A85")
+    return A85Decode(src_span, &ignored_result, dest_size);
+  if (decoder == "ASCIIHexDecode" || decoder == "AHx")
+    return HexDecode(src_span, &ignored_result, dest_size);
   if (decoder == "RunLengthDecode" || decoder == "RL")
-    return RunLengthDecode(src_span, dest_buf, dest_size);
+    return RunLengthDecode(src_span, &ignored_result, dest_size);
 
   return FX_INVALID_OFFSET;
 }
diff --git a/core/fpdfapi/parser/fpdf_parser_decode.cpp b/core/fpdfapi/parser/fpdf_parser_decode.cpp
index efa60d8..9041666 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_decode.cpp
@@ -210,7 +210,7 @@
 }
 
 uint32_t RunLengthDecode(pdfium::span<const uint8_t> src_span,
-                         uint8_t** dest_buf,
+                         std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
                          uint32_t* dest_size) {
   size_t i = 0;
   *dest_size = 0;
@@ -234,7 +234,8 @@
   if (*dest_size >= kMaxStreamSize)
     return FX_INVALID_OFFSET;
 
-  *dest_buf = FX_Alloc(uint8_t, *dest_size);
+  dest_buf->reset(FX_Alloc(uint8_t, *dest_size));
+  pdfium::span<uint8_t> dest_span(dest_buf->get(), *dest_size);
   i = 0;
   int dest_count = 0;
   while (i < src_span.size()) {
@@ -247,17 +248,17 @@
       if (buf_left < copy_len) {
         uint32_t delta = copy_len - buf_left;
         copy_len = buf_left;
-        memset(*dest_buf + dest_count + copy_len, '\0', delta);
+        memset(&dest_span[dest_count + copy_len], '\0', delta);
       }
       auto copy_span = src_span.subspan(i + 1, copy_len);
-      memcpy(*dest_buf + dest_count, copy_span.data(), copy_span.size());
+      memcpy(&dest_span[dest_count], copy_span.data(), copy_span.size());
       dest_count += src_span[i] + 1;
       i += src_span[i] + 2;
     } else {
       int fill = 0;
       if (i < src_span.size() - 1)
         fill = src_span[i + 1];
-      memset(*dest_buf + dest_count, fill, 257 - src_span[i]);
+      memset(&dest_span[dest_count], fill, 257 - src_span[i]);
       dest_count += 257 - src_span[i];
       i += 2;
     }
@@ -409,7 +410,9 @@
         *pImageParams = pParam;
         return true;
       }
-      offset = RunLengthDecode(last_span, &new_buf, &new_size);
+      std::unique_ptr<uint8_t, FxFreeDeleter> result;
+      offset = RunLengthDecode(last_span, &result, &new_size);
+      new_buf = result.release();
     } else {
       // If we get here, assume it's an image decoder.
       if (decoder == "DCT")
diff --git a/core/fpdfapi/parser/fpdf_parser_decode.h b/core/fpdfapi/parser/fpdf_parser_decode.h
index eb7beac..0032b97 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode.h
+++ b/core/fpdfapi/parser/fpdf_parser_decode.h
@@ -48,7 +48,7 @@
                      uint32_t* dest_size);
 
 uint32_t RunLengthDecode(pdfium::span<const uint8_t> src_span,
-                         uint8_t** dest_buf,
+                         std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
                          uint32_t* dest_size);
 
 uint32_t A85Decode(pdfium::span<const uint8_t> src_span,
diff --git a/core/fxcodec/codec/fx_codec_rle_unittest.cpp b/core/fxcodec/codec/fx_codec_rle_unittest.cpp
index 62ea4e7..3ee0aa6 100644
--- a/core/fxcodec/codec/fx_codec_rle_unittest.cpp
+++ b/core/fxcodec/codec/fx_codec_rle_unittest.cpp
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include <limits>
+#include <memory>
 
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
 #include "core/fxcodec/codec/ccodec_basicmodule.h"
@@ -63,40 +64,37 @@
 
   // Case 1:
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size));
-  uint8_t* decoded_buf = nullptr;
+  std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf;
   uint32_t decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_1), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_1[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_1[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 
   // Case 2:
   dest_buf = nullptr;
   dest_size = 0;
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size));
-  decoded_buf = nullptr;
+  decoded_buf.reset();
   decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_2), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_2[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_2[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 
   // Case 3:
   dest_buf = nullptr;
   dest_size = 0;
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size));
-  decoded_buf = nullptr;
+  decoded_buf.reset();
   decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_3), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_3[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_3[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 }
 
 // Check that runs longer than 128 are broken up properly, both matched and
@@ -128,51 +126,47 @@
 
   // Case 1:
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size));
-  uint8_t* decoded_buf = nullptr;
+  std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf;
   uint32_t decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_1), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_1[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_1[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 
   // Case 2:
   dest_buf = nullptr;
   dest_size = 0;
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size));
-  decoded_buf = nullptr;
+  decoded_buf.reset();
   decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_2), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_2[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_2[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 
   // Case 3:
   dest_buf = nullptr;
   dest_size = 0;
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size));
-  decoded_buf = nullptr;
+  decoded_buf.reset();
   decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_3), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_3[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_3[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 
   // Case 4:
   dest_buf = nullptr;
   dest_size = 0;
   EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_4, &dest_buf, &dest_size));
-  decoded_buf = nullptr;
+  decoded_buf.reset();
   decoded_size = 0;
   RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size);
   ASSERT_EQ(sizeof(src_buf_4), decoded_size);
   for (uint32_t i = 0; i < decoded_size; i++)
-    EXPECT_EQ(src_buf_4[i], decoded_buf[i]) << " at " << i;
+    EXPECT_EQ(src_buf_4[i], decoded_buf.get()[i]) << " at " << i;
   FX_Free(dest_buf);
-  FX_Free(decoded_buf);
 }