Skip to content

Commit

Permalink
Berry upstream fix mod 0 (arendst#21174)
Browse files Browse the repository at this point in the history
* Berry upstream fix mod 0

* Add test case
  • Loading branch information
s-hadinger authored Apr 14, 2024
1 parent a2ad349 commit 105aa03
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 21 deletions.
50 changes: 29 additions & 21 deletions lib/libesp32/berry/src/be_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,22 +723,20 @@ static void vm_exec(bvm *vm)
}
} else if (var_isnumber(a) && var_isnumber(b)) {
#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */
union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug
x.i = a->v.i;
if (var_isint(a)) { x.r = (breal) x.i; }
y.i = b->v.i;
if (var_isint(b)) { y.r = (breal) y.i; }
if (y.r == cast(breal, 0)) {
vm_error(vm, "divzero_error", "division by zero");
}
var_setreal(dst, x.r / y.r);
union bvaldata x0, y0; // TASMOTA workaround for ESP32 rev0 bug
x0.i = a->v.i;
if (var_isint(a)) { x0.r = (breal) x0.i; }
y0.i = b->v.i;
if (var_isint(b)) { y0.r = (breal) y0.i; }
breal x = x0.r, y = y0.r;
#else // CONFIG_IDF_TARGET_ESP32
breal x = var2real(a), y = var2real(b);
#endif // CONFIG_IDF_TARGET_ESP32
if (y == cast(breal, 0)) {
vm_error(vm, "divzero_error", "division by zero");
} else {
var_setreal(dst, x / y);
}
var_setreal(dst, x / y);
#endif // CONFIG_IDF_TARGET_ESP32
} else if (var_isinstance(a)) {
ins_binop(vm, "/", ins);
} else {
Expand All @@ -749,18 +747,28 @@ static void vm_exec(bvm *vm)
opcase(MOD): {
bvalue *dst = RA(), *a = RKB(), *b = RKC();
if (var_isint(a) && var_isint(b)) {
var_setint(dst, ibinop(%, a, b));
bint x = var_toint(a), y = var_toint(b);
if (y == 0) {
vm_error(vm, "divzero_error", "division by zero");
} else {
var_setint(dst, x % y);
}
} else if (var_isnumber(a) && var_isnumber(b)) {
#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */
union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug
x.i = a->v.i;
if (var_isint(a)) { x.r = (breal) x.i; }
y.i = b->v.i;
if (var_isint(b)) { y.r = (breal) y.i; }
var_setreal(dst, mathfunc(fmod)(x.r, y.r));
#else // CONFIG_IDF_TARGET_ESP32
var_setreal(dst, mathfunc(fmod)(var_toreal(a), var_toreal(b)));
#endif // CONFIG_IDF_TARGET_ESP32
union bvaldata x0, y0; // TASMOTA workaround for ESP32 rev0 bug
x0.i = a->v.i;
if (var_isint(a)) { x0.r = (breal) x0.i; }
y0.i = b->v.i;
if (var_isint(b)) { y0.r = (breal) y0.i; }
breal x = x0.r, y = y0.r;
#else
breal x = var2real(a), y = var2real(b);
#endif
if (y == cast(breal, 0)) {
vm_error(vm, "divzero_error", "division by zero");
} else {
var_setreal(dst, mathfunc(fmod)(x, y));
}
} else if (var_isinstance(a)) {
ins_binop(vm, "%", ins);
} else {
Expand Down
47 changes: 47 additions & 0 deletions lib/libesp32/berry/tests/division_by_zero.be
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

try
# Test integer division
var div = 1/0
assert(false) # Should not reach this point
except .. as e,m

assert(e == "divzero_error")
assert(m == "division by zero")
end


try
# Test integer modulo
var div = 1%0
assert(false)
except .. as e,m
assert(e == "divzero_error")
assert(m == "division by zero")
end

try
# Test float division
var div = 1.1/0.0
assert(false)
except .. as e,m
assert(e == "divzero_error")
assert(m == "division by zero")
end

try
# Test float modulo
var div = 1.1%0.0
assert(false)
except .. as e,m
assert(e == "divzero_error")
assert(m == "division by zero")
end


# Check normal division & modulo
assert(1/2 == 0)
assert(1%2 == 1)
assert(1.0/2.0 == 0.5)
assert(1.0%2.0 == 1.0)
assert(4/2 == 2)
assert(4%2 == 0)

0 comments on commit 105aa03

Please sign in to comment.