Skip to content

Commit f9175a9

Browse files
authored
Ensure safe handling of IO::Buffer#hexdump width. (ruby#16593)
1 parent 843bb9b commit f9175a9

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

io_buffer.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
3939

4040
enum {
4141
RB_IO_BUFFER_HEXDUMP_DEFAULT_WIDTH = 16,
42+
RB_IO_BUFFER_HEXDUMP_MAXIMUM_WIDTH = 1024,
4243

4344
RB_IO_BUFFER_INSPECT_HEXDUMP_MAXIMUM_SIZE = 256,
4445
RB_IO_BUFFER_INSPECT_HEXDUMP_WIDTH = 16,
@@ -384,7 +385,7 @@ io_buffer_extract_size(VALUE argument)
384385
}
385386

386387
// Extract a width argument, which must be a non-negative integer, and must be
387-
// at least the given minimum.
388+
// at least the given minimum and at most RB_IO_BUFFER_HEXDUMP_MAXIMUM_WIDTH.
388389
static inline size_t
389390
io_buffer_extract_width(VALUE argument, size_t minimum)
390391
{
@@ -398,6 +399,10 @@ io_buffer_extract_width(VALUE argument, size_t minimum)
398399
rb_raise(rb_eArgError, "Width must be at least %" PRIuSIZE "!", minimum);
399400
}
400401

402+
if (width > RB_IO_BUFFER_HEXDUMP_MAXIMUM_WIDTH) {
403+
rb_raise(rb_eArgError, "Width must be at most %" PRIuSIZE "!", (size_t)RB_IO_BUFFER_HEXDUMP_MAXIMUM_WIDTH);
404+
}
405+
401406
return width;
402407
}
403408

test/ruby/test_io_buffer.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,4 +960,48 @@ def test_locked_throw
960960
refute_predicate buf, :locked?
961961
buf.locked { }
962962
end
963+
964+
def test_hexdump_default_width
965+
buffer = IO::Buffer.for("Hello World")
966+
hexdump = buffer.hexdump
967+
assert_include hexdump, "Hello World"
968+
assert_include hexdump, "0x00000000"
969+
end
970+
971+
def test_hexdump_custom_width
972+
buffer = IO::Buffer.for("A" * 64)
973+
hexdump = buffer.hexdump(0, 64, 32)
974+
assert_include hexdump, "0x00000000"
975+
assert_include hexdump, "0x00000020"
976+
end
977+
978+
def test_hexdump_maximum_width
979+
buffer = IO::Buffer.for("A" * 2048)
980+
# Maximum width is 1024
981+
hexdump = buffer.hexdump(0, 1024, 1024)
982+
assert_include hexdump, "0x00000000"
983+
end
984+
985+
def test_hexdump_width_too_large
986+
buffer = IO::Buffer.for("A")
987+
# Width exceeding maximum (1024) should raise ArgumentError
988+
assert_raise(ArgumentError) do
989+
buffer.hexdump(0, 1, 1025)
990+
end
991+
end
992+
993+
def test_hexdump_width_negative
994+
buffer = IO::Buffer.for("A")
995+
assert_raise(ArgumentError) do
996+
buffer.hexdump(0, 1, -1)
997+
end
998+
end
999+
1000+
def test_hexdump_width_zero
1001+
buffer = IO::Buffer.for("A")
1002+
# Width must be at least 1
1003+
assert_raise(ArgumentError) do
1004+
buffer.hexdump(0, 1, 0)
1005+
end
1006+
end
9631007
end

0 commit comments

Comments
 (0)