diff --git a/ext/strscan/lib/strscan/strscan.rb b/ext/strscan/lib/strscan/strscan.rb index 46acc7ea823f07..07ed102d9a8cfe 100644 --- a/ext/strscan/lib/strscan/strscan.rb +++ b/ext/strscan/lib/strscan/strscan.rb @@ -1,17 +1,41 @@ # frozen_string_literal: true class StringScanner + # :markup: markdown + # # call-seq: - # scan_integer(base: 10) + # scan_integer(base: 10) -> integer or nil + # + # Returns an integer scanned from `self`, + # beginning at the current position; + # returns `nil` if no such integer was available. + # + # When `base` is `10` (the default), + # equivalent to calling #scan with argument +pattern+ + # as `'[+-]?\d+'`: + # + # ```ruby + # scanner = StringScanner.new('Form 27B/6') + # scanner.scan_integer # => nil # No integer at position 0. + # scanner.pos = 5 + # scanner.scan_integer # => 27 + # scanner.matched # => "27" + # scanner.pos # => 7 + # ``` # - # If `base` isn't provided or is `10`, then it is equivalent to calling `#scan` with a `[+-]?\d+` pattern, - # and returns an Integer or nil. + # When `base` is `16` (the only other value allowed), + # equivalent to calling #scan with argument `pattern` + # as `'[+-]?(0x)?[0-9a-fA-F]+'`: # - # If `base` is `16`, then it is equivalent to calling `#scan` with a `[+-]?(0x)?[0-9a-fA-F]+` pattern, - # and returns an Integer or nil. + # ```ruby + # scanner.pos = 5 + # scanner.scan_integer(base: 16) # => 635 + # scanner.matched # => "27B" + # scanner.pos # => 8 + # ``` # - # The scanned string must be encoded with an ASCII compatible encoding, otherwise - # Encoding::CompatibilityError will be raised. + # Raises Encoding::CompatibilityError if `self` does not have + # an ASCII compatible encoding. def scan_integer(base: 10) case base when 10 diff --git a/file.c b/file.c index b045e8e899bc9f..ae741ce5671399 100644 --- a/file.c +++ b/file.c @@ -5471,10 +5471,10 @@ rb_file_join_ary(VALUE ary) } else { tail = chompdirsep(name, name + len, true, rb_enc_get(result)); - if (RSTRING_PTR(tmp) && isdirsep(RSTRING_PTR(tmp)[0])) { + if (RSTRING_LEN(tmp) > 0 && isdirsep(RSTRING_PTR(tmp)[0])) { rb_str_set_len(result, tail - name); } - else if (!*tail) { + else if (tail == name + len) { rb_str_cat(result, "/", 1); } } @@ -5518,7 +5518,7 @@ rb_file_join_fastpath(long argc, VALUE *args) long tmp_len; RSTRING_GETMEM(tmp, tmp_s, tmp_len); - if (isdirsep(tmp_s[0])) { + if (tmp_len > 0 && isdirsep(tmp_s[0])) { // right side has a leading separator, remove left side separators. long trailing_seps = 0; while (isdirsep(name[len - trailing_seps - 1])) { @@ -5526,7 +5526,7 @@ rb_file_join_fastpath(long argc, VALUE *args) } rb_str_set_len(result, len - trailing_seps); } - else if (!isdirsep(name[len - 1])) { + else if (len < 1 || !isdirsep(name[len - 1])) { // neither side have a separator, append one; rb_str_cat(result, "/", 1); } diff --git a/io_buffer.c b/io_buffer.c index 6bd0b3cfd38cd3..95d6b2491397fb 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -3509,13 +3509,21 @@ io_buffer_xor(VALUE self, VALUE mask) struct rb_io_buffer *mask_buffer = NULL; TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer); - io_buffer_check_mask_size(mask_buffer->size); + const void *base; + size_t size; + io_buffer_get_bytes_for_reading(buffer, &base, &size); - VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size)); + const void *mask_base; + size_t mask_size; + io_buffer_get_bytes_for_reading(mask_buffer, &mask_base, &mask_size); + + io_buffer_check_mask_size(mask_size); + + VALUE output = rb_io_buffer_new(NULL, size, io_flags_for_size(size)); struct rb_io_buffer *output_buffer = NULL; TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer); - memory_xor(output_buffer->base, buffer->base, buffer->size, mask_buffer->base, mask_buffer->size); + memory_xor(output_buffer->base, base, size, mask_base, mask_size); return output; } diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb index 92a81ddd97cce0..4022bd5d4873cf 100644 --- a/test/ruby/test_io_buffer.rb +++ b/test/ruby/test_io_buffer.rb @@ -710,6 +710,7 @@ def test_operators_raise_on_freed_self mask = IO::Buffer.for("ABCDEFGH") assert_raise(IO::Buffer::InvalidatedError) { slice & mask } assert_raise(IO::Buffer::InvalidatedError) { slice | mask } + assert_raise(IO::Buffer::InvalidatedError) { slice ^ mask } end def test_operators_raise_on_freed_mask @@ -720,6 +721,7 @@ def test_operators_raise_on_freed_mask source = IO::Buffer.for("ABCDEFGH") assert_raise(IO::Buffer::InvalidatedError) { source & mask_slice } assert_raise(IO::Buffer::InvalidatedError) { source | mask_slice } + assert_raise(IO::Buffer::InvalidatedError) { source ^ mask_slice } end def test_bit_count