Skip to content

Commit 1d353a3

Browse files
fix platform specific fixnum boundaries
1 parent 86b1d2d commit 1d353a3

3 files changed

Lines changed: 137 additions & 137 deletions

File tree

‎array.c‎

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -474,12 +474,12 @@ ary_narrow_count(VALUE ary, long needle)
474474
return count;
475475
}
476476

477-
/* Sum as a long. Cannot overflow below 2**31 elements; callers check. */
478-
static long
477+
/* long long, not long (32-bit on LLP64). Callers check the length. */
478+
static long long
479479
ary_narrow_sum(VALUE ary)
480480
{
481481
const long len = RARRAY_LEN(ary);
482-
long acc = 0;
482+
long long acc = 0;
483483
ARY_NARROW_DISPATCH(ary, T, p, {
484484
for (long i = 0; i < len; i++) acc += p[i];
485485
});
@@ -5879,9 +5879,20 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
58795879
rb_array_stride(ary2) != RARRAY_STRIDE_VALUE)) {
58805880
return ary_narrow_equal(ary1, ary2, true);
58815881
}
5882-
for (i = 0; i < RARRAY_LEN(ary1); i++) {
5883-
if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5884-
return Qfalse;
5882+
5883+
/* rb_eql() can resize either array and evacuate ptrs */
5884+
p1 = RARRAY_CONST_PTR(ary1);
5885+
p2 = RARRAY_CONST_PTR(ary2);
5886+
len1 = RARRAY_LEN(ary1);
5887+
5888+
for (i = 0; i < len1; i++) {
5889+
if (p1[i] != p2[i]) {
5890+
if (!rb_eql(p1[i], p2[i])) return Qfalse;
5891+
len1 = RARRAY_LEN(ary1);
5892+
if (len1 != RARRAY_LEN(ary2)) return Qfalse;
5893+
p1 = RARRAY_CONST_PTR(ary1);
5894+
p2 = RARRAY_CONST_PTR(ary2);
5895+
}
58855896
}
58865897
return Qtrue;
58875898
}
@@ -6011,12 +6022,15 @@ rb_ary_includes(VALUE ary, VALUE item)
60116022
}
60126023

60136024
/* Test hooks for the stride machinery. Not public API. */
6025+
6026+
/* :nodoc: */
60146027
static VALUE
60156028
rb_ary_narrow_bang(VALUE ary)
60166029
{
60176030
return INT2FIX(ary_try_narrow(ary));
60186031
}
60196032

6033+
/* :nodoc: */
60206034
static VALUE
60216035
rb_ary_stride_m(VALUE ary)
60226036
{
@@ -8763,7 +8777,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
87638777
if (!block_given && FIXNUM_P(v) &&
87648778
RB_UNLIKELY(rb_array_stride(ary) != RARRAY_STRIDE_VALUE) &&
87658779
RARRAY_LEN(ary) < (1L << 30)) {
8766-
return rb_int_plus(LONG2NUM(ary_narrow_sum(ary)), v);
8780+
return rb_int_plus(LL2NUM(ary_narrow_sum(ary)), v);
87678781
}
87688782

87698783
bool init_is_float = RB_FLOAT_TYPE_P(v);

‎internal/array.h‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,30 @@ rarray_raw_ptr(VALUE ary)
3434
}
3535

3636
/* Load element i of a narrowed array as a C integer. The single place that
37-
* knows the width/sign encoding. */
38-
static inline long
37+
* knows the width/sign encoding. int64_t, not long: long is 32-bit on
38+
* LLP64 platforms. Dispatches once on the stride and sign flag bits
39+
* together, the same way io.c switches on FMODE_READABLE|FMODE_WRITABLE. */
40+
static inline int64_t
3941
rarray_narrow_load_int(VALUE ary, long i)
4042
{
4143
const void *p = rarray_raw_ptr(ary);
42-
if (rb_array_stride_unsigned_p(ary)) {
43-
switch (rb_array_stride(ary)) {
44-
case RARRAY_STRIDE_W8: return (long)((const uint8_t *)p)[i];
45-
case RARRAY_STRIDE_W16: return (long)((const uint16_t *)p)[i];
46-
default: return (long)((const uint32_t *)p)[i];
47-
}
48-
}
49-
switch (rb_array_stride(ary)) {
50-
case RARRAY_STRIDE_W8: return ((const int8_t *)p)[i];
51-
case RARRAY_STRIDE_W16: return ((const int16_t *)p)[i];
52-
default: return ((const int32_t *)p)[i];
44+
#define W(stride) ((VALUE)(stride) << RARRAY_STRIDE_SHIFT)
45+
switch (RBASIC(ary)->flags & (RARRAY_STRIDE_MASK | RARRAY_STRIDE_UNSIGNED)) {
46+
case W(RARRAY_STRIDE_W8): return ((const int8_t *)p)[i];
47+
case W(RARRAY_STRIDE_W16): return ((const int16_t *)p)[i];
48+
case W(RARRAY_STRIDE_W32): return ((const int32_t *)p)[i];
49+
case W(RARRAY_STRIDE_W8) | RARRAY_STRIDE_UNSIGNED: return ((const uint8_t *)p)[i];
50+
case W(RARRAY_STRIDE_W16) | RARRAY_STRIDE_UNSIGNED: return ((const uint16_t *)p)[i];
51+
default: return ((const uint32_t *)p)[i];
5352
}
53+
#undef W
5454
}
5555

5656
/* Decode element i of a narrowed array into a ::VALUE. */
5757
static inline VALUE
5858
rarray_narrow_aref(VALUE ary, long i)
5959
{
60-
return LONG2FIX(rarray_narrow_load_int(ary, i));
60+
return LL2NUM(rarray_narrow_load_int(ary, i));
6161
}
6262

6363
/* Core's RARRAY_AREF replaces the public macro. It adds a bounds assertion

0 commit comments

Comments
 (0)