Skip to content

Commit

Permalink
Bugfix: Sub-table memory corruption (#14)
Browse files Browse the repository at this point in the history
Make sure sub-table memory isn't overwritten when reassigning other values in a parent Table.

Co-authored-by: Jon Börjesson <jon@84codes.com>
  • Loading branch information
viktorerlingsson and spuun authored Sep 22, 2023
1 parent 77b4b99 commit 0e687df
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
36 changes: 36 additions & 0 deletions spec/table_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,39 @@ describe AMQ::Protocol::Table do
t1.to_h.should eq({"x-stream-offset" => 1i64})
end
end

# Verifies bugfix for Sub-table memory corruption
# https://github.com/cloudamqp/amq-protocol.cr/pull/14
describe "should not overwrite sub-tables memory when reassigning values in a Table" do
it "when reassigning a Table" do
parent_table = AMQ::Protocol::Table.new
child_table = AMQ::Protocol::Table.new({"a": "b"})
parent_table["table"] = child_table

# Read child_table from io
table_from_io = parent_table["table"].as(AMQ::Protocol::Table)

# Overwrite child_table data in parent_table
parent_table["table"] = "foo"

# Verify that read_table wasn't modified by reassignment of "table"
table_from_io.should eq child_table
end

it "when reassigning a string" do
parent_table = AMQ::Protocol::Table.new
child_table = AMQ::Protocol::Table.new({"abc": "123"})

parent_table["foo"] = "bar"
parent_table["tbl"] = child_table

# Read child_table from io
read_table = parent_table["tbl"].as(AMQ::Protocol::Table)

# Overwrite string "foo" in parent_table
parent_table["foo"] = "foooo"

# Verify that read_table wasn't modified by reassignment of "foo"
read_table.should eq child_table
end
end
12 changes: 9 additions & 3 deletions src/amq/protocol/table.cr
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,15 @@ module AMQ
size ||= UInt32.from_io(io, format)
case io
when IO::Memory
bytes = io.to_slice[io.pos, size]
io.pos += size
self.new(IO::Memory.new(bytes, writeable: false))
if io.@writeable
mem = IO::Memory.new(size)
IO.copy(io, mem, size)
self.new(mem)
else
bytes = io.to_slice[io.pos, size]
io.pos += size
self.new(IO::Memory.new(bytes, writeable: false))
end
else
mem = IO::Memory.new(size)
IO.copy(io, mem, size)
Expand Down

0 comments on commit 0e687df

Please sign in to comment.