@@ -1526,13 +1526,19 @@ VALUE rb_io_buffer_free_locked(VALUE self)
15261526 return self ;
15271527}
15281528
1529+ static bool
1530+ size_sum_is_bigger_than (size_t a , size_t b , size_t x )
1531+ {
1532+ struct rbimpl_size_mul_overflow_tag size = rbimpl_size_add_overflow (a , b );
1533+ return size .left || size .right > x ;
1534+ }
1535+
15291536// Validate that access to the buffer is within bounds, assuming you want to
15301537// access length bytes from the specified offset.
15311538static inline void
15321539io_buffer_validate_range (struct rb_io_buffer * buffer , size_t offset , size_t length )
15331540{
1534- // We assume here that offset + length won't overflow:
1535- if (offset + length > buffer -> size ) {
1541+ if (size_sum_is_bigger_than (offset , length , buffer -> size )) {
15361542 rb_raise (rb_eArgError , "Specified offset+length is bigger than the buffer size!" );
15371543 }
15381544}
@@ -1842,9 +1848,9 @@ rb_io_buffer_compare(VALUE self, VALUE other)
18421848}
18431849
18441850static void
1845- io_buffer_validate_type (size_t size , size_t offset )
1851+ io_buffer_validate_type (size_t size , size_t offset , size_t extend )
18461852{
1847- if (offset > size ) {
1853+ if (size_sum_is_bigger_than ( offset , extend , size ) ) {
18481854 rb_raise (rb_eArgError , "Type extends beyond end of buffer! (offset=%" PRIdSIZE " > size=%" PRIdSIZE ")" , offset , size );
18491855 }
18501856}
@@ -1944,7 +1950,7 @@ static ID RB_IO_BUFFER_DATA_TYPE_##name; \
19441950static VALUE \
19451951io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
19461952{ \
1947- io_buffer_validate_type(size, *offset + sizeof(type)); \
1953+ io_buffer_validate_type(size, *offset, sizeof(type)); \
19481954 type value; \
19491955 memcpy(&value, (char*)base + *offset, sizeof(type)); \
19501956 if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
@@ -1955,7 +1961,7 @@ io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
19551961static void \
19561962io_buffer_write_##name(const void* base, size_t size, size_t *offset, VALUE _value) \
19571963{ \
1958- io_buffer_validate_type(size, *offset + sizeof(type)); \
1964+ io_buffer_validate_type(size, *offset, sizeof(type)); \
19591965 type value = unwrap(_value); \
19601966 if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
19611967 memcpy((char*)base + *offset, &value, sizeof(type)); \
@@ -2483,7 +2489,7 @@ io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source
24832489
24842490 io_buffer_validate_range (buffer , offset , length );
24852491
2486- if (source_offset + length > source_size ) {
2492+ if (size_sum_is_bigger_than ( source_offset , length , source_size ) ) {
24872493 rb_raise (rb_eArgError , "The computed source range exceeds the size of the source buffer!" );
24882494 }
24892495
0 commit comments