Move rbimpl_size_add_overflow from gc.c to memory.h

This commit is contained in:
Peter Zhu 2024-12-24 17:46:43 -05:00
parent b8c4af24f9
commit 99ff0224a5
Notes: git 2025-01-02 16:03:26 +00:00
2 changed files with 97 additions and 30 deletions

40
gc.c
View File

@ -480,39 +480,11 @@ rb_malloc_grow_capa(size_t current, size_t type_size)
return new_capacity;
}
static inline struct rbimpl_size_mul_overflow_tag
size_add_overflow(size_t x, size_t y)
{
size_t z;
bool p;
#if 0
#elif defined(ckd_add)
p = ckd_add(&z, x, y);
#elif __has_builtin(__builtin_add_overflow)
p = __builtin_add_overflow(x, y, &z);
#elif defined(DSIZE_T)
RB_GNUC_EXTENSION DSIZE_T dx = x;
RB_GNUC_EXTENSION DSIZE_T dy = y;
RB_GNUC_EXTENSION DSIZE_T dz = dx + dy;
p = dz > SIZE_MAX;
z = (size_t)dz;
#else
z = x + y;
p = z < y;
#endif
return (struct rbimpl_size_mul_overflow_tag) { p, z, };
}
static inline struct rbimpl_size_mul_overflow_tag
size_mul_add_overflow(size_t x, size_t y, size_t z) /* x * y + z */
{
struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
struct rbimpl_size_mul_overflow_tag u = size_add_overflow(t.right, z);
struct rbimpl_size_mul_overflow_tag u = rbimpl_size_add_overflow(t.right, z);
return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left, u.right };
}
@ -521,7 +493,7 @@ size_mul_add_mul_overflow(size_t x, size_t y, size_t z, size_t w) /* x * y + z *
{
struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
struct rbimpl_size_mul_overflow_tag u = rbimpl_size_mul_overflow(z, w);
struct rbimpl_size_mul_overflow_tag v = size_add_overflow(t.right, u.right);
struct rbimpl_size_mul_overflow_tag v = rbimpl_size_add_overflow(t.right, u.right);
return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left || v.left, v.right };
}
@ -4590,6 +4562,14 @@ ruby_malloc_size_overflow(size_t count, size_t elsize)
count, elsize);
}
void
ruby_malloc_add_size_overflow(size_t x, size_t y)
{
rb_raise(rb_eArgError,
"malloc: possible integer overflow (%"PRIuSIZE"+%"PRIuSIZE")",
x, y);
}
static void *ruby_xmalloc2_body(size_t n, size_t size);
void *

View File

@ -488,6 +488,18 @@ RBIMPL_ATTR_NORETURN()
*/
void ruby_malloc_size_overflow(size_t x, size_t y);
RBIMPL_ATTR_NORETURN()
/**
* @private
*
* This is an implementation detail. People don't use this directly.
*
* @param[in] x Arbitrary value.
* @param[in] y Arbitrary value.
* @exception rb_eArgError `x` + `y` would integer overflow.
*/
void ruby_malloc_add_size_overflow(size_t x, size_t y);
#ifdef HAVE_RB_GC_GUARDED_PTR_VAL
volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val);
#endif
@ -635,6 +647,81 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
}
}
#if defined(__DOXYGEN__)
RBIMPL_ATTR_CONSTEXPR(CXX14)
#elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */
#elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0)
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */
#endif
RBIMPL_ATTR_CONST()
/**
* @private
*
* This is an implementation detail. People don't use this directly.
*
* @param[in] x Arbitrary value.
* @param[in] y Arbitrary value.
* @return `{ left, right }`, where `left` is whether there is an integer
* overflow or not, and `right` is a (possibly overflowed) result
* of `x` + `y`.
*
* @internal
*/
static inline struct rbimpl_size_mul_overflow_tag
rbimpl_size_add_overflow(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
#if defined(ckd_add)
ret.left = ckd_add(&ret.right, x, y);
#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
ret.left = __builtin_add_overflow(x, y, &ret.right);
#elif defined(DSIZE_T)
RB_GNUC_EXTENSION DSIZE_T dx = x;
RB_GNUC_EXTENSION DSIZE_T dy = y;
RB_GNUC_EXTENSION DSIZE_T dz = dx + dy;
ret.left = dz > SIZE_MAX;
ret.right = (size_t)dz;
#else
ret.right = x + y;
ret.left = ret.right < y;
#endif
return ret;
}
/**
* @private
*
* This is an implementation detail. People don't use this directly.
*
* @param[in] x Arbitrary value.
* @param[in] y Arbitrary value.
* @exception rb_eArgError Multiplication could integer overflow.
* @return `x` + `y`.
*
* @internal
*/
static inline size_t
rbimpl_size_add_or_raise(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag size =
rbimpl_size_add_overflow(x, y);
if (RB_LIKELY(!size.left)) {
return size.right;
}
else {
ruby_malloc_add_size_overflow(x, y);
RBIMPL_UNREACHABLE_RETURN(0);
}
}
/**
* This is an implementation detail of #RB_ALLOCV_N(). People don't use this
* directly.