Coverage Report

Created: 2023-06-07 06:24

/src/exprtk_fuzzer.cpp
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
#include <cstdint>
16
#include <chrono>
17
#include <string>
18
19
#define exprtk_enable_range_runtime_checks
20
#include "exprtk.hpp"
21
22
struct timeout_rtc_handler : public exprtk::loop_runtime_check
23
{
24
   timeout_rtc_handler()
25
   : exprtk::loop_runtime_check()
26
42.4k
   {}
27
28
   class timeout_exception : public std::runtime_error
29
   {
30
   public:
31
       timeout_exception(const std::string& what = "")
32
       : std::runtime_error(what)
33
1.61k
       {}
34
   };
35
36
   static constexpr std::size_t max_iterations = 5000000;
37
38
   using time_point_t = std::chrono::time_point<std::chrono::steady_clock>;
39
40
   void set_timeout_time(const time_point_t& timeout_tp)
41
28.4k
   {
42
28.4k
      timeout_tp_ = timeout_tp;
43
28.4k
   }
44
45
   bool check() override
46
161M
   {
47
161M
      if (++iterations_ >= max_iterations)
48
0
      {
49
0
         if (std::chrono::steady_clock::now() >= timeout_tp_)
50
0
         {
51
0
            return false;
52
0
         }
53
0
         iterations_ = 0;
54
0
      }
55
56
161M
      return true;
57
161M
   }
58
59
   void handle_runtime_violation(const violation_context& ctx) override
60
1.61k
   {
61
1.61k
      throw timeout_exception("ExprTk Loop run-time timeout violation.");
62
1.61k
   }
63
64
   std::size_t iterations_ = 0;
65
   time_point_t timeout_tp_;
66
};
67
68
template <typename T>
69
void run(const std::string& expression_string)
70
42.4k
{
71
42.4k
   typedef exprtk::symbol_table<T>    symbol_table_t;
72
42.4k
   typedef exprtk::expression<T>      expression_t;
73
42.4k
   typedef exprtk::parser<T>          parser_t;
74
42.4k
   typedef exprtk::loop_runtime_check loop_runtime_check_t;
75
76
42.4k
   T x = T(1.2345);
77
42.4k
   T y = T(2.2345);
78
42.4k
   T z = T(3.2345);
79
42.4k
   T w = T(4.2345);
80
81
42.4k
   symbol_table_t symbol_table;
82
42.4k
   symbol_table.add_variable("x",x);
83
42.4k
   symbol_table.add_variable("y",y);
84
42.4k
   symbol_table.add_variable("z",z);
85
42.4k
   symbol_table.add_variable("w",w);
86
42.4k
   symbol_table.add_constants();
87
88
42.4k
   expression_t expression;
89
42.4k
   expression.register_symbol_table(symbol_table);
90
91
42.4k
   timeout_rtc_handler loop_runtime_check;
92
42.4k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
93
42.4k
   loop_runtime_check.max_loop_iterations = 100000;
94
95
42.4k
   parser_t parser;
96
97
42.4k
   parser.register_loop_runtime_check(loop_runtime_check);
98
99
42.4k
   if (parser.compile(expression_string, expression))
100
29.3k
   {
101
29.3k
      const std::size_t max_expression_size = 64 * 1024;
102
103
29.3k
      if (expression_string.size() <= max_expression_size)
104
28.4k
      {
105
28.4k
         const auto max_duration = std::chrono::seconds(25);
106
28.4k
         const auto timeout_tp = std::chrono::steady_clock::now() + max_duration;
107
28.4k
         loop_runtime_check.set_timeout_time(timeout_tp);
108
109
28.4k
         try
110
28.4k
         {
111
28.4k
            expression.value();
112
28.4k
         }
113
28.4k
         catch (std::runtime_error& rte)
114
28.4k
         {}
115
116
28.4k
         parser.clear_loop_runtime_check();
117
28.4k
      }
118
29.3k
   }
119
42.4k
}
void run<double>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
70
21.2k
{
71
21.2k
   typedef exprtk::symbol_table<T>    symbol_table_t;
72
21.2k
   typedef exprtk::expression<T>      expression_t;
73
21.2k
   typedef exprtk::parser<T>          parser_t;
74
21.2k
   typedef exprtk::loop_runtime_check loop_runtime_check_t;
75
76
21.2k
   T x = T(1.2345);
77
21.2k
   T y = T(2.2345);
78
21.2k
   T z = T(3.2345);
79
21.2k
   T w = T(4.2345);
80
81
21.2k
   symbol_table_t symbol_table;
82
21.2k
   symbol_table.add_variable("x",x);
83
21.2k
   symbol_table.add_variable("y",y);
84
21.2k
   symbol_table.add_variable("z",z);
85
21.2k
   symbol_table.add_variable("w",w);
86
21.2k
   symbol_table.add_constants();
87
88
21.2k
   expression_t expression;
89
21.2k
   expression.register_symbol_table(symbol_table);
90
91
21.2k
   timeout_rtc_handler loop_runtime_check;
92
21.2k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
93
21.2k
   loop_runtime_check.max_loop_iterations = 100000;
94
95
21.2k
   parser_t parser;
96
97
21.2k
   parser.register_loop_runtime_check(loop_runtime_check);
98
99
21.2k
   if (parser.compile(expression_string, expression))
100
14.7k
   {
101
14.7k
      const std::size_t max_expression_size = 64 * 1024;
102
103
14.7k
      if (expression_string.size() <= max_expression_size)
104
14.2k
      {
105
14.2k
         const auto max_duration = std::chrono::seconds(25);
106
14.2k
         const auto timeout_tp = std::chrono::steady_clock::now() + max_duration;
107
14.2k
         loop_runtime_check.set_timeout_time(timeout_tp);
108
109
14.2k
         try
110
14.2k
         {
111
14.2k
            expression.value();
112
14.2k
         }
113
14.2k
         catch (std::runtime_error& rte)
114
14.2k
         {}
115
116
14.2k
         parser.clear_loop_runtime_check();
117
14.2k
      }
118
14.7k
   }
119
21.2k
}
void run<float>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
70
21.2k
{
71
21.2k
   typedef exprtk::symbol_table<T>    symbol_table_t;
72
21.2k
   typedef exprtk::expression<T>      expression_t;
73
21.2k
   typedef exprtk::parser<T>          parser_t;
74
21.2k
   typedef exprtk::loop_runtime_check loop_runtime_check_t;
75
76
21.2k
   T x = T(1.2345);
77
21.2k
   T y = T(2.2345);
78
21.2k
   T z = T(3.2345);
79
21.2k
   T w = T(4.2345);
80
81
21.2k
   symbol_table_t symbol_table;
82
21.2k
   symbol_table.add_variable("x",x);
83
21.2k
   symbol_table.add_variable("y",y);
84
21.2k
   symbol_table.add_variable("z",z);
85
21.2k
   symbol_table.add_variable("w",w);
86
21.2k
   symbol_table.add_constants();
87
88
21.2k
   expression_t expression;
89
21.2k
   expression.register_symbol_table(symbol_table);
90
91
21.2k
   timeout_rtc_handler loop_runtime_check;
92
21.2k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
93
21.2k
   loop_runtime_check.max_loop_iterations = 100000;
94
95
21.2k
   parser_t parser;
96
97
21.2k
   parser.register_loop_runtime_check(loop_runtime_check);
98
99
21.2k
   if (parser.compile(expression_string, expression))
100
14.6k
   {
101
14.6k
      const std::size_t max_expression_size = 64 * 1024;
102
103
14.6k
      if (expression_string.size() <= max_expression_size)
104
14.1k
      {
105
14.1k
         const auto max_duration = std::chrono::seconds(25);
106
14.1k
         const auto timeout_tp = std::chrono::steady_clock::now() + max_duration;
107
14.1k
         loop_runtime_check.set_timeout_time(timeout_tp);
108
109
14.1k
         try
110
14.1k
         {
111
14.1k
            expression.value();
112
14.1k
         }
113
14.1k
         catch (std::runtime_error& rte)
114
14.1k
         {}
115
116
14.1k
         parser.clear_loop_runtime_check();
117
14.1k
      }
118
14.6k
   }
119
21.2k
}
120
121
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
122
21.2k
{
123
21.2k
   const std::string expression(reinterpret_cast<const char*>(data), size);
124
125
21.2k
   run<double>(expression);
126
21.2k
   run<float> (expression);
127
128
21.2k
   return 0;
129
21.2k
}