mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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`).
This commit is contained in:
@@ -20,6 +20,7 @@ enum irep_pool_type {
|
||||
IREP_TT_SSTR = 2, /* string (static) */
|
||||
IREP_TT_INT32 = 1, /* 32bit integer */
|
||||
IREP_TT_INT64 = 3, /* 64bit integer */
|
||||
IREP_TT_BIGINT = 7, /* big integer (not yet supported) */
|
||||
IREP_TT_FLOAT = 5, /* float (double/float) */
|
||||
};
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/dump.h>
|
||||
|
||||
#ifndef MRB_NO_STDIO
|
||||
#ifndef MRB_NOP_STDIO
|
||||
static void
|
||||
print_r(mrb_state *mrb, const mrb_irep *irep, size_t n)
|
||||
{
|
||||
|
||||
+28
-1
@@ -129,6 +129,15 @@ get_pool_block_size(mrb_state *mrb, const mrb_irep *irep)
|
||||
size += 4; /* 32bits = 4bytes */
|
||||
break;
|
||||
|
||||
case IREP_TT_BIGINT:
|
||||
{
|
||||
mrb_int len = irep->pool[pool_no].u.str[0];
|
||||
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
|
||||
size += sizeof(uint8_t);
|
||||
size += (size_t)len+2;
|
||||
}
|
||||
break;
|
||||
|
||||
case IREP_TT_FLOAT:
|
||||
#ifndef MRB_NO_FLOAT
|
||||
{
|
||||
@@ -187,6 +196,14 @@ write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
|
||||
cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */
|
||||
break;
|
||||
|
||||
case IREP_TT_BIGINT:
|
||||
cur += uint8_to_bin(IREP_TT_BIGINT, cur); /* data type */
|
||||
len = irep->pool[pool_no].u.str[0];
|
||||
memcpy(cur, irep->pool[pool_no].u.str, (size_t)len+2);
|
||||
cur += len+2;
|
||||
*cur++ = '\0';
|
||||
break;
|
||||
|
||||
case IREP_TT_FLOAT:
|
||||
cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
|
||||
#ifndef MRB_NO_FLOAT
|
||||
@@ -216,7 +233,6 @@ write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
|
||||
return cur - buf;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
get_syms_block_size(mrb_state *mrb, const mrb_irep *irep)
|
||||
{
|
||||
@@ -941,6 +957,17 @@ dump_pool(mrb_state *mrb, const mrb_pool_value *p, FILE *fp)
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case IREP_TT_BIGINT:
|
||||
{
|
||||
const char *s = p->u.str;
|
||||
int len = s[0]+2;
|
||||
fputs("{IREP_TT_BIGINT, {\"", fp);
|
||||
for (int i=0; i<len; i++) {
|
||||
fprintf(fp, "\\x%02x", (int)s[i]&0xff);
|
||||
}
|
||||
fputs("\"}},\n", fp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* string */
|
||||
|
||||
+13
@@ -161,6 +161,19 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
|
||||
return FALSE; /* INT64 not supported on MRB_32BIT */
|
||||
#endif
|
||||
|
||||
case IREP_TT_BIGINT:
|
||||
pool_data_len = bin_to_uint8(src); /* pool data length */
|
||||
src += sizeof(uint8_t);
|
||||
{
|
||||
char *p;
|
||||
pool[i].tt = IREP_TT_BIGINT;
|
||||
p = (char*)mrb_malloc(mrb, pool_data_len+2);
|
||||
memcpy(p, src, pool_data_len+2);
|
||||
pool[i].u.str = (const char*)p;
|
||||
}
|
||||
src += pool_data_len + 2;
|
||||
break;
|
||||
|
||||
case IREP_TT_FLOAT:
|
||||
#ifndef MRB_NO_FLOAT
|
||||
pool[i].tt = tt;
|
||||
|
||||
+2
-1
@@ -154,7 +154,8 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
|
||||
mrb_free(mrb, (void*)irep->iseq);
|
||||
if (irep->pool) {
|
||||
for (i=0; i<irep->plen; i++) {
|
||||
if ((irep->pool[i].tt & 3) == IREP_TT_STR) {
|
||||
if ((irep->pool[i].tt & 3) == IREP_TT_STR ||
|
||||
irep->pool[i].tt == IREP_TT_BIGINT) {
|
||||
mrb_free(mrb, (void*)irep->pool[i].u.str);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user