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

Fixes for Marshal.load and Marshal.dump related to binary strings #2243

Merged
merged 2 commits into from
Sep 29, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions spec/core/marshal/dump_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -321,21 +321,15 @@ def _dump(level)

describe "with a String" do
it "dumps a blank String" do
NATFIXME 'dumps a blank String', exception: SpecFailedException do
Marshal.dump("".dup.force_encoding("binary")).should == "\004\b\"\000"
end
Marshal.dump("".dup.force_encoding("binary")).should == "\004\b\"\000"
end

it "dumps a short String" do
NATFIXME 'dumps a short String', exception: SpecFailedException do
Marshal.dump("short".dup.force_encoding("binary")).should == "\004\b\"\012short"
end
Marshal.dump("short".dup.force_encoding("binary")).should == "\004\b\"\012short"
end

it "dumps a long String" do
NATFIXME 'dumps a long String', exception: SpecFailedException do
Marshal.dump(("big" * 100).force_encoding("binary")).should == "\004\b\"\002,\001#{"big" * 100}"
end
Marshal.dump(("big" * 100).force_encoding("binary")).should == "\004\b\"\002,\001#{"big" * 100}"
end

it "dumps a String extended with a Module" do
Expand Down
28 changes: 10 additions & 18 deletions spec/core/marshal/shared/load.rb
Original file line number Diff line number Diff line change
Expand Up @@ -484,9 +484,7 @@
arr = ArraySubPush.new
arr[0] = '1'
arr_dump = Marshal.dump(arr)
NATFIXME 'loads subclasses of Array with overridden << and push correctly', exception: ArgumentError, message: 'marshal data too short' do
Marshal.send(@method, arr_dump).should == arr
end
Marshal.send(@method, arr_dump).should == arr
end

it "raises a TypeError with bad Marshal version" do
Expand Down Expand Up @@ -612,7 +610,7 @@
h = { key: s }
h.instance_variable_set :@hash_ivar, 'hash ivar'

NATFIXME 'preserves hash ivars when hash contains a string having ivar', exception: ArgumentError, message: 'marshal data too short' do
NATFIXME 'preserves hash ivars when hash contains a string having ivar', exception: SpecFailedException do
unmarshalled = Marshal.send(@method, Marshal.dump(h))
unmarshalled.instance_variable_get(:@hash_ivar).should == 'hash ivar'
unmarshalled[:key].instance_variable_get(:@string_ivar).should == 'string ivar'
Expand Down Expand Up @@ -746,9 +744,7 @@
it "loads a string through StringIO stream" do
require 'stringio'
obj = "This is a string which should be unmarshalled through StringIO stream!"
NATFIXME 'loads a string through StringIO stream', exception: ArgumentError, message: 'marshal data too short' do
Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj
end
Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj
end

it "sets binmode if it is loading through StringIO stream" do
Expand Down Expand Up @@ -802,21 +798,17 @@ def io.binmode; raise "binmode"; end
it "loads a String as BINARY if no encoding is specified at the end" do
str = "\xC3\xB8".dup.force_encoding("BINARY")
data = "\x04\b\"\a\xC3\xB8".dup.force_encoding("UTF-8")
NATFIXME 'loads a String as BINARY if no encoding is specified at the end', exception: ArgumentError, message: 'marshal data too short' do
result = Marshal.send(@method, data)
result.encoding.should == Encoding::BINARY
result.should == str
end
result = Marshal.send(@method, data)
result.encoding.should == Encoding::BINARY
result.should == str
end

it "raises ArgumentError when end of byte sequence reached before string characters end" do
NATFIXME 'raises ArgumentError when end of byte sequence reached before string characters end', exception: SpecFailedException do
Marshal.dump("hello").should == "\x04\b\"\nhello"
Marshal.dump("hello").should == "\x04\b\"\nhello"

-> {
Marshal.send(@method, "\x04\b\"\nhel")
}.should raise_error(ArgumentError, "marshal data too short")
end
-> {
Marshal.send(@method, "\x04\b\"\nhel")
}.should raise_error(ArgumentError, "marshal data too short")
end
end

Expand Down
10 changes: 5 additions & 5 deletions src/marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ def write_integer(value)
end

def write_string(value)
write_char('I')
write_char('I') if value.encoding != Encoding::ASCII_8BIT
write_char('"')
write_string_bytes(value)
write_encoding_bytes(value)
write_encoding_bytes(value) if value.encoding != Encoding::ASCII_8BIT
end

def write_symbol(value)
Expand Down Expand Up @@ -564,10 +564,10 @@ def read_byte
end

def read_bytes(integer)
if @source.length - @offset >= integer
string = @source.slice(@offset, integer)
if @source.bytesize - @offset >= integer
string = @source.byteslice(@offset, integer)
@offset += integer
string
string.b
else
raise ArgumentError, 'marshal data too short'
end
Expand Down
Loading