Skip to content

Commit

Permalink
Update ExprTk Fuzzer (#12688)
Browse files Browse the repository at this point in the history
- Additional RTCs:
  1. Compilation time-out RTC
  2. Vector access RTC
  3. Assert handler
 
- Set maximum vector size (#64099)
- Ensure tests don't exceed 60sec time limit (#56181, #38029, #44308)
  • Loading branch information
ArashPartow authored Nov 4, 2024
1 parent 9a50925 commit d5619e1
Showing 1 changed file with 77 additions and 10 deletions.
87 changes: 77 additions & 10 deletions projects/exprtk/exprtk_fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cstdint>

#include <chrono>
#include <cstdint>
#include <string>

#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()
Expand Down Expand Up @@ -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.");
}
Expand All @@ -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<std::chrono::steady_clock>;

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 <typename T>
void run(const std::string& expression_string)
{
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
typedef exprtk::loop_runtime_check loop_runtime_check_t;
using symbol_table_t = exprtk::symbol_table<T>;
using expression_t = exprtk::expression<T>;
using parser_t = exprtk::parser<T>;
using loop_runtime_check_t = exprtk::loop_runtime_check;

T x = T(1.2345);
T y = T(2.2345);
Expand All @@ -92,26 +146,39 @@ 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))
{
const std::size_t max_expression_size = 64 * 1024;

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
{
expression.value();
}
catch (std::runtime_error& rte)
{}
catch (...)
{}

parser.clear_loop_runtime_check();
}
Expand Down

0 comments on commit d5619e1

Please sign in to comment.