Mark one remaining unsafe function in core/fpdfapi/edit.

This will allow the entire directory to be included into
UNSAFE checks once the format of the paths.txt file matures.

Change-Id: Ia57ebf136e7cdf7ce73928230a223884135a80d9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117933
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp b/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
index d1fede9..4c55b55 100644
--- a/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
+++ b/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
@@ -10,6 +10,8 @@
 #include <cmath>
 #include <ostream>
 
+#include "core/fxcrt/compiler_specific.h"
+
 namespace {
 
 constexpr unsigned kMaximumSkFloatToDecimalLength = 49;
@@ -96,6 +98,7 @@
 // Motivation: "PDF does not support [numbers] in exponential format
 // (such as 6.02e23)."  Otherwise, this function would rely on a
 // sprintf-type function from the standard library.
+// TODO(tsepez): should be UNSAFE_BUFFER_USAGE.
 unsigned SkFloatToDecimal(float value,
                           char output[kMaximumSkFloatToDecimalLength]) {
   // The longest result is -FLT_MIN.
@@ -108,109 +111,112 @@
   // abs(FLT_MIN_10_EXP) = number of zeros in FLT_MIN
   static_assert(kMaximumSkFloatToDecimalLength == 3 + 9 - FLT_MIN_10_EXP, "");
 
-  // section C.1 of the PDF 1.4 spec (http://goo.gl/0SCswJ) says that
-  // most PDF rasterizers will use fixed-point scalars that lack the
-  // dynamic range of floats.  Even if this is the case, I want to
-  // serialize these (uncommon) very small and very large scalar
-  // values with enough precision to allow a floating-point
-  // rasterizer to read them in with perfect accuracy.
-  // Experimentally, rasterizers such as pdfium do seem to benefit
-  // from this.  Rasterizers that rely on fixed-point scalars should
-  // gracefully ignore these values that they can not parse.
-  char* output_ptr = &output[0];
-  const char* const end = &output[kMaximumSkFloatToDecimalLength - 1];
-  // subtract one to leave space for '\0'.
+  // TODO(tsepez): this whole section is unsafe.
+  UNSAFE_BUFFERS({
+    // section C.1 of the PDF 1.4 spec (http://goo.gl/0SCswJ) says that
+    // most PDF rasterizers will use fixed-point scalars that lack the
+    // dynamic range of floats.  Even if this is the case, I want to
+    // serialize these (uncommon) very small and very large scalar
+    // values with enough precision to allow a floating-point
+    // rasterizer to read them in with perfect accuracy.
+    // Experimentally, rasterizers such as pdfium do seem to benefit
+    // from this.  Rasterizers that rely on fixed-point scalars should
+    // gracefully ignore these values that they can not parse.
+    char* output_ptr = &output[0];
+    const char* const end = &output[kMaximumSkFloatToDecimalLength - 1];
+    // subtract one to leave space for '\0'.
 
-  // This function is written to accept any possible input value,
-  // including non-finite values such as INF and NAN.  In that case,
-  // we ignore value-correctness and output a syntacticly-valid
-  // number.
-  if (value == INFINITY) {
-    value = FLT_MAX;  // nearest finite float.
-  }
-  if (value == -INFINITY) {
-    value = -FLT_MAX;  // nearest finite float.
-  }
-  if (!std::isfinite(value) || value == 0.0f) {
-    // NAN is unsupported in PDF.  Always output a valid number.
-    // Also catch zero here, as a special case.
-    *output_ptr++ = '0';
-    *output_ptr = '\0';
-    return static_cast<unsigned>(output_ptr - output);
-  }
-  if (value < 0.0) {
-    *output_ptr++ = '-';
-    value = -value;
-  }
-  assert(value >= 0.0f);
-
-  int binaryExponent;
-  (void)std::frexp(value, &binaryExponent);
-  static const double kLog2 = 0.3010299956639812;  // log10(2.0);
-  int decimalExponent = static_cast<int>(std::floor(kLog2 * binaryExponent));
-  int decimalShift = decimalExponent - 8;
-  double power = pow10(-decimalShift);
-  assert(value * power <= (double)INT_MAX);
-  int d = static_cast<int>(value * power + 0.5);
-  // assert(value == (float)(d * pow(10.0, decimalShift)));
-  assert(d <= 999999999);
-  if (d > 167772159) {  // floor(pow(10,1+log10(1<<24)))
-    // need one fewer decimal digits for 24-bit precision.
-    decimalShift = decimalExponent - 7;
-    // assert(power * 0.1 = pow10(-decimalShift));
-    // recalculate to get rounding right.
-    d = static_cast<int>(value * (power * 0.1) + 0.5);
-    assert(d <= 99999999);
-  }
-  while (d % 10 == 0) {
-    d /= 10;
-    ++decimalShift;
-  }
-  assert(d > 0);
-  // assert(value == (float)(d * pow(10.0, decimalShift)));
-  unsigned char buffer[9];  // decimal value buffer.
-  int bufferIndex = 0;
-  do {
-    buffer[bufferIndex++] = d % 10;
-    d /= 10;
-  } while (d != 0);
-  assert(bufferIndex <= (int)sizeof(buffer) && bufferIndex > 0);
-  if (decimalShift >= 0) {
-    do {
-      --bufferIndex;
-      *output_ptr++ = '0' + buffer[bufferIndex];
-    } while (bufferIndex);
-    for (int i = 0; i < decimalShift; ++i) {
-      *output_ptr++ = '0';
+    // This function is written to accept any possible input value,
+    // including non-finite values such as INF and NAN.  In that case,
+    // we ignore value-correctness and output a syntacticly-valid
+    // number.
+    if (value == INFINITY) {
+      value = FLT_MAX;  // nearest finite float.
     }
-  } else {
-    int placesBeforeDecimal = bufferIndex + decimalShift;
-    if (placesBeforeDecimal > 0) {
-      while (placesBeforeDecimal-- > 0) {
+    if (value == -INFINITY) {
+      value = -FLT_MAX;  // nearest finite float.
+    }
+    if (!std::isfinite(value) || value == 0.0f) {
+      // NAN is unsupported in PDF.  Always output a valid number.
+      // Also catch zero here, as a special case.
+      *output_ptr++ = '0';
+      *output_ptr = '\0';
+      return static_cast<unsigned>(output_ptr - output);
+    }
+    if (value < 0.0) {
+      *output_ptr++ = '-';
+      value = -value;
+    }
+    assert(value >= 0.0f);
+
+    int binaryExponent;
+    (void)std::frexp(value, &binaryExponent);
+    static const double kLog2 = 0.3010299956639812;  // log10(2.0);
+    int decimalExponent = static_cast<int>(std::floor(kLog2 * binaryExponent));
+    int decimalShift = decimalExponent - 8;
+    double power = pow10(-decimalShift);
+    assert(value * power <= (double)INT_MAX);
+    int d = static_cast<int>(value * power + 0.5);
+    // assert(value == (float)(d * pow(10.0, decimalShift)));
+    assert(d <= 999999999);
+    if (d > 167772159) {  // floor(pow(10,1+log10(1<<24)))
+      // need one fewer decimal digits for 24-bit precision.
+      decimalShift = decimalExponent - 7;
+      // assert(power * 0.1 = pow10(-decimalShift));
+      // recalculate to get rounding right.
+      d = static_cast<int>(value * (power * 0.1) + 0.5);
+      assert(d <= 99999999);
+    }
+    while (d % 10 == 0) {
+      d /= 10;
+      ++decimalShift;
+    }
+    assert(d > 0);
+    // assert(value == (float)(d * pow(10.0, decimalShift)));
+    unsigned char buffer[9];  // decimal value buffer.
+    int bufferIndex = 0;
+    do {
+      buffer[bufferIndex++] = d % 10;
+      d /= 10;
+    } while (d != 0);
+    assert(bufferIndex <= (int)sizeof(buffer) && bufferIndex > 0);
+    if (decimalShift >= 0) {
+      do {
         --bufferIndex;
         *output_ptr++ = '0' + buffer[bufferIndex];
-      }
-      *output_ptr++ = '.';
-    } else {
-      *output_ptr++ = '.';
-      int placesAfterDecimal = -placesBeforeDecimal;
-      while (placesAfterDecimal-- > 0) {
+      } while (bufferIndex);
+      for (int i = 0; i < decimalShift; ++i) {
         *output_ptr++ = '0';
       }
-    }
-    while (bufferIndex > 0) {
-      --bufferIndex;
-      *output_ptr++ = '0' + buffer[bufferIndex];
-      if (output_ptr == end) {
-        break;  // denormalized: don't need extra precision.
-                // Note: denormalized numbers will not have the same number of
-                // significantDigits, but do not need them to round-trip.
+    } else {
+      int placesBeforeDecimal = bufferIndex + decimalShift;
+      if (placesBeforeDecimal > 0) {
+        while (placesBeforeDecimal-- > 0) {
+          --bufferIndex;
+          *output_ptr++ = '0' + buffer[bufferIndex];
+        }
+        *output_ptr++ = '.';
+      } else {
+        *output_ptr++ = '.';
+        int placesAfterDecimal = -placesBeforeDecimal;
+        while (placesAfterDecimal-- > 0) {
+          *output_ptr++ = '0';
+        }
+      }
+      while (bufferIndex > 0) {
+        --bufferIndex;
+        *output_ptr++ = '0' + buffer[bufferIndex];
+        if (output_ptr == end) {
+          break;  // denormalized: don't need extra precision.
+                  // Note: denormalized numbers will not have the same number of
+                  // significantDigits, but do not need them to round-trip.
+        }
       }
     }
-  }
-  assert(output_ptr <= end);
-  *output_ptr = '\0';
-  return static_cast<unsigned>(output_ptr - output);
+    assert(output_ptr <= end);
+    *output_ptr = '\0';
+    return static_cast<unsigned>(output_ptr - output);
+  });
 }
 
 }  // namespace