Skip to content

Commit

Permalink
Merge pull request #2243 from herwinw/marshal_string_encoding
Browse files Browse the repository at this point in the history
Fixes for Marshal.load and Marshal.dump related to binary strings
  • Loading branch information
herwinw committed Sep 29, 2024
2 parents ed151a7 + 0135e40 commit 1668e40
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 32 deletions.
12 changes: 3 additions & 9 deletions spec/core/marshal/dump_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,21 +319,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 @@ -565,10 +565,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

0 comments on commit 1668e40

Please sign in to comment.