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(user_type<std::runtime_error>(), "runtime_error");
|
||||||
m->add(chaiscript::base_class<std::exception, std::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(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
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(&has_parse_tree), "has_parse_tree");
|
||||||
m->add(chaiscript::fun(&get_parse_tree), "get_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);
|
// 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;
|
class Type_Conversions;
|
||||||
} // namespace chaiscript
|
} // 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
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -37,6 +49,21 @@ namespace chaiscript
|
|||||||
class Boxed_Number
|
class Boxed_Number
|
||||||
{
|
{
|
||||||
private:
|
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
|
struct boolean
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -89,6 +116,7 @@ namespace chaiscript
|
|||||||
t += u;
|
t += u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_quotient:
|
case Operators::assign_quotient:
|
||||||
|
check_divide_by_zero(u);
|
||||||
t /= u;
|
t /= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_difference:
|
case Operators::assign_difference:
|
||||||
@ -122,6 +150,7 @@ namespace chaiscript
|
|||||||
t >>= u;
|
t >>= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_remainder:
|
case Operators::assign_remainder:
|
||||||
|
check_divide_by_zero(u);
|
||||||
t %= u;
|
t %= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_bitwise_xor:
|
case Operators::assign_bitwise_xor:
|
||||||
@ -146,6 +175,7 @@ namespace chaiscript
|
|||||||
case Operators::shift_right:
|
case Operators::shift_right:
|
||||||
return const_var(t >> u);
|
return const_var(t >> u);
|
||||||
case Operators::remainder:
|
case Operators::remainder:
|
||||||
|
check_divide_by_zero(u);
|
||||||
return const_var(t % u);
|
return const_var(t % u);
|
||||||
case Operators::bitwise_and:
|
case Operators::bitwise_and:
|
||||||
return const_var(t & u);
|
return const_var(t & u);
|
||||||
@ -171,6 +201,7 @@ namespace chaiscript
|
|||||||
case Operators::sum:
|
case Operators::sum:
|
||||||
return const_var(t + u);
|
return const_var(t + u);
|
||||||
case Operators::quotient:
|
case Operators::quotient:
|
||||||
|
check_divide_by_zero(u);
|
||||||
return const_var(t / u);
|
return const_var(t / u);
|
||||||
case Operators::product:
|
case Operators::product:
|
||||||
return const_var(t * u);
|
return const_var(t * u);
|
||||||
@ -327,7 +358,6 @@ namespace chaiscript
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Boxed_Number()
|
Boxed_Number()
|
||||||
: bv(Boxed_Value(0))
|
: bv(Boxed_Value(0))
|
||||||
|
@ -93,6 +93,8 @@ namespace chaiscript
|
|||||||
// If it's an arithmetic operation we want to short circuit dispatch
|
// If it's an arithmetic operation we want to short circuit dispatch
|
||||||
try{
|
try{
|
||||||
return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
|
return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
|
||||||
|
} catch (const chaiscript::exception::arithmetic_error &) {
|
||||||
|
throw;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
|
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 func = fun(){
|
||||||
var ret = 0;
|
var ret = 0;
|
||||||
for (var i = 0; i < 1000000; ++i) {
|
for (var i = 0; i < 50000; ++i) {
|
||||||
ret += i;
|
ret += i;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -9,9 +9,7 @@ var func = fun(){
|
|||||||
|
|
||||||
var fut1 := async(func);
|
var fut1 := async(func);
|
||||||
var fut2 := async(func);
|
var fut2 := async(func);
|
||||||
var fut3 := async(func);
|
|
||||||
var fut4 := async(func);
|
|
||||||
|
|
||||||
// simply executing without crashing is good enough for this test
|
// 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