summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-03-12 16:21:32 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-03-12 16:21:32 +0900
commit4ae5ae353564291cdb28108c26382c32242966a8 (patch)
tree6cb495e5c3c59a0c9f46b8e4548f17e7082443d2 /mrbgems/mruby-compiler
parent84e27d3b519d8fba87c6ffdf318ccadf67d5318f (diff)
downloadmruby-4ae5ae353564291cdb28108c26382c32242966a8.tar.gz
mruby-4ae5ae353564291cdb28108c26382c32242966a8.zip
codegen.c: no integer overflow error in `codegen`; close #5376
Add new pool value type `IREP_TT_BIGINT` and generate integer overflow error in the VM. In the future, `mruby` will support `Bignum` for integers bigger than `mrb_int` (probably using `mpz`).
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 555479a7e..d02dd82f2 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -589,7 +589,47 @@ pop_n_(codegen_scope *s, int n)
#define pop_n(n) pop_n_(s,n)
#define cursp() (s->sp)
-static inline int
+static int
+new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg)
+{
+ int i, plen;
+ mrb_pool_value *pv;
+
+ plen = strlen(p);
+ if (plen > 255) {
+ codegen_error(s, "integer too big");
+ }
+ for (i=0; i<s->irep->plen; i++) {
+ mrb_int len;
+ pv = &s->pool[i];
+ if (pv->tt != IREP_TT_BIGINT) continue;
+ len = pv->u.str[0];
+ if (len == strlen(p) && pv->u.str[1] == base && memcmp(pv->u.str+2, p, len) == 0)
+ return i;
+ }
+
+ if (s->irep->plen == s->pcapa) {
+ s->pcapa *= 2;
+ s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa);
+ }
+
+ pv = &s->pool[s->irep->plen];
+ i = s->irep->plen++;
+ {
+ char *buf;
+ mrb_int len = strlen(p);
+ pv->tt = IREP_TT_BIGINT;
+ buf = (char*)codegen_realloc(s, NULL, len+3);
+ buf[0] = len;
+ buf[1] = base;
+ memcpy(buf+2, p, len);
+ buf[len+2] = '\0';
+ pv->u.str = buf;
+ }
+ return i;
+}
+
+static int
new_lit(codegen_scope *s, mrb_value val)
{
int i;
@@ -2493,7 +2533,8 @@ codegen(codegen_scope *s, node *tree, int val)
i = readint_mrb_int(s, p, base, FALSE, &overflow);
if (overflow) {
- codegen_error(s, "integer overflow");
+ int off = new_litbn(s, p, base, FALSE);
+ genop_bs(s, OP_LOADL, cursp(), off);
}
else {
if (i < 0) {
@@ -2509,7 +2550,6 @@ codegen(codegen_scope *s, node *tree, int val)
else if (i <= INT32_MAX) genop_2SS(s, OP_LOADI32, cursp(), (uint32_t)i);
else {
int off;
-
lit_int:
off = new_lit(s, mrb_int_value(s->mrb, i));
genop_bs(s, OP_LOADL, cursp(), off);
@@ -2558,7 +2598,8 @@ codegen(codegen_scope *s, node *tree, int val)
i = readint_mrb_int(s, p, base, TRUE, &overflow);
if (overflow) {
- codegen_error(s, "integer overflow");
+ int off = new_litbn(s, p, base, TRUE);
+ genop_bs(s, OP_LOADL, cursp(), off);
}
else {
if (i == -1) genop_1(s, OP_LOADI__1, cursp());