summaryrefslogtreecommitdiffhomepage
path: root/src/string.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-01-02 12:45:29 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-01-02 20:28:27 +0900
commitc1f05a7fb3e15acbe8bce0789af505a2b6a5876a (patch)
tree8d271b7b7c11e1b9aa831f207a824629cd8e840f /src/string.c
parent4ac73307fdf7996484378fdd6e09c02e5e7efbdc (diff)
downloadmruby-c1f05a7fb3e15acbe8bce0789af505a2b6a5876a.tar.gz
mruby-c1f05a7fb3e15acbe8bce0789af505a2b6a5876a.zip
Avoid `uint64_t` in string-to-integer conversion; ref #5201
Diffstat (limited to 'src/string.c')
-rw-r--r--src/string.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/string.c b/src/string.c
index 4e8bd7835..749d32698 100644
--- a/src/string.c
+++ b/src/string.c
@@ -2216,7 +2216,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, i
const char *pend = str + len;
char sign = 1;
int c;
- uint64_t n = 0;
+ mrb_int n = 0;
mrb_int val;
#define conv_digit(c) \
@@ -2343,15 +2343,17 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, i
if (c < 0 || c >= base) {
break;
}
- n *= base;
- n += c;
- if (n > (uint64_t)MRB_INT_MAX) {
- if (sign == 0 && n == (uint64_t)MRB_INT_MIN) {
+ if (mrb_int_mul_overflow(n, base, &n)) goto overflow;
+ if (MRB_INT_MAX - c < n) {
+ if (sign == 0 && MRB_INT_MAX - n == c - 1) {
+ n = MRB_INT_MIN;
sign = 1;
break;
}
+ overflow:
mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
}
+ n += c;
}
val = (mrb_int)n;
if (badcheck) {