From 2124b9b4c95e66e63b1eb26a8dab49753b82fd6c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Jan 2020 10:52:24 +0900 Subject: Fix buffer overflow in `mrb_str_len_to_dbl`. Issue 19902: mruby:mruby_fuzzer: Stack-buffer-overflow in mrb_str_len_to_dbl --- src/string.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src/string.c') diff --git a/src/string.c b/src/string.c index e61a85cff..c7b9db17a 100644 --- a/src/string.c +++ b/src/string.c @@ -10,6 +10,7 @@ #ifndef MRB_WITHOUT_FLOAT #include +#include #endif #include #include @@ -2491,16 +2492,18 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) { - char buf[DBL_DIG * 4 + 10]; - const char *p = s; + char buf[DBL_DIG * 4 + 20]; + const char *p = s, *p2; const char *pend = p + len; char *end; char *n; char prev = 0; double d; + mrb_bool dot = FALSE; if (!p) return 0.0; while (p 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { mrb_value x; @@ -2515,21 +2518,27 @@ mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) } while (p < pend) { if (!*p) { - if (badcheck && p < pend) { + if (badcheck) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte"); /* not reached */ } pend = p; - p = s; + p = p2; + goto nocopy; + } + if (!badcheck && *p == ' ') { + pend = p; + p = p2; goto nocopy; } if (*p == '_') break; p++; } - p = s; + p = p2; n = buf; while (p < pend) { char c = *p++; + if (c == '.') dot = TRUE; if (c == '_') { /* remove an underscore between digits */ if (n == buf || !ISDIGIT(prev) || p == pend) { @@ -2539,6 +2548,11 @@ mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) } else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad; else { + const char *bend = buf+sizeof(buf)-1; + if (n==bend) { /* buffer overflow */ + if (dot) break; /* cut off remaining fractions */ + return INFINITY; + } *n++ = c; } prev = c; -- cgit v1.2.3