Fix #634: Add divide-by-zero check for modulo assignment operator (#672)

The assign_remainder (%=) case in Boxed_Number::go was missing the
check_divide_by_zero guard, causing a hardware SIGFPE on integer
modulo by zero. Also moved a misplaced check_divide_by_zero from
assign_bitwise_and (&=) where it was erroneous. Additionally, the
catch block in Equation_AST_Node::eval_internal was masking the
arithmetic_error exception as a generic "unsupported operation" error;
arithmetic_error is now re-thrown to provide the correct error message.

Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
leftibot 2026-04-12 16:28:41 -06:00 committed by GitHub
parent 4804fb6e03
commit 9237acbbb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 1 deletions

View File

@ -220,7 +220,6 @@ namespace chaiscript {
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
switch (t_oper) {
case Operators::Opers::assign_bitwise_and:
check_divide_by_zero(c_rhs);
*t_lhs &= c_rhs;
return t_bv;
case Operators::Opers::assign_bitwise_or:
@ -233,6 +232,7 @@ namespace chaiscript {
*t_lhs >>= c_rhs;
return t_bv;
case Operators::Opers::assign_remainder:
check_divide_by_zero(c_rhs);
*t_lhs %= c_rhs;
return t_bv;
case Operators::Opers::assign_bitwise_xor:

View File

@ -438,6 +438,8 @@ namespace chaiscript {
if (m_oper != Operators::Opers::invalid && params[0].get_type_info().is_arithmetic() && params[1].get_type_info().is_arithmetic()) {
try {
return Boxed_Number::do_oper(m_oper, params[0], params[1]);
} catch (const chaiscript::exception::arithmetic_error &) {
throw;
} catch (const std::exception &) {
throw exception::eval_error("Error with unsupported arithmetic assignment operation.");
}

View File

@ -0,0 +1,16 @@
// modulo by zero should throw, not crash
try {
3 % 0
assert_true(false)
} catch (e) {
assert_equal("Arithmetic error: divide by zero", e.what())
}
// assign-modulo by zero should also throw
var x = 3;
try {
x %= 0
assert_true(false)
} catch (e) {
assert_equal("Arithmetic error: divide by zero", e.what())
}