Permalink
Browse files

Fix CompiledFile unmarshalling

This Ruby unmarshaller is not currently exercised by normal code
loading: it uses marshal.cpp instead.

Fixes #1706.
  • Loading branch information...
jfirebaugh committed May 7, 2012
1 parent 3026bd1 commit a6fb7b6c6c4254c841ca0e109034b3c7fc4507e4
Showing with 94 additions and 35 deletions.
  1. +15 −35 lib/compiler/compiled_file.rb
  2. +79 −0 spec/compiler/compiled_file/marshal/unmarshal_spec.rb
@@ -99,15 +99,15 @@ def unmarshal(stream)
def unmarshal_data
kind = next_type
case kind
- when ?t
+ when 116 # ?t
return true
- when ?f
+ when 102 # ?f
return false
- when ?n
+ when 110 # ?n
return nil
- when ?I
+ when 73 # ?I
return next_string.to_i(16)
- when ?d
+ when 100 # ?d
str = next_string.chop
# handle the special NaN, Infinity and -Infinity differently
@@ -133,24 +133,21 @@ def unmarshal_data
raise TypeError, "Invalid Float format: #{str}"
end
end
- when ?s
+ when 115 # ?s
enc = unmarshal_data
count = next_string.to_i
str = next_bytes count
str.force_encoding enc if enc and defined?(Encoding)
- discard # remove the \n
return str
- when ?x
+ when 120 # ?x
count = next_string.to_i
str = next_bytes count
- discard # remove the \n
return str.to_sym
- when ?c
+ when 99 # ?c
count = next_string.to_i
str = next_bytes count
- discard
return str.split("::").inject(Object) { |a,n| a.const_get(n) }
- when ?p
+ when 112 # ?p
count = next_string.to_i
obj = Tuple.new(count)
i = 0
@@ -159,7 +156,7 @@ def unmarshal_data
i += 1
end
return obj
- when ?i
+ when 105 # ?i
count = next_string.to_i
seq = InstructionSequence.new(count)
i = 0
@@ -168,11 +165,11 @@ def unmarshal_data
i += 1
end
return seq
- when ?E
+ when 69 # ?E
count = next_string.to_i
name = next_bytes count
return Encoding.find(name) if defined?(Encoding)
- when ?M
+ when 77 # ?M
version = next_string.to_i
if version != 1
raise "Unknown CompiledMethod version #{version}"
@@ -229,33 +226,16 @@ def next_string
private :next_string
##
- # Returns the next _count_ bytes in _@data_.
+ # Returns the next _count_ bytes in _@data_, skipping the
+ # trailing "\n" character.
def next_bytes(count)
str = String.from_bytearray @data, @start, count
- @start += count
+ @start += count + 1
str
end
private :next_bytes
- ##
- # Returns the next byte in _@data_.
- def next_byte
- byte = @data[@start]
- @start += 1
- byte
- end
-
- private :next_byte
-
- ##
- # Moves the next read pointer ahead by one character.
- def discard
- @start += 1
- end
-
- private :discard
-
##
# For object +val+, return a String represetation.
@@ -0,0 +1,79 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "Rubinius::CompiledFile::Marshal#unmarshal" do
+ it "unmarshals true" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("t\n").should == true
+ end
+
+ it "unmarshals false" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("f\n").should == false
+ end
+
+ it "unmarshals nil" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("n\n").should == nil
+ end
+
+ it "unmarshals an Integer" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("I\nCAFEF00D").should == 0xCAFEF00D
+ end
+
+ it "unmarshals a Float" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\n +0.785000000000000031086244689504383131861686706542968750 2\n").should == 3.14
+ end
+
+ it "unmarshals +infinity" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\nInfinity\n").should be_positive_infinity
+ end
+
+ it "unmarshals -infinity" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\n-Infinity\n").should be_negative_infinity
+ end
+
+ it "unmarshals NaN" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\nNaN\n").should be_nan
+ end
+
+ it "unmarshals a Symbol" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("x\n12\nHello world!\n").should == :"Hello world!"
+ end
+
+ it "unmarshals a constant" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("c\n22\nRubinius::CompiledFile\n").should == Rubinius::CompiledFile
+ end
+
+ ruby_version_is ""..."1.9" do
+ it "unmarshals a String" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("s\nE\n0\n\n12\nHello world!\n").should == "Hello world!"
+ end
+
+ it "returns nil when unmarshalling an encoding" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("E\n5\nUTF-8\n13\n").should be_nil
+ end
+ end
+
+ ruby_version_is "1.9" do
+ it "unmarshals a String" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ str = marshal.unmarshal("s\nE\n5\nUTF-8\n12\nHello world!\n")
+ str.should == "Hello world!"
+ str.encoding.should == Encoding::UTF_8
+ end
+
+ it "unmarshals an encoding" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("E\n5\nUTF-8\n13\n").should == Encoding::UTF_8
+ end
+ end
+end

0 comments on commit a6fb7b6

Please sign in to comment.