зеркало из https://github.com/github/ruby.git
Add integer overflow check macros for add/sub as well as mul
This commit is contained in:
Родитель
d1969474e9
Коммит
edb1c8215d
28
configure.ac
28
configure.ac
|
@ -20,6 +20,7 @@ RUBY_M4_INCLUDE([colorize_result.m4])dnl
|
|||
RUBY_M4_INCLUDE([ruby_append_option.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_append_options.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_check_builtin_func.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_check_builtin_overflow.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_check_builtin_setjmp.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_check_header.m4])dnl
|
||||
RUBY_M4_INCLUDE([ruby_check_printf_prefix.m4])dnl
|
||||
|
@ -2297,10 +2298,6 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_clzl, [__builtin_clzl(0)])
|
|||
RUBY_CHECK_BUILTIN_FUNC(__builtin_clzll, [__builtin_clzll(0)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_ctz, [__builtin_ctz(0)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_ctzll, [__builtin_ctzll(0)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_add_overflow, [int x;__builtin_add_overflow(0,0,&x)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_sub_overflow, [int x;__builtin_sub_overflow(0,0,&x)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow, [int x;__builtin_mul_overflow(0,0,&x)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow_p, [__builtin_mul_overflow_p(0,0,(int)0)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_constant_p, [__builtin_constant_p(0)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_choose_expr, [
|
||||
[int x[__extension__(__builtin_choose_expr(1, 1, -1))]];
|
||||
|
@ -2316,26 +2313,9 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_types_compatible_p, [__builtin_types_compatibl
|
|||
RUBY_CHECK_BUILTIN_FUNC(__builtin_trap, [__builtin_trap()])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_expect, [__builtin_expect(0, 0)])
|
||||
|
||||
AS_IF([test "$rb_cv_builtin___builtin_mul_overflow" != no], [
|
||||
AC_CACHE_CHECK(for __builtin_mul_overflow with long long arguments, rb_cv_use___builtin_mul_overflow_long_long, [
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||
#pragma clang optimize off
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
long long x = 0, y;
|
||||
__builtin_mul_overflow(x, x, &y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
]])],
|
||||
rb_cv_use___builtin_mul_overflow_long_long=yes,
|
||||
rb_cv_use___builtin_mul_overflow_long_long=no)])
|
||||
])
|
||||
AS_IF([test "$rb_cv_use___builtin_mul_overflow_long_long" = yes], [
|
||||
AC_DEFINE(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG, 1)
|
||||
])
|
||||
RUBY_CHECK_BUILTIN_OVERFLOW(add)
|
||||
RUBY_CHECK_BUILTIN_OVERFLOW(sub)
|
||||
RUBY_CHECK_BUILTIN_OVERFLOW(mul)
|
||||
|
||||
AS_IF([test "$ac_cv_func_qsort_r" != no], [
|
||||
AC_CACHE_CHECK(whether qsort_r is GNU version, rb_cv_gnu_qsort_r,
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
|
||||
#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)
|
||||
|
||||
#ifndef MUL_OVERFLOW_SIGNED_INTEGER_P
|
||||
#if __has_builtin(__builtin_mul_overflow_p)
|
||||
# define MUL_OVERFLOW_P(a, b) \
|
||||
__builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
|
||||
|
@ -131,6 +132,87 @@
|
|||
# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
|
||||
# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ADD_OVERFLOW_SIGNED_INTEGER_P
|
||||
#if __has_builtin(__builtin_add_overflow_p)
|
||||
# define ADD_OVERFLOW_P(a, b) \
|
||||
__builtin_add_overflow_p((a), (b), (__typeof__(a * b))0)
|
||||
#elif __has_builtin(__builtin_add_overflow)
|
||||
# define ADD_OVERFLOW_P(a, b) \
|
||||
__extension__ ({ __typeof__(a) c; __builtin_add_overflow((a), (b), &c); })
|
||||
#endif
|
||||
|
||||
#define ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
|
||||
(a) > 0 ? (b) > (max) - (a) : (b) < (min) - (a))
|
||||
|
||||
#if __has_builtin(__builtin_add_overflow_p)
|
||||
/* __builtin_add_overflow_p can take bitfield */
|
||||
/* and GCC permits bitfields for integers other than int */
|
||||
# define ADD_OVERFLOW_FIXNUM_P(a, b) \
|
||||
__extension__ ({ \
|
||||
struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
|
||||
__builtin_add_overflow_p((a), (b), c.fixnum); \
|
||||
})
|
||||
#else
|
||||
# define ADD_OVERFLOW_FIXNUM_P(a, b) \
|
||||
ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
|
||||
#endif
|
||||
|
||||
#if defined(ADD_OVERFLOW_P) && defined(USE___BUILTIN_ADD_OVERFLOW_LONG_LONG)
|
||||
# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
|
||||
#else
|
||||
# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
|
||||
#endif
|
||||
|
||||
#ifdef ADD_OVERFLOW_P
|
||||
# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
|
||||
# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_P(a, b)
|
||||
#else
|
||||
# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
|
||||
# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SUB_OVERFLOW_SIGNED_INTEGER_P
|
||||
#if __has_builtin(__builtin_sub_overflow_p)
|
||||
# define SUB_OVERFLOW_P(a, b) \
|
||||
__builtin_sub_overflow_p((a), (b), (__typeof__(a * b))0)
|
||||
#elif __has_builtin(__builtin_sub_overflow)
|
||||
# define SUB_OVERFLOW_P(a, b) \
|
||||
__extension__ ({ __typeof__(a) c; __builtin_sub_overflow((a), (b), &c); })
|
||||
#endif
|
||||
|
||||
#define SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
|
||||
(b) > 0 ? (a) < (min) + (b) : (a) > (max) + (b))
|
||||
|
||||
#if __has_builtin(__builtin_sub_overflow_p)
|
||||
/* __builtin_sub_overflow_p can take bitfield */
|
||||
/* and GCC permits bitfields for integers other than int */
|
||||
# define SUB_OVERFLOW_FIXNUM_P(a, b) \
|
||||
__extension__ ({ \
|
||||
struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
|
||||
__builtin_sub_overflow_p((a), (b), c.fixnum); \
|
||||
})
|
||||
#else
|
||||
# define SUB_OVERFLOW_FIXNUM_P(a, b) \
|
||||
SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
|
||||
#endif
|
||||
|
||||
#if defined(SUB_OVERFLOW_P) && defined(USE___BUILTIN_SUB_OVERFLOW_LONG_LONG)
|
||||
# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
|
||||
#else
|
||||
# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
|
||||
#endif
|
||||
|
||||
#ifdef SUB_OVERFLOW_P
|
||||
# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
|
||||
# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_P(a, b)
|
||||
#else
|
||||
# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
|
||||
# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UINT128_T
|
||||
# define bit_length(x) \
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
dnl -*- Autoconf -*-
|
||||
AC_DEFUN([RUBY_CHECK_BUILTIN_OVERFLOW], [dnl
|
||||
{ # $0($1)
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_[$1]_overflow, [int x;__builtin_[$1]_overflow(0,0,&x)])
|
||||
RUBY_CHECK_BUILTIN_FUNC(__builtin_[$1]_overflow_p, [__builtin_[$1]_overflow_p(0,0,(int)0)])
|
||||
|
||||
AS_IF([test "$rb_cv_builtin___builtin_[$1]_overflow" != no], [
|
||||
AC_CACHE_CHECK(for __builtin_[$1]_overflow with long long arguments, rb_cv_use___builtin_[$1]_overflow_long_long, [
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||
@%:@pragma clang optimize off
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
long long x = 0, y;
|
||||
__builtin_$1_overflow(x, x, &y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
]])],
|
||||
rb_cv_use___builtin_[$1]_overflow_long_long=yes,
|
||||
rb_cv_use___builtin_[$1]_overflow_long_long=no)])
|
||||
])
|
||||
AS_IF([test "$rb_cv_use___builtin_[$1]_overflow_long_long" = yes], [
|
||||
AC_DEFINE(USE___BUILTIN_[]AS_TR_CPP($1)_OVERFLOW_LONG_LONG, 1)
|
||||
])
|
||||
}
|
||||
])dnl
|
Загрузка…
Ссылка в новой задаче