Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2020 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | |
16 | | #include <chrono> |
17 | | #include <cstdint> |
18 | | #include <string> |
19 | | |
20 | | #define exprtk_enable_range_runtime_checks |
21 | | #include "exprtk.hpp" |
22 | | |
23 | | |
24 | | constexpr auto max_test_duration = std::chrono::seconds(58); // OSSFuzz test time is 60seconds |
25 | | const auto global_timeout_tp = std::chrono::steady_clock::now() + max_test_duration; |
26 | | |
27 | | struct timeout_rtc_handler : public exprtk::loop_runtime_check |
28 | | { |
29 | | timeout_rtc_handler() |
30 | 12.6k | : exprtk::loop_runtime_check() |
31 | 12.6k | {} |
32 | | |
33 | | class timeout_exception : public std::runtime_error |
34 | | { |
35 | | public: |
36 | | timeout_exception(const std::string& what = "") |
37 | 0 | : std::runtime_error(what) |
38 | 0 | {} |
39 | | }; |
40 | | |
41 | | static constexpr std::size_t max_iterations = 5000000; |
42 | | |
43 | | using time_point_t = std::chrono::time_point<std::chrono::steady_clock>; |
44 | | |
45 | | void set_timeout_time(const time_point_t& timeout_tp) |
46 | 6.64k | { |
47 | 6.64k | timeout_tp_ = timeout_tp; |
48 | 6.64k | } |
49 | | |
50 | | bool check() override |
51 | 0 | { |
52 | 0 | if (++iterations_ >= max_iterations) |
53 | 0 | { |
54 | 0 | if (std::chrono::steady_clock::now() >= timeout_tp_) |
55 | 0 | { |
56 | 0 | return false; |
57 | 0 | } |
58 | | |
59 | 0 | iterations_ = 0; |
60 | 0 | } |
61 | | |
62 | 0 | return true; |
63 | 0 | } |
64 | | |
65 | | void handle_runtime_violation(const violation_context& /*context*/) override |
66 | 0 | { |
67 | 0 | throw timeout_exception("ExprTk Loop run-time timeout violation."); |
68 | 0 | } |
69 | | |
70 | | std::size_t iterations_ = 0; |
71 | | time_point_t timeout_tp_; |
72 | | }; |
73 | | |
74 | | struct compilation_timeout_check final : public exprtk::compilation_check |
75 | | { |
76 | | static constexpr std::size_t max_iters_per_check = 500; |
77 | | |
78 | | bool continue_compilation(compilation_context& context) override |
79 | 329k | { |
80 | 329k | if (++iterations_ >= max_iters_per_check) |
81 | 11.7k | { |
82 | 11.7k | if (std::chrono::steady_clock::now() >= timeout_tp_) |
83 | 8 | { |
84 | 8 | context.error_message = "Compilation has timed-out"; |
85 | 8 | return false; |
86 | 8 | } |
87 | | |
88 | 11.7k | iterations_ = 0; |
89 | 11.7k | } |
90 | | |
91 | 329k | return true; |
92 | 329k | } |
93 | | |
94 | | using time_point_t = std::chrono::time_point<std::chrono::steady_clock>; |
95 | | |
96 | | void set_timeout_time(const time_point_t& timeout_tp) |
97 | 12.6k | { |
98 | 12.6k | timeout_tp_ = timeout_tp; |
99 | 12.6k | } |
100 | | |
101 | | std::size_t iterations_ = max_iters_per_check; |
102 | | time_point_t timeout_tp_; |
103 | | }; |
104 | | |
105 | | struct vector_access_rtc final : public exprtk::vector_access_runtime_check |
106 | | { |
107 | | bool handle_runtime_violation(violation_context& /*context*/) override |
108 | 0 | { |
109 | 0 | throw std::runtime_error("Runtime vector access violation."); |
110 | 0 | return false; |
111 | 0 | } |
112 | | }; |
113 | | |
114 | | struct assert_handler final : public exprtk::assert_check |
115 | | { |
116 | | void handle_assert(const assert_context& /*context*/) override |
117 | 0 | { |
118 | 0 | throw std::runtime_error("assert: vector access violation."); |
119 | 0 | } |
120 | | }; |
121 | | |
122 | | template <typename T> |
123 | | void run(const std::string& expression_string) |
124 | 12.6k | { |
125 | 12.6k | using symbol_table_t = exprtk::symbol_table<T>; |
126 | 12.6k | using expression_t = exprtk::expression<T>; |
127 | 12.6k | using parser_t = exprtk::parser<T>; |
128 | 12.6k | using loop_runtime_check_t = exprtk::loop_runtime_check; |
129 | | |
130 | 12.6k | T x = T(1.2345); |
131 | 12.6k | T y = T(2.2345); |
132 | 12.6k | T z = T(3.2345); |
133 | 12.6k | T w = T(4.2345); |
134 | | |
135 | 12.6k | symbol_table_t symbol_table; |
136 | 12.6k | symbol_table.add_variable("x",x); |
137 | 12.6k | symbol_table.add_variable("y",y); |
138 | 12.6k | symbol_table.add_variable("z",z); |
139 | 12.6k | symbol_table.add_variable("w",w); |
140 | 12.6k | symbol_table.add_constants(); |
141 | | |
142 | 12.6k | expression_t expression; |
143 | 12.6k | expression.register_symbol_table(symbol_table); |
144 | | |
145 | 12.6k | timeout_rtc_handler loop_runtime_check; |
146 | 12.6k | loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; |
147 | 12.6k | loop_runtime_check.max_loop_iterations = 100000; |
148 | | |
149 | 12.6k | compilation_timeout_check compilation_timeout_chck; |
150 | 12.6k | vector_access_rtc vector_rtc; |
151 | 12.6k | assert_handler asrt_handler; |
152 | | |
153 | 12.6k | parser_t parser; |
154 | | |
155 | 12.6k | parser.settings().set_max_stack_depth(400); |
156 | 12.6k | parser.settings().set_max_node_depth (400); |
157 | 12.6k | parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB |
158 | | |
159 | 12.6k | parser.register_compilation_timeout_check (compilation_timeout_chck); |
160 | 12.6k | parser.register_loop_runtime_check (loop_runtime_check ); |
161 | 12.6k | parser.register_vector_access_runtime_check(vector_rtc ); |
162 | 12.6k | parser.register_assert_check (asrt_handler ); |
163 | | |
164 | 12.6k | compilation_timeout_chck.set_timeout_time(global_timeout_tp); |
165 | | |
166 | 12.6k | if (parser.compile(expression_string, expression)) |
167 | 6.66k | { |
168 | 6.66k | const std::size_t max_expression_size = 64 * 1024; |
169 | | |
170 | 6.66k | if (expression_string.size() <= max_expression_size) |
171 | 6.64k | { |
172 | 6.64k | loop_runtime_check.set_timeout_time(global_timeout_tp); |
173 | | |
174 | 6.64k | try |
175 | 6.64k | { |
176 | 6.64k | expression.value(); |
177 | 6.64k | } |
178 | 6.64k | catch (std::runtime_error& rte) |
179 | 6.64k | {} |
180 | 6.64k | catch (...) |
181 | 6.64k | {} |
182 | | |
183 | 6.64k | parser.clear_loop_runtime_check(); |
184 | 6.64k | } |
185 | 6.66k | } |
186 | 12.6k | } void run<double>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 124 | 6.34k | { | 125 | 6.34k | using symbol_table_t = exprtk::symbol_table<T>; | 126 | 6.34k | using expression_t = exprtk::expression<T>; | 127 | 6.34k | using parser_t = exprtk::parser<T>; | 128 | 6.34k | using loop_runtime_check_t = exprtk::loop_runtime_check; | 129 | | | 130 | 6.34k | T x = T(1.2345); | 131 | 6.34k | T y = T(2.2345); | 132 | 6.34k | T z = T(3.2345); | 133 | 6.34k | T w = T(4.2345); | 134 | | | 135 | 6.34k | symbol_table_t symbol_table; | 136 | 6.34k | symbol_table.add_variable("x",x); | 137 | 6.34k | symbol_table.add_variable("y",y); | 138 | 6.34k | symbol_table.add_variable("z",z); | 139 | 6.34k | symbol_table.add_variable("w",w); | 140 | 6.34k | symbol_table.add_constants(); | 141 | | | 142 | 6.34k | expression_t expression; | 143 | 6.34k | expression.register_symbol_table(symbol_table); | 144 | | | 145 | 6.34k | timeout_rtc_handler loop_runtime_check; | 146 | 6.34k | loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; | 147 | 6.34k | loop_runtime_check.max_loop_iterations = 100000; | 148 | | | 149 | 6.34k | compilation_timeout_check compilation_timeout_chck; | 150 | 6.34k | vector_access_rtc vector_rtc; | 151 | 6.34k | assert_handler asrt_handler; | 152 | | | 153 | 6.34k | parser_t parser; | 154 | | | 155 | 6.34k | parser.settings().set_max_stack_depth(400); | 156 | 6.34k | parser.settings().set_max_node_depth (400); | 157 | 6.34k | parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB | 158 | | | 159 | 6.34k | parser.register_compilation_timeout_check (compilation_timeout_chck); | 160 | 6.34k | parser.register_loop_runtime_check (loop_runtime_check ); | 161 | 6.34k | parser.register_vector_access_runtime_check(vector_rtc ); | 162 | 6.34k | parser.register_assert_check (asrt_handler ); | 163 | | | 164 | 6.34k | compilation_timeout_chck.set_timeout_time(global_timeout_tp); | 165 | | | 166 | 6.34k | if (parser.compile(expression_string, expression)) | 167 | 3.33k | { | 168 | 3.33k | const std::size_t max_expression_size = 64 * 1024; | 169 | | | 170 | 3.33k | if (expression_string.size() <= max_expression_size) | 171 | 3.32k | { | 172 | 3.32k | loop_runtime_check.set_timeout_time(global_timeout_tp); | 173 | | | 174 | 3.32k | try | 175 | 3.32k | { | 176 | 3.32k | expression.value(); | 177 | 3.32k | } | 178 | 3.32k | catch (std::runtime_error& rte) | 179 | 3.32k | {} | 180 | 3.32k | catch (...) | 181 | 3.32k | {} | 182 | | | 183 | 3.32k | parser.clear_loop_runtime_check(); | 184 | 3.32k | } | 185 | 3.33k | } | 186 | 6.34k | } |
void run<float>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 124 | 6.34k | { | 125 | 6.34k | using symbol_table_t = exprtk::symbol_table<T>; | 126 | 6.34k | using expression_t = exprtk::expression<T>; | 127 | 6.34k | using parser_t = exprtk::parser<T>; | 128 | 6.34k | using loop_runtime_check_t = exprtk::loop_runtime_check; | 129 | | | 130 | 6.34k | T x = T(1.2345); | 131 | 6.34k | T y = T(2.2345); | 132 | 6.34k | T z = T(3.2345); | 133 | 6.34k | T w = T(4.2345); | 134 | | | 135 | 6.34k | symbol_table_t symbol_table; | 136 | 6.34k | symbol_table.add_variable("x",x); | 137 | 6.34k | symbol_table.add_variable("y",y); | 138 | 6.34k | symbol_table.add_variable("z",z); | 139 | 6.34k | symbol_table.add_variable("w",w); | 140 | 6.34k | symbol_table.add_constants(); | 141 | | | 142 | 6.34k | expression_t expression; | 143 | 6.34k | expression.register_symbol_table(symbol_table); | 144 | | | 145 | 6.34k | timeout_rtc_handler loop_runtime_check; | 146 | 6.34k | loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; | 147 | 6.34k | loop_runtime_check.max_loop_iterations = 100000; | 148 | | | 149 | 6.34k | compilation_timeout_check compilation_timeout_chck; | 150 | 6.34k | vector_access_rtc vector_rtc; | 151 | 6.34k | assert_handler asrt_handler; | 152 | | | 153 | 6.34k | parser_t parser; | 154 | | | 155 | 6.34k | parser.settings().set_max_stack_depth(400); | 156 | 6.34k | parser.settings().set_max_node_depth (400); | 157 | 6.34k | parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB | 158 | | | 159 | 6.34k | parser.register_compilation_timeout_check (compilation_timeout_chck); | 160 | 6.34k | parser.register_loop_runtime_check (loop_runtime_check ); | 161 | 6.34k | parser.register_vector_access_runtime_check(vector_rtc ); | 162 | 6.34k | parser.register_assert_check (asrt_handler ); | 163 | | | 164 | 6.34k | compilation_timeout_chck.set_timeout_time(global_timeout_tp); | 165 | | | 166 | 6.34k | if (parser.compile(expression_string, expression)) | 167 | 3.32k | { | 168 | 3.32k | const std::size_t max_expression_size = 64 * 1024; | 169 | | | 170 | 3.32k | if (expression_string.size() <= max_expression_size) | 171 | 3.31k | { | 172 | 3.31k | loop_runtime_check.set_timeout_time(global_timeout_tp); | 173 | | | 174 | 3.31k | try | 175 | 3.31k | { | 176 | 3.31k | expression.value(); | 177 | 3.31k | } | 178 | 3.31k | catch (std::runtime_error& rte) | 179 | 3.31k | {} | 180 | 3.31k | catch (...) | 181 | 3.31k | {} | 182 | | | 183 | 3.31k | parser.clear_loop_runtime_check(); | 184 | 3.31k | } | 185 | 3.32k | } | 186 | 6.34k | } |
|
187 | | |
188 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
189 | 6.34k | { |
190 | 6.34k | const std::string expression(reinterpret_cast<const char*>(data), size); |
191 | | |
192 | 6.34k | run<double>(expression); |
193 | 6.34k | run<float> (expression); |
194 | | |
195 | 6.34k | return 0; |
196 | 6.34k | } |