mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Marshal.load: do not call the proc until strings have their encoding
Ref: https://bugs.ruby-lang.org/issues/18141
This commit is contained in:
		
							parent
							
								
									a0357acf19
								
							
						
					
					
						commit
						89242279e6
					
				
				
				Notes:
				
					git
				
				2021-09-15 08:00:43 +09:00 
				
			
			
			
		
		
					 3 changed files with 61 additions and 19 deletions
				
			
		|  | @ -1690,6 +1690,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) | |||
| 
 | ||||
| 	    v = r_object0(arg, &ivar, extmod); | ||||
| 	    if (ivar) r_ivar(v, NULL, arg); | ||||
| 	    if (RB_TYPE_P(v, T_STRING)) { | ||||
| 	        v = r_leave(v, arg); | ||||
| 	    } | ||||
| 	} | ||||
| 	break; | ||||
| 
 | ||||
|  | @ -1819,7 +1822,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) | |||
| 
 | ||||
|       case TYPE_STRING: | ||||
| 	v = r_entry(r_string(arg), arg); | ||||
| 	if (!ivp) { | ||||
| 	    v = r_leave(v, arg); | ||||
| 	} | ||||
| 	break; | ||||
| 
 | ||||
|       case TYPE_REGEXP: | ||||
|  |  | |||
|  | @ -20,6 +20,24 @@ describe :marshal_load, shared: true do | |||
|   end | ||||
| 
 | ||||
|   describe "when called with a proc" do | ||||
|     ruby_bug "#18141", ""..."3.1" do | ||||
|       it "call the proc with fully initialized strings" do | ||||
|         utf8_string = "foo".encode(Encoding::UTF_8) | ||||
|         Marshal.send(@method, Marshal.dump(utf8_string), proc { |arg| | ||||
|           if arg.is_a?(String) | ||||
|             arg.should == utf8_string | ||||
|             arg.encoding.should == Encoding::UTF_8 | ||||
|           end | ||||
|           arg | ||||
|         }) | ||||
|       end | ||||
| 
 | ||||
|       it "no longer mutate the object after it was passed to the proc" do | ||||
|         string = Marshal.load(Marshal.dump("foo"), :freeze.to_proc) | ||||
|         string.should.frozen? | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     it "returns the value of the proc" do | ||||
|       Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should ==  [3,4] | ||||
|     end | ||||
|  | @ -35,6 +53,7 @@ describe :marshal_load, shared: true do | |||
|       ret.size.should == 3 | ||||
|     end | ||||
| 
 | ||||
|     ruby_bug "#18141", ""..."3.1" do | ||||
|       it "loads an Array with proc" do | ||||
|         arr = [] | ||||
|         s = 'hi' | ||||
|  | @ -52,12 +71,13 @@ describe :marshal_load, shared: true do | |||
| 
 | ||||
|         Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc) | ||||
| 
 | ||||
|       arr.should == ["hi", false, 5, 10, "hi", "hi", 0.0, st, "none", false, | ||||
|                      :b, :c, a, 2, ["hi", 10, "hi", "hi", st, [:a, :b, :c]], "ant", false] | ||||
|         arr.should == [false, 5, "hi", 10, "hi", "hi", 0.0, st, false, "none", | ||||
|                        :b, :c, a, 2, ["hi", 10, "hi", "hi", st, [:a, :b, :c]], false, "ant"] | ||||
| 
 | ||||
|         Struct.send(:remove_const, :Brittle) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "when called with nil for the proc argument" do | ||||
|     it "behaves as if no proc argument was passed" do | ||||
|  |  | |||
|  | @ -676,6 +676,23 @@ class TestMarshal < Test::Unit::TestCase | |||
|     assert_equal(['X', 'X'], Marshal.load(Marshal.dump(obj), ->(v) { v == str ? v.upcase : v })) | ||||
|   end | ||||
| 
 | ||||
|   def test_marshal_proc_string_encoding | ||||
|     string = "foo" | ||||
|     payload = Marshal.dump(string) | ||||
|     Marshal.load(payload, ->(v) { | ||||
|       if v.is_a?(String) | ||||
|         assert_equal(string, v) | ||||
|         assert_equal(string.encoding, v.encoding) | ||||
|       end | ||||
|       v | ||||
|     }) | ||||
|   end | ||||
| 
 | ||||
|   def test_marshal_proc_freeze | ||||
|     object = { foo: [42, "bar"] } | ||||
|     assert_equal object, Marshal.load(Marshal.dump(object), :freeze.to_proc) | ||||
|   end | ||||
| 
 | ||||
|   def test_marshal_load_extended_class_crash | ||||
|     assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") | ||||
|     begin; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jean Boussier
						Jean Boussier