Skip to content

Commit

Permalink
Implement a simpler regression test for #341
Browse files Browse the repository at this point in the history
What is happening is that when we call into a recursive packing
proc, we first save the packer buffer state onto the stack
and then reset the buffer.

Once we return from the proc, the original buffer state is copied
back.

The problem with this is that if any of the chunk has a mapped string
then they are not reachable by any Ruby object and may be garbage collected
at any moment.
  • Loading branch information
byroot committed Jul 13, 2023
1 parent 79027da commit e48df01
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
27 changes: 27 additions & 0 deletions bin/rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'rspec' is installed as part of a gem, and
# this file is here to facilitate running it.
#

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

bundle_binstub = File.expand_path("bundle", __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rspec-core", "rspec")
27 changes: 27 additions & 0 deletions spec/packer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -589,4 +589,31 @@ def to_msgpack_ext
GC.stress = stress
end
end

it "doesn't crash when using recursive packers concurrently" do
hash_with_indifferent_access = Class.new(Hash)
msgpack = MessagePack::Factory.new
msgpack.register_type(
0x02,
hash_with_indifferent_access,
packer: ->(value, packer) do
packer.write("a".b * 600_0000) # Over MSGPACK_BUFFER_STRING_WRITE_REFERENCE_DEFAULT
packer.write(value.to_h)
GC.start(full_mark: true, immediate_mark: true, immediate_sweep: true)
end,
unpacker: ->(unpacker) { hash_with_indifferent_access.new(unpacker.read) },
recursive: true
)

packer = msgpack.packer

top_hash = hash = hash_with_indifferent_access.new
10.times do
hash["a"] = new_hash = hash_with_indifferent_access.new
hash = new_hash
end
packer.write(top_hash)
packer.write(top_hash)
packer.full_pack
end
end

0 comments on commit e48df01

Please sign in to comment.