Add pdf_cjs_util_fuzzer.

Expose some CJS_Util methods for testing.
Disambiguate printx overloads for clarity.

Change-Id: I6b85846078677ca3977924602ce4c1101827d486
Reviewed-on: https://pdfium-review.googlesource.com/c/45017
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/cjs_publicmethods.cpp b/fxjs/cjs_publicmethods.cpp
index 38dac89..261e464 100644
--- a/fxjs/cjs_publicmethods.cpp
+++ b/fxjs/cjs_publicmethods.cpp
@@ -1365,7 +1365,7 @@
       wsFormat = L"99999-9999";
       break;
     case 2:
-      if (CJS_Util::printx(L"9999999999", wsSource).GetLength() >= 10)
+      if (CJS_Util::StringPrintx(L"9999999999", wsSource).GetLength() >= 10)
         wsFormat = L"(999) 999-9999";
       else
         wsFormat = L"999-9999";
@@ -1375,7 +1375,7 @@
       break;
   }
 
-  pEvent->Value() = CJS_Util::printx(wsFormat, wsSource);
+  pEvent->Value() = CJS_Util::StringPrintx(wsFormat, wsSource);
   return CJS_Result::Success();
 }
 
diff --git a/fxjs/cjs_util.cpp b/fxjs/cjs_util.cpp
index 6d883cc..2e77732 100644
--- a/fxjs/cjs_util.cpp
+++ b/fxjs/cjs_util.cpp
@@ -55,6 +55,16 @@
 #endif
 };
 
+enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
+
+wchar_t TranslateCase(wchar_t input, CaseMode eMode) {
+  if (eMode == kLowerCase && FXSYS_iswupper(input))
+    return input | 0x20;
+  if (eMode == kUpperCase && FXSYS_iswlower(input))
+    return input & ~0x20;
+  return input;
+}
+
 }  // namespace
 
 const JSMethodSpec CJS_Util::MethodSpecs[] = {
@@ -258,23 +268,13 @@
     return CJS_Result::Failure(JSMessage::kParamError);
 
   return CJS_Result::Success(
-      pRuntime->NewString(printx(pRuntime->ToWideString(params[0]),
-                                 pRuntime->ToWideString(params[1]))
+      pRuntime->NewString(StringPrintx(pRuntime->ToWideString(params[0]),
+                                       pRuntime->ToWideString(params[1]))
                               .AsStringView()));
 }
 
-enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
-
-static wchar_t TranslateCase(wchar_t input, CaseMode eMode) {
-  if (eMode == kLowerCase && FXSYS_iswupper(input))
-    return input | 0x20;
-  if (eMode == kUpperCase && FXSYS_iswlower(input))
-    return input & ~0x20;
-  return input;
-}
-
-WideString CJS_Util::printx(const WideString& wsFormat,
-                            const WideString& wsSource) {
+WideString CJS_Util::StringPrintx(const WideString& wsFormat,
+                                  const WideString& wsSource) {
   WideString wsResult;
   size_t iSourceIdx = 0;
   size_t iFormatIdx = 0;
diff --git a/fxjs/cjs_util.h b/fxjs/cjs_util.h
index 917d797..87fd263 100644
--- a/fxjs/cjs_util.h
+++ b/fxjs/cjs_util.h
@@ -26,8 +26,10 @@
   CJS_Util(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime);
   ~CJS_Util() override;
 
-  static WideString printx(const WideString& cFormat,
-                           const WideString& cSource);
+  // Exposed for testing.
+  static int ParseDataType(std::wstring* sFormat);
+  static WideString StringPrintx(const WideString& cFormat,
+                                 const WideString& cSource);
 
   JS_STATIC_METHOD(printd, CJS_Util);
   JS_STATIC_METHOD(printf, CJS_Util);
@@ -36,13 +38,10 @@
   JS_STATIC_METHOD(byteToChar, CJS_Util);
 
  private:
-  friend class CJS_Util_ParseDataType_Test;
-
   static int ObjDefnID;
   static const char kName[];
   static const JSMethodSpec MethodSpecs[];
 
-  static int ParseDataType(std::wstring* sFormat);
 
   CJS_Result printd(CJS_Runtime* pRuntime,
                     const std::vector<v8::Local<v8::Value>>& params);
diff --git a/testing/fuzzers/BUILD.gn b/testing/fuzzers/BUILD.gn
index df4cac0..ccee96b 100644
--- a/testing/fuzzers/BUILD.gn
+++ b/testing/fuzzers/BUILD.gn
@@ -38,6 +38,9 @@
     ":pdf_xml_fuzzer_src",
     ":pdfium_fuzzer_src",
   ]
+  if (pdf_enable_v8) {
+    deps += [ ":pdf_cjs_util_fuzzer_src" ]
+  }
   if (pdf_enable_xfa) {
     deps += [
       ":pdf_bidi_fuzzer_src",
@@ -116,6 +119,17 @@
   }
 }
 
+if (pdf_enable_v8) {
+  pdfium_fuzzer("pdf_cjs_util_fuzzer_src") {
+    sources = [
+      "pdf_cjs_util_fuzzer.cc",
+    ]
+    deps = [
+      "../../fxjs",
+    ]
+  }
+}
+
 if (pdf_enable_xfa) {
   pdfium_fuzzer("pdf_bidi_fuzzer_src") {
     sources = [
diff --git a/testing/fuzzers/pdf_cjs_util_fuzzer.cc b/testing/fuzzers/pdf_cjs_util_fuzzer.cc
new file mode 100644
index 0000000..a773244
--- /dev/null
+++ b/testing/fuzzers/pdf_cjs_util_fuzzer.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "core/fxcrt/widestring.h"
+#include "fxjs/cjs_util.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  auto* short_data = reinterpret_cast<const unsigned short*>(data);
+  size_t short_size = size / sizeof(unsigned short);
+  if (short_size > 1) {
+    WideString input = WideString::FromUTF16LE(short_data, short_size);
+    std::wstring winput(input.c_str(), input.GetLength());
+    CJS_Util::ParseDataType(&winput);
+  }
+  if (short_size > 2) {
+    size_t short_len1 = short_size / 2;
+    size_t short_len2 = short_size - short_len1;
+    WideString input1 = WideString::FromUTF16LE(short_data, short_len1);
+    WideString input2 =
+        WideString::FromUTF16LE(short_data + short_len1, short_len2);
+    CJS_Util::StringPrintx(input1, input2);
+  }
+  return 0;
+}