diff options
author | Bram Moolenaar <Bram@vim.org> | 2018-06-12 17:25:36 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2018-06-12 17:25:36 +0200 |
commit | 07ccf7ce7fb948fd4d080b817e9fbaea9e721dab (patch) | |
tree | 6cef28b8d62f60eb0c3b3b04e5925d6f60eea250 /src/charset.c | |
parent | 19834010889fc5bfa0f88b3ba83133dae6c0a35d (diff) |
patch 8.1.0048: vim_str2nr() does not handle numbers close to the maximumv8.1.0048
Problem: vim_str2nr() does not handle numbers close to the maximum.
Solution: Check for overflow more precisely. (Ken Takata, closes #2746)
Diffstat (limited to 'src/charset.c')
-rw-r--r-- | src/charset.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/src/charset.c b/src/charset.c index e6657ce84c..179fc89db3 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1928,8 +1928,8 @@ vim_str2nr( while ('0' <= *ptr && *ptr <= '1') { /* avoid ubsan error for overflow */ - if (un < UVARNUM_MAX / 2) - un = 2 * un + (unsigned long)(*ptr - '0'); + if (un <= UVARNUM_MAX / 2) + un = 2 * un + (uvarnumber_T)(*ptr - '0'); else un = UVARNUM_MAX; ++ptr; @@ -1943,7 +1943,7 @@ vim_str2nr( while ('0' <= *ptr && *ptr <= '7') { /* avoid ubsan error for overflow */ - if (un < UVARNUM_MAX / 8) + if (un <= UVARNUM_MAX / 8) un = 8 * un + (uvarnumber_T)(*ptr - '0'); else un = UVARNUM_MAX; @@ -1960,7 +1960,7 @@ vim_str2nr( while (vim_isxdigit(*ptr)) { /* avoid ubsan error for overflow */ - if (un < UVARNUM_MAX / 16) + if (un <= UVARNUM_MAX / 16) un = 16 * un + (uvarnumber_T)hex2nr(*ptr); else un = UVARNUM_MAX; @@ -1974,9 +1974,12 @@ vim_str2nr( /* decimal */ while (VIM_ISDIGIT(*ptr)) { + uvarnumber_T digit = (uvarnumber_T)(*ptr - '0'); + /* avoid ubsan error for overflow */ - if (un < UVARNUM_MAX / 10) - un = 10 * un + (uvarnumber_T)(*ptr - '0'); + if (un < UVARNUM_MAX / 10 + || (un == UVARNUM_MAX / 10 && digit <= UVARNUM_MAX % 10)) + un = 10 * un + digit; else un = UVARNUM_MAX; ++ptr; |