To: vim_dev@googlegroups.com Subject: Patch 8.0.0219 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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) Files: src/charset.c, src/eval.c, src/evalfunc.c, src/structs.h, src/testdir/test_viml.vim *** ../vim-8.0.0218/src/charset.c 2017-01-10 13:51:05.583236296 +0100 --- src/charset.c 2017-01-22 18:23:56.676226532 +0100 *************** *** 1901,1907 **** n += 2; /* skip over "0b" */ while ('0' <= *ptr && *ptr <= '1') { ! un = 2 * un + (unsigned long)(*ptr - '0'); ++ptr; if (n++ == maxlen) break; --- 1901,1911 ---- n += 2; /* skip over "0b" */ while ('0' <= *ptr && *ptr <= '1') { ! /* 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,1918 **** /* octal */ while ('0' <= *ptr && *ptr <= '7') { ! un = 8 * un + (uvarnumber_T)(*ptr - '0'); ++ptr; if (n++ == maxlen) break; --- 1916,1926 ---- /* octal */ while ('0' <= *ptr && *ptr <= '7') { ! /* 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,1931 **** n += 2; /* skip over "0x" */ while (vim_isxdigit(*ptr)) { ! un = 16 * un + (uvarnumber_T)hex2nr(*ptr); ++ptr; if (n++ == maxlen) break; --- 1933,1943 ---- n += 2; /* skip over "0x" */ while (vim_isxdigit(*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,1942 **** /* decimal */ while (VIM_ISDIGIT(*ptr)) { ! un = 10 * un + (uvarnumber_T)(*ptr - '0'); ++ptr; if (n++ == maxlen) break; --- 1948,1958 ---- /* decimal */ while (VIM_ISDIGIT(*ptr)) { ! /* 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,1958 **** if (nptr != NULL) { if (negative) /* account for leading '-' for decimal numbers */ ! *nptr = -(varnumber_T)un; else *nptr = (varnumber_T)un; } if (unptr != NULL) *unptr = un; --- 1966,1984 ---- if (nptr != NULL) { if (negative) /* account for leading '-' for decimal numbers */ ! { ! /* 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; *** ../vim-8.0.0218/src/eval.c 2017-01-14 20:06:11.123087733 +0100 --- src/eval.c 2017-01-22 18:18:11.942429692 +0100 *************** *** 4109,4129 **** { if (n2 == 0) /* give an error message? */ { - #ifdef FEAT_NUM64 if (n1 == 0) ! n1 = -0x7fffffffffffffffLL - 1; /* similar to NaN */ else if (n1 < 0) ! n1 = -0x7fffffffffffffffLL; else ! n1 = 0x7fffffffffffffffLL; ! #else ! if (n1 == 0) ! n1 = -0x7fffffffL - 1L; /* similar to NaN */ ! else if (n1 < 0) ! n1 = -0x7fffffffL; ! else ! n1 = 0x7fffffffL; ! #endif } else n1 = n1 / n2; --- 4109,4120 ---- { if (n2 == 0) /* give an error message? */ { if (n1 == 0) ! n1 = VARNUM_MIN; /* similar to NaN */ else if (n1 < 0) ! n1 = -VARNUM_MAX; else ! n1 = VARNUM_MAX; } else n1 = n1 / n2; *** ../vim-8.0.0218/src/evalfunc.c 2017-01-21 20:04:17.566757789 +0100 --- src/evalfunc.c 2017-01-22 18:18:11.946429667 +0100 *************** *** 3304,3324 **** if (get_float_arg(argvars, &f) == OK) { ! # ifdef FEAT_NUM64 ! if (f < -0x7fffffffffffffffLL) ! rettv->vval.v_number = -0x7fffffffffffffffLL; ! else if (f > 0x7fffffffffffffffLL) ! rettv->vval.v_number = 0x7fffffffffffffffLL; else rettv->vval.v_number = (varnumber_T)f; - # else - if (f < -0x7fffffff) - rettv->vval.v_number = -0x7fffffff; - else if (f > 0x7fffffff) - rettv->vval.v_number = 0x7fffffff; - else - rettv->vval.v_number = (varnumber_T)f; - # endif } } --- 3304,3315 ---- if (get_float_arg(argvars, &f) == OK) { ! if (f < -VARNUM_MAX) ! rettv->vval.v_number = -VARNUM_MAX; ! else if (f > VARNUM_MAX) ! rettv->vval.v_number = VARNUM_MAX; else rettv->vval.v_number = (varnumber_T)f; } } *** ../vim-8.0.0218/src/structs.h 2017-01-14 14:28:26.952592354 +0100 --- src/structs.h 2017-01-22 18:18:11.946429667 +0100 *************** *** 1133,1157 **** --- 1133,1175 ---- # ifdef PROTO typedef long varnumber_T; typedef unsigned long uvarnumber_T; + #define VARNUM_MIN LONG_MIN + #define VARNUM_MAX LONG_MAX + #define UVARNUM_MAX ULONG_MAX # else typedef __int64 varnumber_T; typedef unsigned __int64 uvarnumber_T; + #define VARNUM_MIN _I64_MIN + #define VARNUM_MAX _I64_MAX + #define UVARNUM_MAX _UI64_MAX # endif # elif defined(HAVE_STDINT_H) typedef int64_t varnumber_T; typedef uint64_t uvarnumber_T; + #define VARNUM_MIN INT64_MIN + #define VARNUM_MAX INT64_MAX + #define UVARNUM_MAX UINT64_MAX # else typedef long varnumber_T; typedef unsigned long uvarnumber_T; + #define VARNUM_MIN LONG_MIN + #define VARNUM_MAX LONG_MAX + #define UVARNUM_MAX ULONG_MAX # endif #else /* Use 32-bit Number. */ # if VIM_SIZEOF_INT <= 3 /* use long if int is smaller than 32 bits */ typedef long varnumber_T; typedef unsigned long uvarnumber_T; + #define VARNUM_MIN LONG_MIN + #define VARNUM_MAX LONG_MAX + #define UVARNUM_MAX ULONG_MAX # else typedef int varnumber_T; typedef unsigned int uvarnumber_T; + #define VARNUM_MIN INT_MIN + #define VARNUM_MAX INT_MAX + #define UVARNUM_MAX UINT_MAX # endif #endif *** ../vim-8.0.0218/src/testdir/test_viml.vim 2017-01-12 22:20:49.461383785 +0100 --- src/testdir/test_viml.vim 2017-01-22 18:18:11.946429667 +0100 *************** *** 1226,1232 **** call assert_equal( 9223372036854775807, 1 / 0) call assert_equal(-9223372036854775807, -1 / 0) ! call assert_equal(-9223372036854775808, 0 / 0) call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) --- 1226,1232 ---- call assert_equal( 9223372036854775807, 1 / 0) call assert_equal(-9223372036854775807, -1 / 0) ! call assert_equal(-9223372036854775807 - 1, 0 / 0) call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) *** ../vim-8.0.0218/src/version.c 2017-01-22 16:46:52.253278433 +0100 --- src/version.c 2017-01-22 18:33:21.376620042 +0100 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 219, /**/ -- Q: Why do ducks have flat feet? A: To stamp out forest fires. Q: Why do elephants have flat feet? A: To stamp out flaming ducks. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///