Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exprtk_fuzzer.cpp
Line
Count
Source
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
8.26k
   : exprtk::loop_runtime_check()
31
8.26k
   {}
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
2.36k
   {
47
2.36k
      timeout_tp_ = timeout_tp;
48
2.36k
   }
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
34.3k
   {
80
34.3k
      if (++iterations_ >= max_iters_per_check)
81
5.34k
      {
82
5.34k
         if (std::chrono::steady_clock::now() >= timeout_tp_)
83
0
         {
84
0
            context.error_message = "Compilation has timed-out";
85
0
            return false;
86
0
         }
87
88
5.34k
         iterations_ = 0;
89
5.34k
      }
90
91
34.3k
      return true;
92
34.3k
   }
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
8.26k
   {
98
8.26k
      timeout_tp_ = timeout_tp;
99
8.26k
   }
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
8.26k
{
125
8.26k
   using symbol_table_t       = exprtk::symbol_table<T>;
126
8.26k
   using expression_t         = exprtk::expression<T>;
127
8.26k
   using parser_t             = exprtk::parser<T>;
128
8.26k
   using loop_runtime_check_t = exprtk::loop_runtime_check;
129
130
8.26k
   T x = T(1.2345);
131
8.26k
   T y = T(2.2345);
132
8.26k
   T z = T(3.2345);
133
8.26k
   T w = T(4.2345);
134
135
8.26k
   symbol_table_t symbol_table;
136
8.26k
   symbol_table.add_variable("x",x);
137
8.26k
   symbol_table.add_variable("y",y);
138
8.26k
   symbol_table.add_variable("z",z);
139
8.26k
   symbol_table.add_variable("w",w);
140
8.26k
   symbol_table.add_constants();
141
142
8.26k
   expression_t expression;
143
8.26k
   expression.register_symbol_table(symbol_table);
144
145
8.26k
   timeout_rtc_handler loop_runtime_check;
146
8.26k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
147
8.26k
   loop_runtime_check.max_loop_iterations = 100000;
148
149
8.26k
   compilation_timeout_check compilation_timeout_chck;
150
8.26k
   vector_access_rtc         vector_rtc;
151
8.26k
   assert_handler            asrt_handler;
152
153
8.26k
   parser_t parser;
154
155
8.26k
   parser.settings().set_max_stack_depth(400);
156
8.26k
   parser.settings().set_max_node_depth (400);
157
8.26k
   parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB
158
159
8.26k
   parser.register_compilation_timeout_check  (compilation_timeout_chck);
160
8.26k
   parser.register_loop_runtime_check         (loop_runtime_check      );
161
8.26k
   parser.register_vector_access_runtime_check(vector_rtc              );
162
8.26k
   parser.register_assert_check               (asrt_handler            );
163
164
8.26k
   compilation_timeout_chck.set_timeout_time(global_timeout_tp);
165
166
8.26k
   if (parser.compile(expression_string, expression))
167
2.39k
   {
168
2.39k
      const std::size_t max_expression_size = 64 * 1024;
169
170
2.39k
      if (expression_string.size() <= max_expression_size)
171
2.36k
      {
172
2.36k
         loop_runtime_check.set_timeout_time(global_timeout_tp);
173
174
2.36k
         try
175
2.36k
         {
176
2.36k
            expression.value();
177
2.36k
         }
178
2.36k
         catch (std::runtime_error& rte)
179
2.36k
         {}
180
2.36k
         catch (...)
181
2.36k
         {}
182
183
2.36k
         parser.clear_loop_runtime_check();
184
2.36k
      }
185
2.39k
   }
186
8.26k
}
void run<double>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
124
4.13k
{
125
4.13k
   using symbol_table_t       = exprtk::symbol_table<T>;
126
4.13k
   using expression_t         = exprtk::expression<T>;
127
4.13k
   using parser_t             = exprtk::parser<T>;
128
4.13k
   using loop_runtime_check_t = exprtk::loop_runtime_check;
129
130
4.13k
   T x = T(1.2345);
131
4.13k
   T y = T(2.2345);
132
4.13k
   T z = T(3.2345);
133
4.13k
   T w = T(4.2345);
134
135
4.13k
   symbol_table_t symbol_table;
136
4.13k
   symbol_table.add_variable("x",x);
137
4.13k
   symbol_table.add_variable("y",y);
138
4.13k
   symbol_table.add_variable("z",z);
139
4.13k
   symbol_table.add_variable("w",w);
140
4.13k
   symbol_table.add_constants();
141
142
4.13k
   expression_t expression;
143
4.13k
   expression.register_symbol_table(symbol_table);
144
145
4.13k
   timeout_rtc_handler loop_runtime_check;
146
4.13k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
147
4.13k
   loop_runtime_check.max_loop_iterations = 100000;
148
149
4.13k
   compilation_timeout_check compilation_timeout_chck;
150
4.13k
   vector_access_rtc         vector_rtc;
151
4.13k
   assert_handler            asrt_handler;
152
153
4.13k
   parser_t parser;
154
155
4.13k
   parser.settings().set_max_stack_depth(400);
156
4.13k
   parser.settings().set_max_node_depth (400);
157
4.13k
   parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB
158
159
4.13k
   parser.register_compilation_timeout_check  (compilation_timeout_chck);
160
4.13k
   parser.register_loop_runtime_check         (loop_runtime_check      );
161
4.13k
   parser.register_vector_access_runtime_check(vector_rtc              );
162
4.13k
   parser.register_assert_check               (asrt_handler            );
163
164
4.13k
   compilation_timeout_chck.set_timeout_time(global_timeout_tp);
165
166
4.13k
   if (parser.compile(expression_string, expression))
167
1.20k
   {
168
1.20k
      const std::size_t max_expression_size = 64 * 1024;
169
170
1.20k
      if (expression_string.size() <= max_expression_size)
171
1.18k
      {
172
1.18k
         loop_runtime_check.set_timeout_time(global_timeout_tp);
173
174
1.18k
         try
175
1.18k
         {
176
1.18k
            expression.value();
177
1.18k
         }
178
1.18k
         catch (std::runtime_error& rte)
179
1.18k
         {}
180
1.18k
         catch (...)
181
1.18k
         {}
182
183
1.18k
         parser.clear_loop_runtime_check();
184
1.18k
      }
185
1.20k
   }
186
4.13k
}
void run<float>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
124
4.13k
{
125
4.13k
   using symbol_table_t       = exprtk::symbol_table<T>;
126
4.13k
   using expression_t         = exprtk::expression<T>;
127
4.13k
   using parser_t             = exprtk::parser<T>;
128
4.13k
   using loop_runtime_check_t = exprtk::loop_runtime_check;
129
130
4.13k
   T x = T(1.2345);
131
4.13k
   T y = T(2.2345);
132
4.13k
   T z = T(3.2345);
133
4.13k
   T w = T(4.2345);
134
135
4.13k
   symbol_table_t symbol_table;
136
4.13k
   symbol_table.add_variable("x",x);
137
4.13k
   symbol_table.add_variable("y",y);
138
4.13k
   symbol_table.add_variable("z",z);
139
4.13k
   symbol_table.add_variable("w",w);
140
4.13k
   symbol_table.add_constants();
141
142
4.13k
   expression_t expression;
143
4.13k
   expression.register_symbol_table(symbol_table);
144
145
4.13k
   timeout_rtc_handler loop_runtime_check;
146
4.13k
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
147
4.13k
   loop_runtime_check.max_loop_iterations = 100000;
148
149
4.13k
   compilation_timeout_check compilation_timeout_chck;
150
4.13k
   vector_access_rtc         vector_rtc;
151
4.13k
   assert_handler            asrt_handler;
152
153
4.13k
   parser_t parser;
154
155
4.13k
   parser.settings().set_max_stack_depth(400);
156
4.13k
   parser.settings().set_max_node_depth (400);
157
4.13k
   parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB
158
159
4.13k
   parser.register_compilation_timeout_check  (compilation_timeout_chck);
160
4.13k
   parser.register_loop_runtime_check         (loop_runtime_check      );
161
4.13k
   parser.register_vector_access_runtime_check(vector_rtc              );
162
4.13k
   parser.register_assert_check               (asrt_handler            );
163
164
4.13k
   compilation_timeout_chck.set_timeout_time(global_timeout_tp);
165
166
4.13k
   if (parser.compile(expression_string, expression))
167
1.19k
   {
168
1.19k
      const std::size_t max_expression_size = 64 * 1024;
169
170
1.19k
      if (expression_string.size() <= max_expression_size)
171
1.17k
      {
172
1.17k
         loop_runtime_check.set_timeout_time(global_timeout_tp);
173
174
1.17k
         try
175
1.17k
         {
176
1.17k
            expression.value();
177
1.17k
         }
178
1.17k
         catch (std::runtime_error& rte)
179
1.17k
         {}
180
1.17k
         catch (...)
181
1.17k
         {}
182
183
1.17k
         parser.clear_loop_runtime_check();
184
1.17k
      }
185
1.19k
   }
186
4.13k
}
187
188
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
189
4.13k
{
190
4.13k
   const std::string expression(reinterpret_cast<const char*>(data), size);
191
192
4.13k
   run<double>(expression);
193
4.13k
   run<float> (expression);
194
195
4.13k
   return 0;
196
4.13k
}