summaryrefslogtreecommitdiffhomepage
path: root/src/vm.c
diff options
context:
space:
mode:
authorYukihiro Matsumoto <[email protected]>2012-11-01 05:54:53 +0900
committerYukihiro Matsumoto <[email protected]>2012-11-01 05:54:53 +0900
commit9b85ffa5a760e53536762bf6cdf402c90ae9ceb7 (patch)
tree233c39ed97abc4703ede75fd16b5b97ff337adb2 /src/vm.c
parent604e39bdfbc97666671c2b638c1cd2cdc068be3e (diff)
downloadmruby-9b85ffa5a760e53536762bf6cdf402c90ae9ceb7.tar.gz
mruby-9b85ffa5a760e53536762bf6cdf402c90ae9ceb7.zip
OP_ADDI/OP_SUBI should handle integer overflow; close #518
Diffstat (limited to 'src/vm.c')
-rw-r--r--src/vm.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/vm.c b/src/vm.c
index 120e0d4c0..953863a0b 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1444,7 +1444,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* need to check if + is overridden */
switch (mrb_type(regs[a])) {
case MRB_TT_FIXNUM:
- regs[a].attr_i += GETARG_C(i);
+ {
+ mrb_int x = regs[a].attr_i;
+ mrb_int y = GETARG_C(i);
+ mrb_int z = x + y;
+
+ if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) {
+ /* integer overflow */
+ SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y);
+ break;
+ }
+ regs[a].attr_i = z;
+ }
break;
case MRB_TT_FLOAT:
regs[a].attr_f += GETARG_C(i);
@@ -1464,7 +1475,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* need to check if + is overridden */
switch (mrb_type(regs[a])) {
case MRB_TT_FIXNUM:
- regs[a].attr_i -= GETARG_C(i);
+ {
+ mrb_int x = regs[a].attr_i;
+ mrb_int y = GETARG_C(i);
+ mrb_int z = x - y;
+
+ if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) {
+ /* integer overflow */
+ SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y);
+ break;
+ }
+ regs[a].attr_i = z;
+ }
break;
case MRB_TT_FLOAT:
regs[a].attr_f -= GETARG_C(i);