Rename to struct rbimpl_size_overflow_tag

This struct is used for addition not only for multiplication, so
remove the word `mul`, and make the member names more descriptive.
This commit is contained in:
Nobuyoshi Nakada 2025-12-17 14:28:03 +09:00 committed by Nobuyoshi Nakada
parent 79f36c544a
commit 61bab18890
Notes: git 2025-12-17 08:36:28 +00:00
3 changed files with 60 additions and 59 deletions

42
gc.c
View File

@ -484,21 +484,21 @@ rb_malloc_grow_capa(size_t current, size_t type_size)
return new_capacity;
}
static inline struct rbimpl_size_mul_overflow_tag
static inline struct rbimpl_size_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 = rbimpl_size_add_overflow(t.right, z);
return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left, u.right };
struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
struct rbimpl_size_overflow_tag u = rbimpl_size_add_overflow(t.result, z);
return (struct rbimpl_size_overflow_tag) { t.overflowed || u.overflowed, u.result };
}
static inline struct rbimpl_size_mul_overflow_tag
static inline struct rbimpl_size_overflow_tag
size_mul_add_mul_overflow(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
{
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 = rbimpl_size_add_overflow(t.right, u.right);
return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left || v.left, v.right };
struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
struct rbimpl_size_overflow_tag u = rbimpl_size_mul_overflow(z, w);
struct rbimpl_size_overflow_tag v = rbimpl_size_add_overflow(t.result, u.result);
return (struct rbimpl_size_overflow_tag) { t.overflowed || u.overflowed || v.overflowed, v.result };
}
PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3);
@ -506,9 +506,9 @@ PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3);
static inline size_t
size_mul_or_raise(size_t x, size_t y, VALUE exc)
{
struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
if (LIKELY(!t.left)) {
return t.right;
struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
if (LIKELY(!t.overflowed)) {
return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@ -532,9 +532,9 @@ rb_size_mul_or_raise(size_t x, size_t y, VALUE exc)
static inline size_t
size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc)
{
struct rbimpl_size_mul_overflow_tag t = size_mul_add_overflow(x, y, z);
if (LIKELY(!t.left)) {
return t.right;
struct rbimpl_size_overflow_tag t = size_mul_add_overflow(x, y, z);
if (LIKELY(!t.overflowed)) {
return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@ -559,9 +559,9 @@ rb_size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc)
static inline size_t
size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc)
{
struct rbimpl_size_mul_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w);
if (LIKELY(!t.left)) {
return t.right;
struct rbimpl_size_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w);
if (LIKELY(!t.overflowed)) {
return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@ -5372,11 +5372,11 @@ ruby_mimcalloc(size_t num, size_t size)
{
void *mem;
#if CALC_EXACT_MALLOC_SIZE
struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(num, size);
if (UNLIKELY(t.left)) {
struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(num, size);
if (UNLIKELY(t.overflowed)) {
return NULL;
}
size = t.right + sizeof(struct malloc_obj_info);
size = t.result + sizeof(struct malloc_obj_info);
mem = calloc1(size);
if (!mem) {
return NULL;

View File

@ -408,7 +408,8 @@ typedef uint128_t DSIZE_T;
/**
* @private
*
* This is an implementation detail of rbimpl_size_mul_overflow().
* This is an implementation detail of rbimpl_size_mul_overflow() and
* rbimpl_size_add_overflow().
*
* @internal
*
@ -416,9 +417,9 @@ typedef uint128_t DSIZE_T;
* nothing more than std::variant<std::size_t> if we could use recent C++, but
* reality is we cannot.
*/
struct rbimpl_size_mul_overflow_tag {
bool left; /**< Whether overflow happened or not. */
size_t right; /**< Multiplication result. */
struct rbimpl_size_overflow_tag {
bool overflowed; /**< Whether overflow happened or not. */
size_t result; /**< Calculation result. */
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
@ -572,46 +573,46 @@ RBIMPL_ATTR_CONST()
*
* @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`.
* @return `{ overflowed, result }`, where `overflowed` is whether there is
* an integer overflow or not, and `result` is a (possibly
* overflowed) result of `x` * `y`.
*
* @internal
*
* This is in fact also an implementation detail of ruby_xmalloc2() etc.
*/
static inline struct rbimpl_size_mul_overflow_tag
static inline struct rbimpl_size_overflow_tag
rbimpl_size_mul_overflow(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
struct rbimpl_size_overflow_tag ret = { false, 0, };
#if defined(ckd_mul)
ret.left = ckd_mul(&ret.right, x, y);
ret.overflowed = ckd_mul(&ret.result, x, y);
#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
ret.left = __builtin_mul_overflow(x, y, &ret.right);
ret.overflowed = __builtin_mul_overflow(x, y, &ret.result);
#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 = RBIMPL_CAST((size_t)dz);
ret.overflowed = dz > SIZE_MAX;
ret.result = RBIMPL_CAST((size_t)dz);
#elif defined(_MSC_VER) && defined(_M_AMD64)
unsigned __int64 dp = 0;
unsigned __int64 dz = _umul128(x, y, &dp);
ret.left = RBIMPL_CAST((bool)dp);
ret.right = RBIMPL_CAST((size_t)dz);
ret.overflowed = RBIMPL_CAST((bool)dp);
ret.result = RBIMPL_CAST((size_t)dz);
#elif defined(_MSC_VER) && defined(_M_ARM64)
ret.left = __umulh(x, y) != 0;
ret.right = x * y;
ret.overflowed = __umulh(x, y) != 0;
ret.result = x * y;
#else
/* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */
ret.left = (y != 0) && (x > SIZE_MAX / y);
ret.right = x * y;
ret.overflowed = (y != 0) && (x > SIZE_MAX / y);
ret.result = x * y;
#endif
return ret;
@ -635,11 +636,11 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
static inline size_t
rbimpl_size_mul_or_raise(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag size =
struct rbimpl_size_overflow_tag size =
rbimpl_size_mul_overflow(x, y);
if (RB_LIKELY(! size.left)) {
return size.right;
if (RB_LIKELY(! size.overflowed)) {
return size.result;
}
else {
ruby_malloc_size_overflow(x, y);
@ -662,33 +663,33 @@ RBIMPL_ATTR_CONST()
*
* @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`.
* @return `{ overflowed, result }`, where `overflowed` is whether there is
* an integer overflow or not, and `result` is a (possibly
* overflowed) result of `x` + `y`.
*
* @internal
*/
static inline struct rbimpl_size_mul_overflow_tag
static inline struct rbimpl_size_overflow_tag
rbimpl_size_add_overflow(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
struct rbimpl_size_overflow_tag ret = { false, 0, };
#if defined(ckd_add)
ret.left = ckd_add(&ret.right, x, y);
ret.overflowed = ckd_add(&ret.result, x, y);
#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
ret.left = __builtin_add_overflow(x, y, &ret.right);
ret.overflowed = __builtin_add_overflow(x, y, &ret.result);
#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;
ret.overflowed = dz > SIZE_MAX;
ret.result = (size_t)dz;
#else
ret.right = x + y;
ret.left = ret.right < y;
ret.result = x + y;
ret.overflowed = ret.result < y;
#endif
@ -710,11 +711,11 @@ rbimpl_size_add_overflow(size_t x, size_t y)
static inline size_t
rbimpl_size_add_or_raise(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag size =
struct rbimpl_size_overflow_tag size =
rbimpl_size_add_overflow(x, y);
if (RB_LIKELY(!size.left)) {
return size.right;
if (RB_LIKELY(!size.overflowed)) {
return size.result;
}
else {
ruby_malloc_add_size_overflow(x, y);

View File

@ -1527,8 +1527,8 @@ VALUE rb_io_buffer_free_locked(VALUE self)
static bool
size_sum_is_bigger_than(size_t a, size_t b, size_t x)
{
struct rbimpl_size_mul_overflow_tag size = rbimpl_size_add_overflow(a, b);
return size.left || size.right > x;
struct rbimpl_size_overflow_tag size = rbimpl_size_add_overflow(a, b);
return size.overflowed || size.result > x;
}
// Validate that access to the buffer is within bounds, assuming you want to