diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-01-08 10:52:24 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-01-08 10:52:24 +0900 |
| commit | 2124b9b4c95e66e63b1eb26a8dab49753b82fd6c (patch) | |
| tree | 8f60006df2781d9016ba59dc5986f2f81e790b23 /src | |
| parent | dbba0ca517ad0c32cdd7f0bd68de9c35145e1735 (diff) | |
| download | mruby-2124b9b4c95e66e63b1eb26a8dab49753b82fd6c.tar.gz mruby-2124b9b4c95e66e63b1eb26a8dab49753b82fd6c.zip | |
Fix buffer overflow in `mrb_str_len_to_dbl`.
Issue 19902: mruby:mruby_fuzzer: Stack-buffer-overflow in mrb_str_len_to_dbl
Diffstat (limited to 'src')
| -rw-r--r-- | src/string.c | 24 |
1 files changed, 19 insertions, 5 deletions
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 <float.h> +#include <math.h> #endif #include <limits.h> #include <stddef.h> @@ -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<pend && ISSPACE(*p)) p++; + p2 = p; if (pend - 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; |
