diff options
| author | Peter Zhu <peter@peterzhu.ca> | 2024-12-24 17:46:43 -0500 |
|---|---|---|
| committer | Peter Zhu <peter@peterzhu.ca> | 2025-01-02 11:03:04 -0500 |
| commit | 99ff0224a564b59df3ba8fbd7911dd41a7fdde34 (patch) | |
| tree | 50119e2d938e21080f7950ab9f067a0f63b78ce3 /include/ruby/internal | |
| parent | b8c4af24f920a973cfa1f7b671825e8a5421368c (diff) | |
Move rbimpl_size_add_overflow from gc.c to memory.h
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12459
Diffstat (limited to 'include/ruby/internal')
| -rw-r--r-- | include/ruby/internal/memory.h | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h index d231e62982..9fc6c39efc 100644 --- a/include/ruby/internal/memory.h +++ b/include/ruby/internal/memory.h @@ -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. |
