From 261e4d3fa0643d1e9114826486eb91ee27410f32 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Wed, 13 Jun 2012 17:48:03 +0900 Subject: handle number literal overflow --- src/codegen.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/codegen.c b/src/codegen.c index e76443a20..4c0f98295 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -16,6 +16,9 @@ #include "node.h" #include #include +#include +#include +#include typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -800,6 +803,27 @@ raise_error(codegen_scope *s, const char *msg) genop(s, MKOP_ABx(OP_ERR, 0, idx)); } +static mrb_float +readint_float(codegen_scope *s, const char *p, int base) +{ + const char *e = p + strlen(p); + mrb_float f = 0; + int n; + + while (p <= e) { + char c = tolower(*p); + for (n=0; n -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); + if (i == LONG_MAX && errno == ERANGE) { + mrb_float f = readint_float(s, p, base); + int off = new_lit(s, mrb_float_value(f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); } else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); } - genop(s, co); push(); } break; @@ -1599,15 +1631,23 @@ codegen(codegen_scope *s, node *tree, int val) int i = readint(p, base); mrb_code co; - i = -i; - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } - else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); - } - genop(s, co); + if (i == LONG_MAX && errno == ERANGE) { + mrb_float f = readint_float(s, p, base); + int off = new_lit(s, mrb_float_value(-f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + } + else { + i = -i; + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); + } push(); } break; -- cgit v1.2.3