Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing handling of offset argument. #7012

Merged
merged 1 commit into from Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 18 additions & 4 deletions io_buffer.c
Expand Up @@ -1093,6 +1093,8 @@ rb_io_buffer_free(VALUE self)
return self;
}

// Validate that access to the buffer is within bounds, assuming you want to
// access length bytes from the specified offset.
static inline void
io_buffer_validate_range(struct rb_io_buffer *data, size_t offset, size_t length)
{
Expand Down Expand Up @@ -2510,7 +2512,7 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of
struct rb_io_buffer *data = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data);

io_buffer_validate_range(data, 0, length);
io_buffer_validate_range(data, offset, length);

int descriptor = rb_io_descriptor(io);

Expand All @@ -2520,8 +2522,14 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of

struct io_buffer_pread_internal_argument argument = {
.descriptor = descriptor,
.base = base,

// Move the base pointer to the offset:
.base = (unsigned char*)base + offset,

// And the size to the length of data we want to read:
.size = length,

// From the offset in the file we want to read from:
.offset = from,
};

Expand Down Expand Up @@ -2677,7 +2685,7 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o
struct rb_io_buffer *data = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data);

io_buffer_validate_range(data, 0, length);
io_buffer_validate_range(data, offset, length);

int descriptor = rb_io_descriptor(io);

Expand All @@ -2687,8 +2695,14 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o

struct io_buffer_pwrite_internal_argument argument = {
.descriptor = descriptor,
.base = base,

// Move the base pointer to the offset:
.base = (unsigned char *)base + offset,

// And the size to the length of data we want to read:
.size = length,

// And the offset in the file we want to write from:
.offset = from,
};

Expand Down
29 changes: 29 additions & 0 deletions test/ruby/test_io_buffer.rb
Expand Up @@ -373,6 +373,20 @@ def test_pread
io.close!
end

def test_pread_offset
io = Tempfile.new
io.write("Hello World")
io.seek(0)

buffer = IO::Buffer.new(128)
buffer.pread(io, 6, 5, 6)

assert_equal "World", buffer.get_string(6, 5)
assert_equal 0, io.tell
ensure
io.close!
end

def test_pwrite
io = Tempfile.new

Expand All @@ -388,6 +402,21 @@ def test_pwrite
io.close!
end

def test_pwrite_offset
io = Tempfile.new

buffer = IO::Buffer.new(128)
buffer.set_string("Hello World")
buffer.pwrite(io, 6, 5, 6)

assert_equal 0, io.tell

io.seek(6)
assert_equal "World", io.read(5)
ensure
io.close!
end

def test_operators
source = IO::Buffer.for("1234123412")
mask = IO::Buffer.for("133\x00")
Expand Down