diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-12 16:21:32 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-12 16:21:32 +0900 |
| commit | 4ae5ae353564291cdb28108c26382c32242966a8 (patch) | |
| tree | 6cb495e5c3c59a0c9f46b8e4548f17e7082443d2 /mrbgems/mruby-compiler | |
| parent | 84e27d3b519d8fba87c6ffdf318ccadf67d5318f (diff) | |
| download | mruby-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.c | 49 |
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()); |
