diff options
Diffstat (limited to 'spec/ruby/core/marshal/shared/load.rb')
-rw-r--r-- | spec/ruby/core/marshal/shared/load.rb | 96 |
1 files changed, 78 insertions, 18 deletions
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb index bc094f28f2..f599042529 100644 --- a/spec/ruby/core/marshal/shared/load.rb +++ b/spec/ruby/core/marshal/shared/load.rb @@ -183,7 +183,7 @@ describe :marshal_load, shared: true do describe "when called with a proc" do it "call the proc with frozen objects" do arr = [] - s = 'hi' + s = +'hi' s.instance_variable_set(:@foo, 5) st = Struct.new("Brittle", :a).new st.instance_variable_set(:@clue, 'none') @@ -268,7 +268,7 @@ describe :marshal_load, shared: true do it "loads an Array with proc" do arr = [] - s = 'hi' + s = +'hi' s.instance_variable_set(:@foo, 5) st = Struct.new("Brittle", :a).new st.instance_variable_set(:@clue, 'none') @@ -413,13 +413,13 @@ describe :marshal_load, shared: true do end it "raises a TypeError with bad Marshal version" do - marshal_data = '\xff\xff' + marshal_data = +'\xff\xff' marshal_data[0] = (Marshal::MAJOR_VERSION).chr marshal_data[1] = (Marshal::MINOR_VERSION + 1).chr -> { Marshal.send(@method, marshal_data) }.should raise_error(TypeError) - marshal_data = '\xff\xff' + marshal_data = +'\xff\xff' marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr marshal_data[1] = (Marshal::MINOR_VERSION).chr @@ -470,7 +470,7 @@ describe :marshal_load, shared: true do end it "loads an array having ivar" do - s = 'well' + s = +'well' s.instance_variable_set(:@foo, 10) obj = ['5', s, 'hi'].extend(Meths, MethsMore) obj.instance_variable_set(:@mix, s) @@ -516,7 +516,7 @@ describe :marshal_load, shared: true do end it "preserves hash ivars when hash contains a string having ivar" do - s = 'string' + s = +'string' s.instance_variable_set :@string_ivar, 'string ivar' h = { key: s } h.instance_variable_set :@hash_ivar, 'hash ivar' @@ -600,7 +600,7 @@ describe :marshal_load, shared: true do end it "loads a binary encoded Symbol" do - s = "\u2192".force_encoding("binary").to_sym + s = "\u2192".dup.force_encoding("binary").to_sym sym = Marshal.send(@method, "\x04\b:\b\xE2\x86\x92") sym.should == s sym.encoding.should == Encoding::BINARY @@ -614,8 +614,8 @@ describe :marshal_load, shared: true do value = Marshal.send(@method, dump) value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8] expected = [ - "€a".force_encoding(Encoding::UTF_8).to_sym, - "€b".force_encoding(Encoding::UTF_8).to_sym + "€a".dup.force_encoding(Encoding::UTF_8).to_sym, + "€b".dup.force_encoding(Encoding::UTF_8).to_sym ] value.should == expected @@ -623,11 +623,19 @@ describe :marshal_load, shared: true do value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8] value.should == [*expected, expected[0]] end + + it "raises ArgumentError when end of byte sequence reached before symbol characters end" do + Marshal.dump(:hello).should == "\x04\b:\nhello" + + -> { + Marshal.send(@method, "\x04\b:\nhel") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for a String" do it "loads a string having ivar with ref to self" do - obj = 'hi' + obj = +'hi' obj.instance_variable_set(:@self, obj) Marshal.send(@method, "\004\bI\"\ahi\006:\n@self@\000").should == obj end @@ -655,7 +663,7 @@ describe :marshal_load, shared: true do end it "loads a US-ASCII String" do - str = "abc".force_encoding("us-ascii") + str = "abc".dup.force_encoding("us-ascii") data = "\x04\bI\"\babc\x06:\x06EF" result = Marshal.send(@method, data) result.should == str @@ -663,7 +671,7 @@ describe :marshal_load, shared: true do end it "loads a UTF-8 String" do - str = "\x6d\xc3\xb6\x68\x72\x65".force_encoding("utf-8") + str = "\x6d\xc3\xb6\x68\x72\x65".dup.force_encoding("utf-8") data = "\x04\bI\"\vm\xC3\xB6hre\x06:\x06ET" result = Marshal.send(@method, data) result.should == str @@ -671,7 +679,7 @@ describe :marshal_load, shared: true do end it "loads a String in another encoding" do - str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".force_encoding("utf-16le") + str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".dup.force_encoding("utf-16le") data = "\x04\bI\"\x0Fm\x00\xF6\x00h\x00r\x00e\x00\x06:\rencoding\"\rUTF-16LE" result = Marshal.send(@method, data) result.should == str @@ -679,12 +687,20 @@ describe :marshal_load, shared: true do end it "loads a String as BINARY if no encoding is specified at the end" do - str = "\xC3\xB8".force_encoding("BINARY") - data = "\x04\b\"\a\xC3\xB8".force_encoding("UTF-8") + str = "\xC3\xB8".dup.force_encoding("BINARY") + data = "\x04\b\"\a\xC3\xB8".dup.force_encoding("UTF-8") 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 + Marshal.dump("hello").should == "\x04\b\"\nhello" + + -> { + Marshal.send(@method, "\x04\b\"\nhel") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for a Struct" do @@ -807,7 +823,7 @@ describe :marshal_load, shared: true do end it "loads an Object with a non-US-ASCII instance variable" do - ivar = "@é".force_encoding(Encoding::UTF_8).to_sym + ivar = "@é".dup.force_encoding(Encoding::UTF_8).to_sym obj = Marshal.send(@method, "\x04\bo:\vObject\x06I:\b@\xC3\xA9\x06:\x06ETi\x06") obj.instance_variables.should == [ivar] obj.instance_variables[0].encoding.should == Encoding::UTF_8 @@ -819,6 +835,14 @@ describe :marshal_load, shared: true do Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd") end.should raise_error(ArgumentError) end + + it "raises ArgumentError when end of byte sequence reached before class name end" do + Marshal.dump(Object.new).should == "\x04\bo:\vObject\x00" + + -> { + Marshal.send(@method, "\x04\bo:\vObj") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for an object responding to #marshal_dump and #marshal_load" do @@ -908,6 +932,14 @@ describe :marshal_load, shared: true do regexp.encoding.should == Encoding::UTF_32LE regexp.source.should == "a".encode("utf-32le") end + + it "raises ArgumentError when end of byte sequence reached before source string end" do + Marshal.dump(/hello world/).should == "\x04\bI/\x10hello world\x00\x06:\x06EF" + + -> { + Marshal.send(@method, "\x04\bI/\x10hel") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for a Float" do @@ -929,6 +961,14 @@ describe :marshal_load, shared: true do obj = 1.1867345e+22 Marshal.send(@method, "\004\bf\0361.1867344999999999e+22\000\344@").should == obj end + + it "raises ArgumentError when end of byte sequence reached before float string representation end" do + Marshal.dump(1.3).should == "\x04\bf\b1.3" + + -> { + Marshal.send(@method, "\004\bf\v1") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for an Integer" do @@ -994,13 +1034,17 @@ describe :marshal_load, shared: true do describe "for a Rational" do it "loads" do - Marshal.send(@method, Marshal.dump(Rational(1, 3))).should == Rational(1, 3) + r = Marshal.send(@method, Marshal.dump(Rational(1, 3))) + r.should == Rational(1, 3) + r.should.frozen? end end describe "for a Complex" do it "loads" do - Marshal.send(@method, Marshal.dump(Complex(4, 3))).should == Complex(4, 3) + c = Marshal.send(@method, Marshal.dump(Complex(4, 3))) + c.should == Complex(4, 3) + c.should.frozen? end end @@ -1114,6 +1158,14 @@ describe :marshal_load, shared: true do it "raises ArgumentError if given a nonexistent class" do -> { Marshal.send(@method, "\x04\bc\vStrung") }.should raise_error(ArgumentError) end + + it "raises ArgumentError when end of byte sequence reached before class name end" do + Marshal.dump(String).should == "\x04\bc\vString" + + -> { + Marshal.send(@method, "\x04\bc\vStr") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for a Module" do @@ -1128,6 +1180,14 @@ describe :marshal_load, shared: true do it "loads an old module" do Marshal.send(@method, "\x04\bM\vKernel").should == Kernel end + + it "raises ArgumentError when end of byte sequence reached before module name end" do + Marshal.dump(Kernel).should == "\x04\bm\vKernel" + + -> { + Marshal.send(@method, "\x04\bm\vKer") + }.should raise_error(ArgumentError, "marshal data too short") + end end describe "for a wrapped C pointer" do |