merge revision(s) 09295ea796: [Backport #19543]

IO::Buffer#resize: Free internal buffer if new size is zero (#7569)

	`#resize(0)` on an IO::Buffer with internal buffer allocated will
	result in calling `realloc(data->base, 0)`. The behavior of `realloc`
	with size = 0 is implementation-defined (glibc frees the object
	and returns NULL, while BSDs return an inaccessible object). And
	thus such usage is deprecated in standard C (upcoming C23 will make it
	UB).

	To avoid this problem, just `free`s the memory when the new size is zero.
	---
	 io_buffer.c                 |  5 +++++
	 test/ruby/test_io_buffer.rb | 18 ++++++++++++++++++
	 2 files changed, 23 insertions(+)
This commit is contained in:
nagachika 2023-07-16 16:42:12 +09:00
parent 141402d11c
commit c13757ed9a
3 changed files with 24 additions and 1 deletions

View file

@ -1391,6 +1391,11 @@ rb_io_buffer_resize(VALUE self, size_t size)
#endif
if (data->flags & RB_IO_BUFFER_INTERNAL) {
if (size == 0) {
io_buffer_free(data);
return;
}
void *base = realloc(data->base, size);
if (!base) {

View file

@ -142,6 +142,24 @@ class TestIOBuffer < Test::Unit::TestCase
assert_equal message, buffer.get_string(0, message.bytesize)
end
def test_resize_zero_internal
buffer = IO::Buffer.new(1)
buffer.resize(0)
assert_equal 0, buffer.size
buffer.resize(1)
assert_equal 1, buffer.size
end
def test_resize_zero_external
buffer = IO::Buffer.for('1')
assert_raise IO::Buffer::AccessError do
buffer.resize(0)
end
end
def test_compare_same_size
buffer1 = IO::Buffer.new(1)
assert_equal buffer1, buffer1

View file

@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 2
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 68
#define RUBY_PATCHLEVEL 69
#include "ruby/version.h"
#include "ruby/internal/abi.h"