Merge remote-tracking branch 'origin/DivideByZeroProtection' into develop
This commit is contained in:
commit
bde4eb04b6
@ -396,10 +396,9 @@ 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");
|
||||||
|
|
||||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -61,7 +88,7 @@ namespace chaiscript
|
|||||||
case Operators::not_equal:
|
case Operators::not_equal:
|
||||||
return const_var(t != u);
|
return const_var(t != u);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -89,13 +116,14 @@ 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:
|
||||||
t -= u;
|
t -= u;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
|
|
||||||
return t_lhs;
|
return t_lhs;
|
||||||
@ -122,13 +150,14 @@ 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:
|
||||||
t ^= u;
|
t ^= u;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
return t_lhs;
|
return t_lhs;
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
@ -156,7 +186,7 @@ namespace chaiscript
|
|||||||
case Operators::bitwise_complement:
|
case Operators::bitwise_complement:
|
||||||
return const_var(~t);
|
return const_var(~t);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -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);
|
||||||
@ -181,7 +212,7 @@ namespace chaiscript
|
|||||||
case Operators::unary_plus:
|
case Operators::unary_plus:
|
||||||
return const_var(+t);
|
return const_var(+t);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -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))
|
||||||
@ -843,12 +873,12 @@ namespace chaiscript
|
|||||||
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
|
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||||
template<>
|
template<>
|
||||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
@ -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