|  | // Copyright 2019 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 "xfa/fgas/crt/cfgas_stringformatter.h" | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <iterator> | 
|  |  | 
|  | #include "core/fxcrt/cfx_datetime.h" | 
|  | #include "core/fxcrt/fx_string.h" | 
|  | #include "public/fpdfview.h" | 
|  | #include "testing/fuzzers/pdfium_fuzzer_util.h" | 
|  | #include "testing/fuzzers/xfa_process_state.h" | 
|  | #include "v8/include/cppgc/heap.h" | 
|  | #include "v8/include/cppgc/persistent.h" | 
|  | #include "xfa/fxfa/parser/cxfa_localemgr.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | const wchar_t* const kLocales[] = {L"en", L"fr", L"jp", L"zh"}; | 
|  | const CFGAS_StringFormatter::DateTimeType kTypes[] = { | 
|  | CFGAS_StringFormatter::DateTimeType::kDate, | 
|  | CFGAS_StringFormatter::DateTimeType::kTime, | 
|  | CFGAS_StringFormatter::DateTimeType::kDateTime, | 
|  | CFGAS_StringFormatter::DateTimeType::kTimeDate}; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | 
|  | if (size < 5 || size > 128)  // Big strings are unlikely to help. | 
|  | return 0; | 
|  |  | 
|  | auto* state = static_cast<XFAProcessState*>(FPDF_GetFuzzerPerProcessState()); | 
|  | cppgc::Heap* heap = state->GetHeap(); | 
|  |  | 
|  | uint8_t test_selector = data[0] % 10; | 
|  | uint8_t locale_selector = data[1] % std::size(kLocales); | 
|  | uint8_t type_selector = data[2] % std::size(kTypes); | 
|  | data += 3; | 
|  | size -= 3; | 
|  |  | 
|  | size_t pattern_len = size / 2; | 
|  | size_t value_len = size - pattern_len; | 
|  | WideString pattern = | 
|  | WideString::FromLatin1(ByteStringView(data, pattern_len)); | 
|  | WideString value = | 
|  | WideString::FromLatin1(ByteStringView(data + pattern_len, value_len)); | 
|  |  | 
|  | auto fmt = std::make_unique<CFGAS_StringFormatter>(pattern); | 
|  |  | 
|  | WideString result; | 
|  | CFX_DateTime dt; | 
|  | switch (test_selector) { | 
|  | case 0: | 
|  | fmt->FormatText(value, &result); | 
|  | break; | 
|  | case 1: { | 
|  | auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>( | 
|  | heap->GetAllocationHandle(), heap, nullptr, | 
|  | kLocales[locale_selector]); | 
|  | fmt->FormatNum(mgr, value, &result); | 
|  | break; | 
|  | } | 
|  | case 2: { | 
|  | auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>( | 
|  | heap->GetAllocationHandle(), heap, nullptr, | 
|  | kLocales[locale_selector]); | 
|  | fmt->FormatDateTime(mgr, value, kTypes[type_selector], &result); | 
|  | break; | 
|  | } | 
|  | case 3: { | 
|  | fmt->FormatNull(&result); | 
|  | break; | 
|  | } | 
|  | case 4: { | 
|  | fmt->FormatZero(&result); | 
|  | break; | 
|  | } | 
|  | case 5: { | 
|  | fmt->ParseText(value, &result); | 
|  | break; | 
|  | } | 
|  | case 6: { | 
|  | auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>( | 
|  | heap->GetAllocationHandle(), heap, nullptr, | 
|  | kLocales[locale_selector]); | 
|  | fmt->ParseNum(mgr, value, &result); | 
|  | break; | 
|  | } | 
|  | case 7: { | 
|  | auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>( | 
|  | heap->GetAllocationHandle(), heap, nullptr, | 
|  | kLocales[locale_selector]); | 
|  | fmt->ParseDateTime(mgr, value, kTypes[type_selector], &dt); | 
|  | break; | 
|  | } | 
|  | case 8: { | 
|  | fmt->ParseNull(value); | 
|  | break; | 
|  | } | 
|  | case 9: { | 
|  | fmt->ParseZero(value); | 
|  | break; | 
|  | } | 
|  | } | 
|  | state->ForceGCAndPump(); | 
|  | return 0; | 
|  | } |