1 // Copyright 2019 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "xfa/fgas/crt/cfgas_stringformatter.h"
6
7 #include <stdint.h>
8
9 #include <iterator>
10
11 #include "core/fxcrt/cfx_datetime.h"
12 #include "core/fxcrt/compiler_specific.h"
13 #include "core/fxcrt/fx_string.h"
14 #include "public/fpdfview.h"
15 #include "testing/fuzzers/pdfium_fuzzer_util.h"
16 #include "testing/fuzzers/xfa_process_state.h"
17 #include "v8/include/cppgc/heap.h"
18 #include "v8/include/cppgc/persistent.h"
19 #include "xfa/fxfa/parser/cxfa_localemgr.h"
20
21 namespace {
22
23 const wchar_t* const kLocales[] = {L"en", L"fr", L"jp", L"zh"};
24 const CFGAS_StringFormatter::DateTimeType kTypes[] = {
25 CFGAS_StringFormatter::DateTimeType::kDate,
26 CFGAS_StringFormatter::DateTimeType::kTime,
27 CFGAS_StringFormatter::DateTimeType::kDateTime,
28 CFGAS_StringFormatter::DateTimeType::kTimeDate};
29
30 } // namespace
31
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)32 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
33 if (size < 5 || size > 128) // Big strings are unlikely to help.
34 return 0;
35
36 auto* state = static_cast<XFAProcessState*>(FPDF_GetFuzzerPerProcessState());
37 cppgc::Heap* heap = state->GetHeap();
38
39 uint8_t test_selector = data[0] % 10;
40 uint8_t locale_selector = data[1] % std::size(kLocales);
41 uint8_t type_selector = data[2] % std::size(kTypes);
42 data += 3;
43 size -= 3;
44
45 size_t pattern_len = size / 2;
46 size_t value_len = size - pattern_len;
47 WideString pattern =
48 WideString::FromLatin1(UNSAFE_TODO(ByteStringView(data, pattern_len)));
49 WideString value = WideString::FromLatin1(
50 UNSAFE_TODO(ByteStringView(data + pattern_len, value_len)));
51
52 auto fmt = std::make_unique<CFGAS_StringFormatter>(pattern);
53
54 WideString result;
55 CFX_DateTime dt;
56 switch (test_selector) {
57 case 0:
58 fmt->FormatText(value, &result);
59 break;
60 case 1: {
61 auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>(
62 heap->GetAllocationHandle(), heap, nullptr,
63 kLocales[locale_selector]);
64 fmt->FormatNum(mgr, value, &result);
65 break;
66 }
67 case 2: {
68 auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>(
69 heap->GetAllocationHandle(), heap, nullptr,
70 kLocales[locale_selector]);
71 fmt->FormatDateTime(mgr, value, kTypes[type_selector], &result);
72 break;
73 }
74 case 3: {
75 fmt->FormatNull(&result);
76 break;
77 }
78 case 4: {
79 fmt->FormatZero(&result);
80 break;
81 }
82 case 5: {
83 fmt->ParseText(value, &result);
84 break;
85 }
86 case 6: {
87 auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>(
88 heap->GetAllocationHandle(), heap, nullptr,
89 kLocales[locale_selector]);
90 fmt->ParseNum(mgr, value, &result);
91 break;
92 }
93 case 7: {
94 auto* mgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>(
95 heap->GetAllocationHandle(), heap, nullptr,
96 kLocales[locale_selector]);
97 fmt->ParseDateTime(mgr, value, kTypes[type_selector], &dt);
98 break;
99 }
100 case 8: {
101 fmt->ParseNull(value);
102 break;
103 }
104 case 9: {
105 fmt->ParseZero(value);
106 break;
107 }
108 }
109 state->ForceGCAndPump();
110 return 0;
111 }
112