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.
This commit is contained in:
parent
59c3fac6c4
commit
09295ea796
Notes:
git
2023-03-24 23:12:45 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
@ -1422,6 +1422,11 @@ rb_io_buffer_resize(VALUE self, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (data->flags & RB_IO_BUFFER_INTERNAL) {
|
if (data->flags & RB_IO_BUFFER_INTERNAL) {
|
||||||
|
if (size == 0) {
|
||||||
|
io_buffer_free(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void *base = realloc(data->base, size);
|
void *base = realloc(data->base, size);
|
||||||
|
|
||||||
if (!base) {
|
if (!base) {
|
||||||
|
@ -156,6 +156,24 @@ class TestIOBuffer < Test::Unit::TestCase
|
|||||||
assert_equal message, buffer.get_string(0, message.bytesize)
|
assert_equal message, buffer.get_string(0, message.bytesize)
|
||||||
end
|
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
|
def test_compare_same_size
|
||||||
buffer1 = IO::Buffer.new(1)
|
buffer1 = IO::Buffer.new(1)
|
||||||
assert_equal buffer1, buffer1
|
assert_equal buffer1, buffer1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user