Merge remote-tracking branch 'origin/DivideByZeroProtection' into develop
This commit is contained in:
commit
bde4eb04b6
@ -397,7 +397,6 @@ namespace chaiscript
|
||||
m->add(user_type<std::runtime_error>(), "runtime_error");
|
||||
m->add(chaiscript::base_class<std::exception, std::runtime_error>());
|
||||
|
||||
|
||||
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
|
||||
@ -487,7 +486,12 @@ namespace chaiscript
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||
m->add(chaiscript::user_type<chaiscript::exception::eval_error>(), "eval_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||
|
||||
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||
|
||||
|
||||
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
|
@ -22,6 +22,18 @@ namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
struct arithmetic_error : public std::runtime_error
|
||||
{
|
||||
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
@ -37,6 +49,21 @@ namespace chaiscript
|
||||
class Boxed_Number
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
|
||||
if (t == 0) {
|
||||
throw chaiscript::exception::arithmetic_error("divide by zero");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
|
||||
{
|
||||
}
|
||||
|
||||
struct boolean
|
||||
{
|
||||
|
||||
@ -89,6 +116,7 @@ namespace chaiscript
|
||||
t += u;
|
||||
break;
|
||||
case Operators::assign_quotient:
|
||||
check_divide_by_zero(u);
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::assign_difference:
|
||||
@ -122,6 +150,7 @@ namespace chaiscript
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::assign_remainder:
|
||||
check_divide_by_zero(u);
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_xor:
|
||||
@ -146,6 +175,7 @@ namespace chaiscript
|
||||
case Operators::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::remainder:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t % u);
|
||||
case Operators::bitwise_and:
|
||||
return const_var(t & u);
|
||||
@ -171,6 +201,7 @@ namespace chaiscript
|
||||
case Operators::sum:
|
||||
return const_var(t + u);
|
||||
case Operators::quotient:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t / u);
|
||||
case Operators::product:
|
||||
return const_var(t * u);
|
||||
@ -327,7 +358,6 @@ namespace chaiscript
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
Boxed_Number()
|
||||
: bv(Boxed_Value(0))
|
||||
|
@ -93,6 +93,8 @@ namespace chaiscript
|
||||
// If it's an arithmetic operation we want to short circuit dispatch
|
||||
try{
|
||||
return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
|
||||
} catch (const chaiscript::exception::arithmetic_error &) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
|
||||
}
|
||||
|
9
unittests/divide_by_zero_protection.chai
Normal file
9
unittests/divide_by_zero_protection.chai
Normal file
@ -0,0 +1,9 @@
|
||||
try {
|
||||
3/0
|
||||
assert_true(false); // should never get here
|
||||
} catch (e) {
|
||||
assert_equal("Arithmetic error: divide by zero", e.what())
|
||||
}
|
||||
|
||||
assert_equal(3/0.0, Infinity)
|
||||
|
@ -1,6 +1,6 @@
|
||||
var func = fun(){
|
||||
var ret = 0;
|
||||
for (var i = 0; i < 1000000; ++i) {
|
||||
for (var i = 0; i < 50000; ++i) {
|
||||
ret += i;
|
||||
}
|
||||
return ret;
|
||||
@ -9,9 +9,7 @@ var func = fun(){
|
||||
|
||||
var fut1 := async(func);
|
||||
var fut2 := async(func);
|
||||
var fut3 := async(func);
|
||||
var fut4 := async(func);
|
||||
|
||||
// simply executing without crashing is good enough for this test
|
||||
|
||||
print(" ${fut1.get()} ${fut2.get()} ${fut3.get()} ${fut4.get()}")
|
||||
print(" ${fut1.get()} ${fut2.get()} ")
|
||||
|
Loading…
x
Reference in New Issue
Block a user