diff options
| -rw-r--r-- | include/mruby/value.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-pack/src/pack.c | 22 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 25 | ||||
| -rw-r--r-- | src/readint.c | 30 |
4 files changed, 47 insertions, 31 deletions
diff --git a/include/mruby/value.h b/include/mruby/value.h index 841cc7e6e..d9389b6fd 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -100,6 +100,7 @@ struct mrb_state; # define MRB_ENDIAN_LOHI(a,b) b a #endif +MRB_API mrb_int mrb_int_read(const char *p, const char *e, char **endp); #ifndef MRB_NO_FLOAT MRB_API double mrb_float_read(const char*, char**); #ifdef MRB_USE_FLOAT32 diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index fc0f3fa54..f0c5d8f1e 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -1234,17 +1234,16 @@ alias: /* read suffix [0-9*_!<>] */ while (tmpl->idx < tlen) { - ch = tptr[tmpl->idx++]; + ch = tptr[tmpl->idx]; if (ISDIGIT(ch)) { - count = ch - '0'; - while (tmpl->idx < tlen && ISDIGIT(tptr[tmpl->idx])) { - if (count+10 > INT_MAX/10) { - mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length"); - } - ch = tptr[tmpl->idx++] - '0'; - count = count * 10 + ch; + char *e; + mrb_int n = mrb_int_read(tptr+tmpl->idx, tptr+tlen, &e); + if (e == NULL || n > INT_MAX) { + mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length"); } - continue; /* special case */ + count = (int)n; + tmpl->idx += e - tptr; + continue; } else if (ch == '*') { count = -1; } else if (ch == '_' || ch == '!' || ch == '<' || ch == '>') { @@ -1258,10 +1257,11 @@ alias: } else if (ch == '>') { flags |= PACK_FLAG_GT; } - } else { - tmpl->idx--; + } + else { break; } + tmpl->idx++; } if ((flags & PACK_FLAG_LT) || (!(flags & PACK_FLAG_GT) && littleendian)) { diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 2ae982a16..ea9d74d95 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -245,7 +245,6 @@ check_name_arg(mrb_state *mrb, int posarg, const char *name, size_t len) #define GETASTER(num) do { \ mrb_value tmp_v; \ t = p++; \ - n = 0; \ GETNUM(n, val); \ if (*p == '$') { \ tmp_v = GETPOSARG(n); \ @@ -260,22 +259,11 @@ check_name_arg(mrb_state *mrb, int posarg, const char *name, size_t len) static const char * get_num(mrb_state *mrb, const char *p, const char *end, int *valp) { - mrb_int next_n = (int)*valp; - for (; p < end && ISDIGIT(*p); p++) { - if (mrb_int_mul_overflow(10, next_n, &next_n)) { - return NULL; - } - if (MRB_INT_MAX - (*p - '0') < next_n) { - return NULL; - } - next_n += *p - '0'; - } - if (next_n > INT_MAX || next_n < 0) return NULL; - if (p >= end) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed format string - %%*[0-9]"); - } - *valp = (int)next_n; - return p; + char *e; + mrb_int n = mrb_int_read(p, end, &e); + if (e == NULL || n > INT_MAX) return NULL; + *valp = (int)n; + return e; } static void @@ -665,7 +653,6 @@ retry: case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - n = 0; GETNUM(n, width); if (*p == '$') { if (!mrb_undef_p(nextvalue)) { @@ -722,7 +709,6 @@ retry: } flags |= FPREC|FPREC0; - prec = 0; p++; if (*p == '*') { GETASTER(prec); @@ -732,7 +718,6 @@ retry: p++; goto retry; } - GETNUM(prec, precision); goto retry; diff --git a/src/readint.c b/src/readint.c new file mode 100644 index 000000000..4478574fd --- /dev/null +++ b/src/readint.c @@ -0,0 +1,30 @@ +#include <mruby.h> +#include <mruby/numeric.h> +#include <errno.h> + +/* mrb_int_read(): read mrb_int from a string (base 10 only) */ +/* const char *p - string to read */ +/* const char *e - end of string */ +/* char **endp - end of pased integer */ + +/* if integer overflows, errno will be set to ERANGE */ +/* also endp will be set to NULL on overflow */ +MRB_API mrb_int +mrb_int_read(const char *p, const char *e, char **endp) +{ + mrb_int n = 0; + int ch; + + while ((e == NULL || p < e) && ISDIGIT(*p)) { + ch = *p - '0'; + if (mrb_int_mul_overflow(n, 10, &n) || + mrb_int_add_overflow(n, ch, &n)) { + if (endp) *endp = NULL; + errno = ERANGE; + return MRB_INT_MAX; + } + p++; + } + if (endp) *endp = (char*)p; + return n; +} |
