forked from aniani/vim
patch 8.0.0219: ubsan reports errors for overflow
Problem: Ubsan reports errors for integer overflow. Solution: Define macros for minimum and maximum values. Select an expression based on the value. (Mike Williams)
This commit is contained in:
@@ -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;
|
||||
|
15
src/eval.c
15
src/eval.c
@@ -4109,21 +4109,12 @@ eval6(
|
||||
{
|
||||
if (n2 == 0) /* give an error message? */
|
||||
{
|
||||
#ifdef FEAT_NUM64
|
||||
if (n1 == 0)
|
||||
n1 = -0x7fffffffffffffffLL - 1; /* similar to NaN */
|
||||
n1 = VARNUM_MIN; /* similar to NaN */
|
||||
else if (n1 < 0)
|
||||
n1 = -0x7fffffffffffffffLL;
|
||||
n1 = -VARNUM_MAX;
|
||||
else
|
||||
n1 = 0x7fffffffffffffffLL;
|
||||
#else
|
||||
if (n1 == 0)
|
||||
n1 = -0x7fffffffL - 1L; /* similar to NaN */
|
||||
else if (n1 < 0)
|
||||
n1 = -0x7fffffffL;
|
||||
else
|
||||
n1 = 0x7fffffffL;
|
||||
#endif
|
||||
n1 = VARNUM_MAX;
|
||||
}
|
||||
else
|
||||
n1 = n1 / n2;
|
||||
|
@@ -3304,21 +3304,12 @@ f_float2nr(typval_T *argvars, typval_T *rettv)
|
||||
|
||||
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;
|
||||
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;
|
||||
# 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1133,25 +1133,43 @@ typedef long_u hash_T; /* Type for hi_hash */
|
||||
# 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
|
||||
|
||||
|
@@ -1226,7 +1226,7 @@ func Test_num64()
|
||||
|
||||
call assert_equal( 9223372036854775807, 1 / 0)
|
||||
call assert_equal(-9223372036854775807, -1 / 0)
|
||||
call assert_equal(-9223372036854775808, 0 / 0)
|
||||
call assert_equal(-9223372036854775807 - 1, 0 / 0)
|
||||
|
||||
call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
|
||||
call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
|
||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
219,
|
||||
/**/
|
||||
218,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user