Add integer overflow check macros for add/sub as well as mul

This commit is contained in:
Nobuyoshi Nakada 2024-11-08 18:35:52 +09:00 коммит произвёл Nobuyoshi Nakada
Родитель d1969474e9
Коммит edb1c8215d
3 изменённых файлов: 114 добавлений и 24 удалений

Просмотреть файл

@ -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