diff --git a/projects/exprtk/exprtk_fuzzer.cpp b/projects/exprtk/exprtk_fuzzer.cpp index 486e49c400c1..7c722ff65f08 100644 --- a/projects/exprtk/exprtk_fuzzer.cpp +++ b/projects/exprtk/exprtk_fuzzer.cpp @@ -12,13 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include + #include +#include #include #define exprtk_enable_range_runtime_checks #include "exprtk.hpp" + +constexpr auto max_test_duration = std::chrono::seconds(58); // OSSFuzz test time is 60seconds +const auto global_timeout_tp = std::chrono::steady_clock::now() + max_test_duration; + struct timeout_rtc_handler : public exprtk::loop_runtime_check { timeout_rtc_handler() @@ -50,13 +55,14 @@ struct timeout_rtc_handler : public exprtk::loop_runtime_check { return false; } + iterations_ = 0; } return true; } - void handle_runtime_violation(const violation_context& ctx) override + void handle_runtime_violation(const violation_context& /*context*/) override { throw timeout_exception("ExprTk Loop run-time timeout violation."); } @@ -65,13 +71,61 @@ struct timeout_rtc_handler : public exprtk::loop_runtime_check time_point_t timeout_tp_; }; +struct compilation_timeout_check final : public exprtk::compilation_check +{ + static constexpr std::size_t max_iters_per_check = 500; + + bool continue_compilation(compilation_context& context) override + { + if (++iterations_ >= max_iters_per_check) + { + if (std::chrono::steady_clock::now() >= timeout_tp_) + { + context.error_message = "Compilation has timed-out"; + return false; + } + + iterations_ = 0; + } + + return true; + } + + using time_point_t = std::chrono::time_point; + + void set_timeout_time(const time_point_t& timeout_tp) + { + timeout_tp_ = timeout_tp; + } + + std::size_t iterations_ = max_iters_per_check; + time_point_t timeout_tp_; +}; + +struct vector_access_rtc final : public exprtk::vector_access_runtime_check +{ + bool handle_runtime_violation(violation_context& /*context*/) override + { + throw std::runtime_error("Runtime vector access violation."); + return false; + } +}; + +struct assert_handler final : public exprtk::assert_check +{ + void handle_assert(const assert_context& /*context*/) override + { + throw std::runtime_error("assert: vector access violation."); + } +}; + template void run(const std::string& expression_string) { - typedef exprtk::symbol_table symbol_table_t; - typedef exprtk::expression expression_t; - typedef exprtk::parser parser_t; - typedef exprtk::loop_runtime_check loop_runtime_check_t; + using symbol_table_t = exprtk::symbol_table; + using expression_t = exprtk::expression; + using parser_t = exprtk::parser; + using loop_runtime_check_t = exprtk::loop_runtime_check; T x = T(1.2345); T y = T(2.2345); @@ -92,9 +146,22 @@ void run(const std::string& expression_string) loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; loop_runtime_check.max_loop_iterations = 100000; + compilation_timeout_check compilation_timeout_chck; + vector_access_rtc vector_rtc; + assert_handler asrt_handler; + parser_t parser; - parser.register_loop_runtime_check(loop_runtime_check); + parser.settings().set_max_stack_depth(400); + parser.settings().set_max_node_depth (400); + parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB + + parser.register_compilation_timeout_check (compilation_timeout_chck); + parser.register_loop_runtime_check (loop_runtime_check ); + parser.register_vector_access_runtime_check(vector_rtc ); + parser.register_assert_check (asrt_handler ); + + compilation_timeout_chck.set_timeout_time(global_timeout_tp); if (parser.compile(expression_string, expression)) { @@ -102,9 +169,7 @@ void run(const std::string& expression_string) if (expression_string.size() <= max_expression_size) { - const auto max_duration = std::chrono::seconds(25); - const auto timeout_tp = std::chrono::steady_clock::now() + max_duration; - loop_runtime_check.set_timeout_time(timeout_tp); + loop_runtime_check.set_timeout_time(global_timeout_tp); try { @@ -112,6 +177,8 @@ void run(const std::string& expression_string) } catch (std::runtime_error& rte) {} + catch (...) + {} parser.clear_loop_runtime_check(); }