1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
require 'test/unit'
require_relative 'marshaltestlib'
class TestMarshal < Test::Unit::TestCase
include MarshalTestLib
def encode(o)
Marshal.dump(o)
end
def decode(s)
Marshal.load(s)
end
def fact(n)
return 1 if n == 0
f = 1
while n>0
f *= n
n -= 1
end
return f
end
def test_marshal
x = [1, 2, 3, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
assert_equal x, Marshal.load(Marshal.dump(x))
[[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z|
obj = (x.to_f + y.to_f / z.to_f) * Math.exp(w.to_f / (x.to_f + y.to_f / z.to_f))
assert_equal obj, Marshal.load(Marshal.dump(obj))
}
end
StrClone = String.clone
def test_marshal_cloned_class
assert_instance_of(StrClone, Marshal.load(Marshal.dump(StrClone.new("abc"))))
end
def test_inconsistent_struct
TestMarshal.const_set :StructOrNot, Struct.new(:a)
s = Marshal.dump(StructOrNot.new(1))
TestMarshal.instance_eval { remove_const :StructOrNot }
TestMarshal.const_set :StructOrNot, Class.new
assert_raise(TypeError, "[ruby-dev:31709]") { Marshal.load(s) }
end
def test_struct_invalid_members
TestMarshal.const_set :StructInvalidMembers, Struct.new(:a)
Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo")
assert_raise(TypeError, "[ruby-dev:31759]") {
TestMarshal::StructInvalidMembers.members
}
end
class C
def initialize(str)
@str = str
end
attr_reader :str
def _dump(limit)
@str
end
def self._load(s)
new(s)
end
end
def test_too_long_string
data = Marshal.dump(C.new("a".force_encoding("ascii-8bit")))
data[-2, 1] = "\003\377\377\377"
e = assert_raise(ArgumentError, "[ruby-dev:32054]") {
Marshal.load(data)
}
assert_equal("marshal data too short", e.message)
end
def test_userdef_encoding
s1 = "\xa4\xa4".force_encoding("euc-jp")
o1 = C.new(s1)
m = Marshal.dump(o1)
o2 = Marshal.load(m)
s2 = o2.str
assert_equal(s1, s2)
end
def test_pipe
o1 = C.new("a" * 10000)
r, w = IO.pipe
Marshal.dump(o1, w)
o2 = Marshal.load(r)
assert_equal(o1.str, o2.str)
r, w = IO.pipe
Marshal.dump(o1, w, 2)
o2 = Marshal.load(r)
assert_equal(o1.str, o2.str)
assert_raise(TypeError) { Marshal.dump("foo", Object.new) }
assert_raise(TypeError) { Marshal.load(Object.new) }
end
def test_limit
assert_equal([[[]]], Marshal.load(Marshal.dump([[[]]], 3)))
assert_raise(ArgumentError) { Marshal.dump([[[]]], 2) }
end
def test_userdef_invalid
o = C.new(nil)
assert_raise(TypeError) { Marshal.dump(o) }
end
def test_class
o = class << Object.new; self; end
assert_raise(TypeError) { Marshal.dump(o) }
assert_equal(Object, Marshal.load(Marshal.dump(Object)))
assert_equal(Enumerable, Marshal.load(Marshal.dump(Enumerable)))
end
class C2
def initialize(ary)
@ary = ary
end
def _dump(s)
@ary.clear
"foo"
end
end
def test_modify_array_during_dump
a = []
o = C2.new(a)
a << o << nil
assert_raise(RuntimeError) { Marshal.dump(a) }
end
def test_change_class_name
eval("class C3; def _dump(s); 'foo'; end; end")
m = Marshal.dump(C3.new)
assert_raise(TypeError) { Marshal.load(m) }
eval("C3 = nil")
assert_raise(TypeError) { Marshal.load(m) }
end
def test_change_struct
eval("C3 = Struct.new(:foo, :bar)")
m = Marshal.dump(C3.new("FOO", "BAR"))
eval("C3 = Struct.new(:foo)")
assert_raise(TypeError) { Marshal.load(m) }
eval("C3 = Struct.new(:foo, :baz)")
assert_raise(TypeError) { Marshal.load(m) }
end
end
|