diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-01-22 18:34:57 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-01-22 18:34:57 +0100 |
commit | 7a40ea2138102545848ea86a361f1b8dec7552b5 (patch) | |
tree | 28c03360f9bb2de0d7454f50ffccc1f33c75fe54 /src/charset.c | |
parent | 2b2207ba69c6b009e466a36eef0644ca723e16d3 (diff) | |
download | vim-git-7a40ea2138102545848ea86a361f1b8dec7552b5.tar.gz |
patch 8.0.0219: ubsan reports errors for overflowv8.0.0219
Problem: Ubsan reports errors for integer overflow.
Solution: Define macros for minimum and maximum values. Select an
expression based on the value. (Mike Williams)
Diffstat (limited to 'src/charset.c')
-rw-r--r-- | src/charset.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/src/charset.c b/src/charset.c index c3b62590b..c047afec7 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1901,7 +1901,11 @@ vim_str2nr( n += 2; /* skip over "0b" */ while ('0' <= *ptr && *ptr <= '1') { - un = 2 * un + (unsigned long)(*ptr - '0'); + /* avoid ubsan error for overflow */ + if (un < UVARNUM_MAX / 2) + un = 2 * un + (unsigned long)(*ptr - '0'); + else + un = UVARNUM_MAX; ++ptr; if (n++ == maxlen) break; @@ -1912,7 +1916,11 @@ vim_str2nr( /* octal */ while ('0' <= *ptr && *ptr <= '7') { - un = 8 * un + (uvarnumber_T)(*ptr - '0'); + /* avoid ubsan error for overflow */ + if (un < UVARNUM_MAX / 8) + un = 8 * un + (uvarnumber_T)(*ptr - '0'); + else + un = UVARNUM_MAX; ++ptr; if (n++ == maxlen) break; @@ -1925,7 +1933,11 @@ vim_str2nr( n += 2; /* skip over "0x" */ while (vim_isxdigit(*ptr)) { - un = 16 * un + (uvarnumber_T)hex2nr(*ptr); + /* avoid ubsan error for overflow */ + if (un < UVARNUM_MAX / 16) + un = 16 * un + (uvarnumber_T)hex2nr(*ptr); + else + un = UVARNUM_MAX; ++ptr; if (n++ == maxlen) break; @@ -1936,7 +1948,11 @@ vim_str2nr( /* decimal */ while (VIM_ISDIGIT(*ptr)) { - un = 10 * un + (uvarnumber_T)(*ptr - '0'); + /* avoid ubsan error for overflow */ + if (un < UVARNUM_MAX / 10) + un = 10 * un + (uvarnumber_T)(*ptr - '0'); + else + un = UVARNUM_MAX; ++ptr; if (n++ == maxlen) break; @@ -1950,9 +1966,19 @@ vim_str2nr( if (nptr != NULL) { if (negative) /* account for leading '-' for decimal numbers */ - *nptr = -(varnumber_T)un; + { + /* avoid ubsan error for overflow */ + if (un > VARNUM_MAX) + *nptr = VARNUM_MIN; + else + *nptr = -(varnumber_T)un; + } else + { + if (un > VARNUM_MAX) + un = VARNUM_MAX; *nptr = (varnumber_T)un; + } } if (unptr != NULL) *unptr = un; |