/src/boost_regex_replace_fuzzer.cc
Line | Count | Source |
1 | | /* Copyright 2024 Google LLC |
2 | | Licensed under the Apache License, Version 2.0 (the "License"); |
3 | | you may not use this file except in compliance with the License. |
4 | | You may obtain a copy of the License at |
5 | | http://www.apache.org/licenses/LICENSE-2.0 |
6 | | Unless required by applicable law or agreed to in writing, software |
7 | | distributed under the License is distributed on an "AS IS" BASIS, |
8 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
9 | | See the License for the specific language governing permissions and |
10 | | limitations under the License. |
11 | | */ |
12 | | // The ideal place for this fuzz target is the boost repository. |
13 | | #include <boost/regex.hpp> |
14 | | #ifdef DEBUG |
15 | | #include <iostream> |
16 | | #endif |
17 | | #include <sstream> |
18 | | #include <string> |
19 | | #include <iterator> |
20 | | #include <fuzzer/FuzzedDataProvider.h> |
21 | | |
22 | | // purpose of the fuzzer: |
23 | | // fuzz the format string syntax used in match-replace |
24 | | // |
25 | | // the mutator comes from a boost example that: |
26 | | // takes the contents of a file and transform to |
27 | | // syntax highlighted code in html format |
28 | | |
29 | | boost::regex e1, e2; |
30 | | extern const char* expression_text; |
31 | | extern const char* pre_expression; |
32 | | extern const char* pre_format; |
33 | | extern const char* match_against; |
34 | | |
35 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) |
36 | 16.0k | { |
37 | 16.0k | FuzzedDataProvider fdp(Data, Size); |
38 | 16.0k | std::string format_string = fdp.ConsumeRemainingBytesAsString(); |
39 | 16.0k | try{ |
40 | 16.0k | e1.assign(expression_text); |
41 | 16.0k | e2.assign(pre_expression); |
42 | 16.0k | std::string in; |
43 | 16.0k | in.assign(match_against); |
44 | 16.0k | std::ostringstream t(std::ios::out | std::ios::binary); |
45 | 16.0k | std::ostream_iterator<char, char> oi(t); |
46 | 16.0k | boost::regex_replace(oi, in.begin(), in.end(), |
47 | 16.0k | e2, format_string, boost::match_default | boost::format_all); |
48 | 16.0k | std::string s(t.str()); |
49 | | #ifdef DEBUG |
50 | | std::cout << s << std::endl; |
51 | | #endif |
52 | 16.0k | } catch(...) { |
53 | 10.6k | } |
54 | 16.0k | return 0; |
55 | 16.0k | } |
56 | | |
57 | | const char* pre_expression = "(<)|(>)|(&)|\\r"; |
58 | | const char* pre_format = "(?1<)(?2>)(?3&)"; |
59 | | |
60 | | |
61 | | const char* expression_text = |
62 | | // preprocessor directives: index 1 |
63 | | "(^[[:blank:]]*#(?:[^\\\\\\n]|\\\\[^\\n[:punct:][:word:]]*[\\n[:punct:][:word:]])*)|" |
64 | | // comment: index 2 |
65 | | "(//[^\\n]*|/\\*.*?\\*/)|" |
66 | | // literals: index 3 |
67 | | "\\<([+-]?(?:(?:0x[[:xdigit:]]+)|(?:(?:[[:digit:]]*\\.)?[[:digit:]]+" |
68 | | "(?:[eE][+-]?[[:digit:]]+)?))u?(?:(?:int(?:8|16|32|64))|L)?)\\>|" |
69 | | // string literals: index 4 |
70 | | "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|" |
71 | | // keywords: index 5 |
72 | | "\\<(__asm|__cdecl|__declspec|__export|__far16|__fastcall|__fortran|__import" |
73 | | "|__pascal|__rtti|__stdcall|_asm|_cdecl|__except|_export|_far16|_fastcall" |
74 | | "|__finally|_fortran|_import|_pascal|_stdcall|__thread|__try|asm|auto|bool" |
75 | | "|break|case|catch|cdecl|char|class|const|const_cast|continue|default|delete" |
76 | | "|do|double|dynamic_cast|else|enum|explicit|extern|false|float|for|friend|goto" |
77 | | "|if|inline|int|long|mutable|namespace|new|operator|pascal|private|protected" |
78 | | "|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_cast" |
79 | | "|struct|switch|template|this|throw|true|try|typedef|typeid|typename|union|unsigned" |
80 | | "|using|virtual|void|volatile|wchar_t|while)\\>" |
81 | | ; |
82 | | |
83 | | |
84 | | const char* match_against = "#include <iostream>" |
85 | | "#include <string>" |
86 | | "#include <vector>" |
87 | | "#include <boost/regex.hpp>" |
88 | | "" |
89 | | "" |
90 | | "extern \"C\" int main(int argc, char** argv) {" |
91 | | " std::string regex_string;" |
92 | | " std::getline(std::cin, regex_string);" |
93 | | " std::string where(\"AAAA\");" |
94 | | " try {" |
95 | | " boost::regex e(regex_string);" |
96 | | " std::cout << \"Regexp string: \" << regex_string << \"Size: \" << regex_string.size() << std::endl;" |
97 | | " boost::match_results<std::string::const_iterator> what;" |
98 | | " bool match = boost::regex_match(where, what, e, boost::match_default | boost::match_partial | boost::match_perl | boost::match_posix | boost::match_any);" |
99 | | " if (match)" |
100 | | " std::cout << match << std::endl;" |
101 | | " }" |
102 | | " catch (const std::runtime_error &err) {" |
103 | | " std::cerr << \"Caught exception: \" << err.what() << std::endl;" |
104 | | " }" |
105 | | " return 0;" |
106 | | "}"; |
107 | | |