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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui