thrift 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +93 -33
- data/benchmark/benchmark.rb +2 -1
- data/benchmark/client.rb +1 -0
- data/benchmark/server.rb +1 -0
- data/benchmark/thin_server.rb +1 -0
- data/ext/binary_protocol_accelerated.c +78 -23
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +59 -31
- data/ext/extconf.rb +8 -0
- data/ext/memory_buffer.c +37 -0
- data/ext/struct.c +14 -14
- data/ext/thrift_native.c +1 -0
- data/lib/thrift/bytes.rb +4 -1
- data/lib/thrift/client.rb +1 -12
- data/lib/thrift/exceptions.rb +1 -0
- data/lib/thrift/multiplexed_processor.rb +14 -4
- data/lib/thrift/processor.rb +1 -0
- data/lib/thrift/protocol/base_protocol.rb +15 -6
- data/lib/thrift/protocol/binary_protocol.rb +41 -12
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +1 -0
- data/lib/thrift/protocol/compact_protocol.rb +15 -4
- data/lib/thrift/protocol/header_protocol.rb +1 -0
- data/lib/thrift/protocol/json_protocol.rb +18 -11
- data/lib/thrift/protocol/multiplexed_protocol.rb +1 -0
- data/lib/thrift/protocol/protocol_decorator.rb +1 -0
- data/lib/thrift/serializer/deserializer.rb +1 -0
- data/lib/thrift/serializer/serializer.rb +1 -0
- data/lib/thrift/server/base_server.rb +1 -0
- data/lib/thrift/server/mongrel_http_server.rb +1 -0
- data/lib/thrift/server/nonblocking_server.rb +28 -2
- data/lib/thrift/server/simple_server.rb +9 -1
- data/lib/thrift/server/thin_http_server.rb +1 -0
- data/lib/thrift/server/thread_pool_server.rb +1 -0
- data/lib/thrift/server/threaded_server.rb +9 -1
- data/lib/thrift/struct.rb +1 -0
- data/lib/thrift/struct_union.rb +4 -9
- data/lib/thrift/thrift_native.rb +2 -1
- data/lib/thrift/transport/base_server_transport.rb +3 -0
- data/lib/thrift/transport/base_transport.rb +6 -2
- data/lib/thrift/transport/buffered_transport.rb +1 -0
- data/lib/thrift/transport/framed_transport.rb +1 -0
- data/lib/thrift/transport/header_transport.rb +47 -1
- data/lib/thrift/transport/http_client_transport.rb +1 -0
- data/lib/thrift/transport/io_stream_transport.rb +1 -0
- data/lib/thrift/transport/memory_buffer_transport.rb +7 -0
- data/lib/thrift/transport/server_socket.rb +6 -3
- data/lib/thrift/transport/socket.rb +68 -29
- data/lib/thrift/transport/ssl_server_socket.rb +3 -2
- data/lib/thrift/transport/ssl_socket.rb +43 -11
- data/lib/thrift/transport/unix_server_socket.rb +5 -1
- data/lib/thrift/transport/unix_socket.rb +1 -0
- data/lib/thrift/types.rb +1 -0
- data/lib/thrift/union.rb +1 -0
- data/lib/thrift/uuid.rb +1 -0
- data/lib/thrift.rb +1 -0
- data/spec/ThriftSpec.thrift +16 -0
- data/spec/base_protocol_spec.rb +20 -0
- data/spec/base_transport_spec.rb +42 -1
- data/spec/binary_protocol_accelerated_spec.rb +1 -0
- data/spec/binary_protocol_spec.rb +1 -0
- data/spec/binary_protocol_spec_shared.rb +79 -15
- data/spec/bytes_spec.rb +19 -1
- data/spec/client_spec.rb +1 -0
- data/spec/compact_protocol_spec.rb +99 -0
- data/spec/constants_demo_spec.rb +1 -0
- data/spec/exception_spec.rb +1 -0
- data/spec/flat_spec.rb +1 -0
- data/spec/header_protocol_spec.rb +1 -0
- data/spec/header_transport_spec.rb +45 -0
- data/spec/http_client_spec.rb +1 -0
- data/spec/json_protocol_spec.rb +26 -4
- data/spec/multiplexed_processor_spec.rb +75 -0
- data/spec/namespaced_spec.rb +1 -0
- data/spec/nonblocking_server_spec.rb +86 -18
- data/spec/processor_spec.rb +1 -0
- data/spec/recursion_depth_spec.rb +223 -0
- data/spec/serializer_spec.rb +1 -0
- data/spec/server_socket_spec.rb +37 -0
- data/spec/server_spec.rb +52 -0
- data/spec/socket_spec.rb +119 -12
- data/spec/socket_spec_shared.rb +1 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/ssl_server_socket_spec.rb +40 -0
- data/spec/ssl_socket_spec.rb +171 -10
- data/spec/struct_nested_containers_spec.rb +1 -0
- data/spec/struct_spec.rb +1 -0
- data/spec/support/header_protocol_helper.rb +2 -1
- data/spec/thin_http_server_spec.rb +1 -0
- data/spec/types_spec.rb +1 -0
- data/spec/union_spec.rb +1 -0
- data/spec/unix_socket_spec.rb +16 -0
- data/spec/uuid_validation_spec.rb +1 -0
- data/test/fuzz/Makefile +779 -0
- data/test/fuzz/Makefile.in +775 -0
- data/test/fuzz/fuzz_common.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_tracer.rb +1 -0
- metadata +12 -46
data/lib/thrift/union.rb
CHANGED
data/lib/thrift/uuid.rb
CHANGED
data/lib/thrift.rb
CHANGED
data/spec/ThriftSpec.thrift
CHANGED
|
@@ -185,3 +185,19 @@ struct NestedMapInMapKey {
|
|
|
185
185
|
struct NestedMapInMapValue {
|
|
186
186
|
2: map<byte, map<byte, byte>> value
|
|
187
187
|
}
|
|
188
|
+
|
|
189
|
+
# Recursive types for the struct/union/exception recursion-depth limit specs (THRIFT-6045).
|
|
190
|
+
struct RecTree {
|
|
191
|
+
1: list<RecTree> children
|
|
192
|
+
2: i16 item
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
union RecUnion {
|
|
196
|
+
1: list<RecUnion> children
|
|
197
|
+
2: i32 leaf
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
exception RecError {
|
|
201
|
+
1: list<RecError> children
|
|
202
|
+
2: i32 leaf
|
|
203
|
+
}
|
data/spec/base_protocol_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -209,6 +210,25 @@ describe 'BaseProtocol' do
|
|
|
209
210
|
expect(@prot).to receive(:read_list_end)
|
|
210
211
|
real_skip.call(Thrift::Types::LIST)
|
|
211
212
|
end
|
|
213
|
+
|
|
214
|
+
it "should raise DEPTH_LIMIT when max_depth is exhausted" do
|
|
215
|
+
expect { @prot.skip(Thrift::Types::STRUCT, 0) }.to raise_error(Thrift::ProtocolException) do |e|
|
|
216
|
+
expect(e.type).to eq(Thrift::ProtocolException::DEPTH_LIMIT)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "should skip at max_depth=1 without raising" do
|
|
221
|
+
expect(@prot).to receive(:read_bool).once
|
|
222
|
+
expect { @prot.skip(Thrift::Types::BOOL, 1) }.not_to raise_error
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should reject negative container sizes while skipping" do
|
|
226
|
+
expect(@prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, -1])
|
|
227
|
+
|
|
228
|
+
expect { @prot.skip(Thrift::Types::LIST) }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
229
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
212
232
|
end
|
|
213
233
|
|
|
214
234
|
describe Thrift::BaseProtocolFactory do
|
data/spec/base_transport_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -37,6 +38,25 @@ describe 'BaseTransport' do
|
|
|
37
38
|
expect(transport.read_all(40)).to eq("10 lettersfifteen lettersmore characters")
|
|
38
39
|
end
|
|
39
40
|
|
|
41
|
+
it "should coerce reads to binary encoding" do
|
|
42
|
+
transport = Thrift::BaseTransport.new
|
|
43
|
+
expect(transport).to receive(:read).with(3).and_return(+'abc')
|
|
44
|
+
|
|
45
|
+
buf = transport.read_all(3)
|
|
46
|
+
|
|
47
|
+
expect(buf).to eq('abc')
|
|
48
|
+
expect(buf.encoding).to eq(Encoding::BINARY)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should reject negative read sizes" do
|
|
52
|
+
transport = Thrift::BaseTransport.new
|
|
53
|
+
expect(transport).not_to receive(:read)
|
|
54
|
+
|
|
55
|
+
expect { transport.read_all(-1) }.to raise_error(Thrift::TransportException, "Negative size") do |e|
|
|
56
|
+
expect(e.type).to eq(Thrift::TransportException::NEGATIVE_SIZE)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
40
60
|
it "should stub out the rest of the methods" do
|
|
41
61
|
# can't test for stubbiness, so just make sure they're defined
|
|
42
62
|
[:open?, :open, :close, :read, :write, :flush].each do |sym|
|
|
@@ -286,7 +306,7 @@ describe 'BaseTransport' do
|
|
|
286
306
|
end
|
|
287
307
|
|
|
288
308
|
it "should accept a buffer on input and use it directly" do
|
|
289
|
-
s = "this is a test"
|
|
309
|
+
s = +"this is a test"
|
|
290
310
|
@buffer = Thrift::MemoryBufferTransport.new(s)
|
|
291
311
|
expect(@buffer.read(4)).to eq("this")
|
|
292
312
|
s.slice!(-4..-1)
|
|
@@ -338,6 +358,21 @@ describe 'BaseTransport' do
|
|
|
338
358
|
expect(@buffer.read(@buffer.available)).to eq("foo bar")
|
|
339
359
|
end
|
|
340
360
|
|
|
361
|
+
it "should force mutable write buffers into binary in place" do
|
|
362
|
+
s = "abc \u20AC".encode("UTF-8")
|
|
363
|
+
@buffer.write(s)
|
|
364
|
+
expect(s.encoding).to eq(Encoding::BINARY)
|
|
365
|
+
expect(@buffer.read(@buffer.available)).to eq("abc \u20AC".encode("UTF-8").b)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "should not mutate frozen write buffers while forcing binary encoding" do
|
|
369
|
+
s = "abc \u20AC".encode("UTF-8").freeze
|
|
370
|
+
@buffer.write(s)
|
|
371
|
+
expect(s.encoding).to eq(Encoding::UTF_8)
|
|
372
|
+
expect(s).to be_frozen
|
|
373
|
+
expect(@buffer.read(@buffer.available)).to eq("abc \u20AC".encode("UTF-8").b)
|
|
374
|
+
end
|
|
375
|
+
|
|
341
376
|
it "should throw an EOFError when there isn't enough data in the buffer" do
|
|
342
377
|
@buffer.reset_buffer("")
|
|
343
378
|
expect{ @buffer.read(1) }.to raise_error(EOFError)
|
|
@@ -345,6 +380,12 @@ describe 'BaseTransport' do
|
|
|
345
380
|
@buffer.reset_buffer("1234")
|
|
346
381
|
expect{ @buffer.read(5) }.to raise_error(EOFError)
|
|
347
382
|
end
|
|
383
|
+
|
|
384
|
+
it "should reject negative read_all sizes" do
|
|
385
|
+
expect { @buffer.read_all(-1) }.to raise_error(Thrift::TransportException, "Negative size") do |e|
|
|
386
|
+
expect(e.type).to eq(Thrift::TransportException::NEGATIVE_SIZE)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
348
389
|
end
|
|
349
390
|
|
|
350
391
|
describe Thrift::IOStreamTransport do
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -109,15 +110,15 @@ shared_examples_for 'a binary protocol' do
|
|
|
109
110
|
end
|
|
110
111
|
end
|
|
111
112
|
|
|
112
|
-
it "should
|
|
113
|
-
|
|
114
|
-
@prot.write_byte(i)
|
|
115
|
-
expect(@trans.read(1)).to eq([i].pack('c'))
|
|
113
|
+
it "should reject bytes outside the signed byte range" do
|
|
114
|
+
[-129, 128, 255, 2**65].each do |i|
|
|
115
|
+
expect { @prot.write_byte(i) }.to raise_error(RangeError)
|
|
116
116
|
end
|
|
117
|
+
expect(@trans.available).to eq(0)
|
|
117
118
|
end
|
|
118
119
|
|
|
119
|
-
it "
|
|
120
|
-
expect { @prot.write_byte(
|
|
120
|
+
it "should reject non-integer bytes" do
|
|
121
|
+
expect { @prot.write_byte(1.5) }.to raise_error(TypeError)
|
|
121
122
|
end
|
|
122
123
|
|
|
123
124
|
it "should error gracefully when trying to write a nil byte" do
|
|
@@ -130,13 +131,19 @@ shared_examples_for 'a binary protocol' do
|
|
|
130
131
|
[-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i|
|
|
131
132
|
@prot.write_i16(i)
|
|
132
133
|
end
|
|
133
|
-
# and try something out of signed range, it should clip
|
|
134
|
-
@prot.write_i16(2**15 + 5)
|
|
135
134
|
|
|
136
|
-
expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377
|
|
135
|
+
expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377")
|
|
136
|
+
end
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
it "should reject i16 values outside the signed i16 range" do
|
|
139
|
+
[-2**15 - 1, 2**15, 2**65].each do |i|
|
|
140
|
+
expect { @prot.write_i16(i) }.to raise_error(RangeError)
|
|
141
|
+
end
|
|
142
|
+
expect(@trans.available).to eq(0)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should reject non-integer i16 values" do
|
|
146
|
+
expect { @prot.write_i16(1.5) }.to raise_error(TypeError)
|
|
140
147
|
end
|
|
141
148
|
|
|
142
149
|
it "should error gracefully when trying to write a nil i16" do
|
|
@@ -149,13 +156,16 @@ shared_examples_for 'a binary protocol' do
|
|
|
149
156
|
[-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i|
|
|
150
157
|
@prot.write_i32(i)
|
|
151
158
|
end
|
|
152
|
-
# try something out of signed range, it should clip
|
|
153
159
|
expect(@trans.read(@trans.available)).to eq("\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377")
|
|
154
|
-
[2 ** 31
|
|
160
|
+
[-2 ** 31 - 1, 2 ** 31, 2 ** 65 + 5].each do |i|
|
|
155
161
|
expect { @prot.write_i32(i) }.to raise_error(RangeError)
|
|
156
162
|
end
|
|
157
163
|
end
|
|
158
164
|
|
|
165
|
+
it "should reject non-integer i32 values" do
|
|
166
|
+
expect { @prot.write_i32(1.5) }.to raise_error(TypeError)
|
|
167
|
+
end
|
|
168
|
+
|
|
159
169
|
it "should error gracefully when trying to write a nil i32" do
|
|
160
170
|
expect { @prot.write_i32(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
|
|
161
171
|
end
|
|
@@ -166,7 +176,6 @@ shared_examples_for 'a binary protocol' do
|
|
|
166
176
|
[-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i|
|
|
167
177
|
@prot.write_i64(i)
|
|
168
178
|
end
|
|
169
|
-
# try something out of signed range, it should clip
|
|
170
179
|
expect(@trans.read(@trans.available)).to eq(["\200\000\000\000\000\000\000\000",
|
|
171
180
|
"\377\377\364\303\035\244+]",
|
|
172
181
|
"\377\377\377\377\376\231:\341",
|
|
@@ -176,13 +185,30 @@ shared_examples_for 'a binary protocol' do
|
|
|
176
185
|
"\000\000\000\000\000#\340\204",
|
|
177
186
|
"\000\000\000\002\340\311~\365",
|
|
178
187
|
"\177\377\377\377\377\377\377\377"].join(""))
|
|
179
|
-
|
|
188
|
+
[-2 ** 63 - 1, 2 ** 63, 2 ** 65 + 5].each do |i|
|
|
189
|
+
expect { @prot.write_i64(i) }.to raise_error(RangeError)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "should reject non-integer i64 values" do
|
|
194
|
+
expect { @prot.write_i64(1.5) }.to raise_error(TypeError)
|
|
180
195
|
end
|
|
181
196
|
|
|
182
197
|
it "should error gracefully when trying to write a nil i64" do
|
|
183
198
|
expect { @prot.write_i64(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
|
|
184
199
|
end
|
|
185
200
|
|
|
201
|
+
it "should reject out-of-range field ids" do
|
|
202
|
+
expect { @prot.write_field_begin('foo', Thrift::Types::DOUBLE, -2**15 - 1) }.to raise_error(RangeError)
|
|
203
|
+
expect { @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 2**15) }.to raise_error(RangeError)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "should reject out-of-range container sizes" do
|
|
207
|
+
expect { @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, -1) }.to raise_error(RangeError)
|
|
208
|
+
expect { @prot.write_list_begin(Thrift::Types::I16, 2**31) }.to raise_error(RangeError)
|
|
209
|
+
expect { @prot.write_set_begin(Thrift::Types::I16, 2**31) }.to raise_error(RangeError)
|
|
210
|
+
end
|
|
211
|
+
|
|
186
212
|
it "should write a double" do
|
|
187
213
|
# try a random scattering of values, including min/max
|
|
188
214
|
values = [Float::MIN, -1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
|
|
@@ -229,6 +255,16 @@ shared_examples_for 'a binary protocol' do
|
|
|
229
255
|
expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
|
|
230
256
|
end
|
|
231
257
|
|
|
258
|
+
it 'should write a frozen non-binary string without mutating the input' do
|
|
259
|
+
buffer = "abc \u20AC".encode('UTF-8').freeze
|
|
260
|
+
@prot.write_binary(buffer)
|
|
261
|
+
a = @trans.read(@trans.available)
|
|
262
|
+
expect(buffer.encoding).to eq(Encoding::UTF_8)
|
|
263
|
+
expect(buffer).to be_frozen
|
|
264
|
+
expect(a.encoding).to eq(Encoding::BINARY)
|
|
265
|
+
expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
|
|
266
|
+
end
|
|
267
|
+
|
|
232
268
|
it "should error gracefully when trying to write a nil string" do
|
|
233
269
|
expect { @prot.write_string(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
|
|
234
270
|
end
|
|
@@ -284,6 +320,13 @@ shared_examples_for 'a binary protocol' do
|
|
|
284
320
|
expect(@prot.read_map_begin).to eq([Thrift::Types::DOUBLE, Thrift::Types::I64, 42])
|
|
285
321
|
end
|
|
286
322
|
|
|
323
|
+
it "should reject a negative map size" do
|
|
324
|
+
@trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 0xffffffff].pack("ccN"))
|
|
325
|
+
expect { @prot.read_map_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
326
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
287
330
|
# map footer is a noop
|
|
288
331
|
|
|
289
332
|
it "should read a list header" do
|
|
@@ -291,6 +334,13 @@ shared_examples_for 'a binary protocol' do
|
|
|
291
334
|
expect(@prot.read_list_begin).to eq([Thrift::Types::STRING, 17])
|
|
292
335
|
end
|
|
293
336
|
|
|
337
|
+
it "should reject a negative list size" do
|
|
338
|
+
@trans.write([Thrift::Types::STRING, 0xffffffff].pack("cN"))
|
|
339
|
+
expect { @prot.read_list_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
340
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
294
344
|
# list footer is a noop
|
|
295
345
|
|
|
296
346
|
it "should read a set header" do
|
|
@@ -298,6 +348,13 @@ shared_examples_for 'a binary protocol' do
|
|
|
298
348
|
expect(@prot.read_set_begin).to eq([Thrift::Types::STRING, 17])
|
|
299
349
|
end
|
|
300
350
|
|
|
351
|
+
it "should reject a negative set size" do
|
|
352
|
+
@trans.write([Thrift::Types::STRING, 0xffffffff].pack("cN"))
|
|
353
|
+
expect { @prot.read_set_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
354
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
301
358
|
# set footer is a noop
|
|
302
359
|
|
|
303
360
|
it "should read a bool" do
|
|
@@ -371,6 +428,13 @@ shared_examples_for 'a binary protocol' do
|
|
|
371
428
|
expect(a.encoding).to eq(Encoding::BINARY)
|
|
372
429
|
end
|
|
373
430
|
|
|
431
|
+
it "should reject a negative binary size" do
|
|
432
|
+
@trans.write([0xff, 0xff, 0xff, 0xff].pack('C*'))
|
|
433
|
+
expect { @prot.read_binary }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
434
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
374
438
|
it "should perform a complete rpc with no args or return" do
|
|
375
439
|
srv_test(
|
|
376
440
|
proc { |client| client.send_voidMethod() },
|
data/spec/bytes_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -44,6 +45,23 @@ describe Thrift::Bytes do
|
|
|
44
45
|
a = Thrift::Bytes.force_binary_encoding e
|
|
45
46
|
expect(a.encoding).to eq(Encoding::BINARY)
|
|
46
47
|
end
|
|
48
|
+
|
|
49
|
+
it 'should return the same frozen binary string unchanged' do
|
|
50
|
+
e = 'STRING'.b.freeze
|
|
51
|
+
a = Thrift::Bytes.force_binary_encoding(e)
|
|
52
|
+
expect(a).to equal(e)
|
|
53
|
+
expect(a.encoding).to eq(Encoding::BINARY)
|
|
54
|
+
expect(a).to be_frozen
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'should duplicate a frozen non-binary string before changing encoding' do
|
|
58
|
+
e = 'STRING'.encode('UTF-8').freeze
|
|
59
|
+
a = Thrift::Bytes.force_binary_encoding(e)
|
|
60
|
+
expect(a).not_to equal(e)
|
|
61
|
+
expect(a.encoding).to eq(Encoding::BINARY)
|
|
62
|
+
expect(e.encoding).to eq(Encoding::UTF_8)
|
|
63
|
+
expect(e).to be_frozen
|
|
64
|
+
end
|
|
47
65
|
end
|
|
48
66
|
|
|
49
67
|
describe '.get_string_byte' do
|
|
@@ -56,7 +74,7 @@ describe Thrift::Bytes do
|
|
|
56
74
|
|
|
57
75
|
describe '.set_string_byte' do
|
|
58
76
|
it 'should set byte value at index' do
|
|
59
|
-
s = "\x41\x42"
|
|
77
|
+
s = "\x41\x42".b
|
|
60
78
|
Thrift::Bytes.set_string_byte(s, 0, 0x43)
|
|
61
79
|
expect(s.getbyte(0)).to eq(0x43)
|
|
62
80
|
expect(s).to eq('CB')
|
data/spec/client_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -21,6 +22,16 @@
|
|
|
21
22
|
require 'spec_helper'
|
|
22
23
|
|
|
23
24
|
describe Thrift::CompactProtocol do
|
|
25
|
+
INTEGER_BOUNDARY_TESTS = {
|
|
26
|
+
:i32 => [-(2**31), (2**31) - 1],
|
|
27
|
+
:i64 => [-(2**63), (2**63) - 1]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
INTEGER_MINIMUM_ENCODINGS = {
|
|
31
|
+
:i32 => [0xff, 0xff, 0xff, 0xff, 0x0f],
|
|
32
|
+
:i64 => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01]
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
TESTS = {
|
|
25
36
|
:byte => (-127..127).to_a,
|
|
26
37
|
:i16 => (0..14).map { |shift| [1 << shift, -(1 << shift)] }.flatten.sort,
|
|
@@ -71,6 +82,54 @@ describe Thrift::CompactProtocol do
|
|
|
71
82
|
end
|
|
72
83
|
end
|
|
73
84
|
|
|
85
|
+
it "should round-trip signed integer boundaries correctly" do
|
|
86
|
+
INTEGER_BOUNDARY_TESTS.each_pair do |primitive_type, test_values|
|
|
87
|
+
test_values.each do |value|
|
|
88
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
89
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
90
|
+
|
|
91
|
+
proto.send(writer(primitive_type), value)
|
|
92
|
+
expect(proto.send(reader(primitive_type))).to eq(value)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "should encode signed integer minima with the canonical zigzag varint bytes" do
|
|
98
|
+
INTEGER_MINIMUM_ENCODINGS.each_pair do |primitive_type, expected_bytes|
|
|
99
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
100
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
101
|
+
|
|
102
|
+
proto.send(writer(primitive_type), INTEGER_BOUNDARY_TESTS.fetch(primitive_type).first)
|
|
103
|
+
expect(trans.read(trans.available).bytes).to eq(expected_bytes)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should decode i32 minima from direct canonical zigzag bytes" do
|
|
108
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
109
|
+
trans.write(INTEGER_MINIMUM_ENCODINGS[:i32].pack("C*"))
|
|
110
|
+
|
|
111
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
112
|
+
expect(proto.read_i32).to eq(INTEGER_BOUNDARY_TESTS[:i32].first)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should decode i64 minima from direct canonical zigzag bytes" do
|
|
116
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
117
|
+
trans.write(INTEGER_MINIMUM_ENCODINGS[:i64].pack("C*"))
|
|
118
|
+
|
|
119
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
120
|
+
expect(proto.read_i64).to eq(INTEGER_BOUNDARY_TESTS[:i64].first)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should read binary values with multi-byte varint32 lengths" do
|
|
124
|
+
payload = "x" * 128
|
|
125
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
126
|
+
trans.write([0x80, 0x01].pack("C*"))
|
|
127
|
+
trans.write(payload)
|
|
128
|
+
|
|
129
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
130
|
+
expect(proto.read_binary).to eq(payload)
|
|
131
|
+
end
|
|
132
|
+
|
|
74
133
|
it "should write a uuid" do
|
|
75
134
|
trans = Thrift::MemoryBufferTransport.new
|
|
76
135
|
proto = Thrift::CompactProtocol.new(trans)
|
|
@@ -170,6 +229,46 @@ describe Thrift::CompactProtocol do
|
|
|
170
229
|
expect(Thrift::CompactProtocol.new(trans).to_s).to eq("compact(memory)")
|
|
171
230
|
end
|
|
172
231
|
|
|
232
|
+
it "should write a frozen non-binary string without mutating the input" do
|
|
233
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
234
|
+
prot = Thrift::CompactProtocol.new(trans)
|
|
235
|
+
buffer = "abc \u20AC".encode("UTF-8").freeze
|
|
236
|
+
|
|
237
|
+
prot.write_binary(buffer)
|
|
238
|
+
|
|
239
|
+
expect(buffer.encoding).to eq(Encoding::UTF_8)
|
|
240
|
+
expect(buffer).to be_frozen
|
|
241
|
+
expect(trans.read(trans.available).unpack("C*")).to eq([0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "should reject a varint with more than 10 continuation bytes" do
|
|
245
|
+
trans = Thrift::MemoryBufferTransport.new(([0x80] * 11).pack("C*"))
|
|
246
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
247
|
+
expect { proto.read_i64 }.to raise_error(Thrift::ProtocolException) do |e|
|
|
248
|
+
expect(e.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "should accept a valid 10-byte varint" do
|
|
253
|
+
trans = Thrift::MemoryBufferTransport.new((([0x80] * 9) + [0x01]).pack("C*"))
|
|
254
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
255
|
+
expect { proto.read_i64 }.not_to raise_error
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should reject a 32-bit varint with more than 5 continuation bytes" do
|
|
259
|
+
trans = Thrift::MemoryBufferTransport.new(([0x80] * 6).pack("C*"))
|
|
260
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
261
|
+
expect { proto.read_i32 }.to raise_error(Thrift::ProtocolException) do |e|
|
|
262
|
+
expect(e.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "should accept a valid 5-byte varint for i32" do
|
|
267
|
+
trans = Thrift::MemoryBufferTransport.new((([0x80] * 4) + [0x0f]).pack("C*"))
|
|
268
|
+
proto = Thrift::CompactProtocol.new(trans)
|
|
269
|
+
expect { proto.read_i32 }.not_to raise_error
|
|
270
|
+
end
|
|
271
|
+
|
|
173
272
|
class JankyHandler
|
|
174
273
|
def Janky(i32arg)
|
|
175
274
|
i32arg * 2
|
data/spec/constants_demo_spec.rb
CHANGED
data/spec/exception_spec.rb
CHANGED
data/spec/flat_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -158,6 +159,50 @@ describe 'HeaderTransport' do
|
|
|
158
159
|
end
|
|
159
160
|
end
|
|
160
161
|
|
|
162
|
+
describe "decompressed size limits" do
|
|
163
|
+
it "should accept a valid max_decompressed_size" do
|
|
164
|
+
expect { @trans.set_max_decompressed_size(1024) }.not_to raise_error
|
|
165
|
+
expect { @trans.set_max_decompressed_size(Thrift::HeaderTransport::MAX_FRAME_SIZE) }.not_to raise_error
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should reject invalid max_decompressed_size" do
|
|
169
|
+
expect { @trans.set_max_decompressed_size(0) }.to raise_error(ArgumentError)
|
|
170
|
+
expect { @trans.set_max_decompressed_size(-1) }.to raise_error(ArgumentError)
|
|
171
|
+
expect { @trans.set_max_decompressed_size(Thrift::HeaderTransport::MAX_FRAME_SIZE + 1) }.to raise_error(ArgumentError)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should decompress ZLIB payload within the limit" do
|
|
175
|
+
write_buf = Thrift::MemoryBufferTransport.new
|
|
176
|
+
writer = Thrift::HeaderTransport.new(write_buf)
|
|
177
|
+
writer.add_transform(Thrift::HeaderTransformID::ZLIB)
|
|
178
|
+
writer.write("A" * 1_000)
|
|
179
|
+
writer.flush
|
|
180
|
+
|
|
181
|
+
written_data = write_buf.read(write_buf.available)
|
|
182
|
+
read_trans = Thrift::HeaderTransport.new(Thrift::MemoryBufferTransport.new(written_data))
|
|
183
|
+
read_trans.set_max_decompressed_size(2_000)
|
|
184
|
+
|
|
185
|
+
expect(read_trans.read(1_000)).to eq("A" * 1_000)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should raise SIZE_LIMIT TransportException when decompressed output exceeds the limit" do
|
|
189
|
+
write_buf = Thrift::MemoryBufferTransport.new
|
|
190
|
+
writer = Thrift::HeaderTransport.new(write_buf)
|
|
191
|
+
writer.add_transform(Thrift::HeaderTransformID::ZLIB)
|
|
192
|
+
writer.write("A" * 10_000)
|
|
193
|
+
writer.flush
|
|
194
|
+
|
|
195
|
+
written_data = write_buf.read(write_buf.available)
|
|
196
|
+
read_trans = Thrift::HeaderTransport.new(Thrift::MemoryBufferTransport.new(written_data))
|
|
197
|
+
read_trans.set_max_decompressed_size(100)
|
|
198
|
+
|
|
199
|
+
expect { read_trans.read(1) }.to raise_error(Thrift::TransportException) do |e|
|
|
200
|
+
expect(e.type).to eq(Thrift::TransportException::SIZE_LIMIT)
|
|
201
|
+
expect(e.message).to match(/limit/)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
161
206
|
describe "read and frame detection" do
|
|
162
207
|
it "should detect Header format" do
|
|
163
208
|
# Write a Header frame
|
data/spec/http_client_spec.rb
CHANGED
data/spec/json_protocol_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -223,14 +224,14 @@ describe 'JsonProtocol' do
|
|
|
223
224
|
it 'should write string' do
|
|
224
225
|
@prot.write_string('this is a test string')
|
|
225
226
|
a = @trans.read(@trans.available)
|
|
226
|
-
expect(a).to eq('"this is a test string"'.
|
|
227
|
+
expect(a).to eq('"this is a test string"'.b)
|
|
227
228
|
expect(a.encoding).to eq(Encoding::BINARY)
|
|
228
229
|
end
|
|
229
230
|
|
|
230
231
|
it 'should write string with unicode characters' do
|
|
231
232
|
@prot.write_string("this is a test string with unicode characters: \u20AC \u20AD")
|
|
232
233
|
a = @trans.read(@trans.available)
|
|
233
|
-
expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".
|
|
234
|
+
expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".b)
|
|
234
235
|
expect(a.encoding).to eq(Encoding::BINARY)
|
|
235
236
|
end
|
|
236
237
|
|
|
@@ -442,6 +443,13 @@ describe 'JsonProtocol' do
|
|
|
442
443
|
expect(@prot.read_map_begin).to eq([12, 15, 2])
|
|
443
444
|
end
|
|
444
445
|
|
|
446
|
+
it "should reject a negative map size" do
|
|
447
|
+
@trans.write("[\"rec\",\"lst\",-1,{")
|
|
448
|
+
expect { @prot.read_map_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
449
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
445
453
|
it "should read map end" do
|
|
446
454
|
@trans.write("}]")
|
|
447
455
|
expect(@prot.read_map_end).to eq(nil)
|
|
@@ -452,6 +460,13 @@ describe 'JsonProtocol' do
|
|
|
452
460
|
expect(@prot.read_list_begin).to eq([12, 2])
|
|
453
461
|
end
|
|
454
462
|
|
|
463
|
+
it "should reject a negative list size" do
|
|
464
|
+
@trans.write("[\"rec\",-1\"\"")
|
|
465
|
+
expect { @prot.read_list_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
466
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
455
470
|
it "should read list end" do
|
|
456
471
|
@trans.write("]")
|
|
457
472
|
expect(@prot.read_list_end).to eq(nil)
|
|
@@ -462,6 +477,13 @@ describe 'JsonProtocol' do
|
|
|
462
477
|
expect(@prot.read_set_begin).to eq([12, 2])
|
|
463
478
|
end
|
|
464
479
|
|
|
480
|
+
it "should reject a negative set size" do
|
|
481
|
+
@trans.write("[\"rec\",-1\"\"")
|
|
482
|
+
expect { @prot.read_set_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
483
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
465
487
|
it "should read set end" do
|
|
466
488
|
@trans.write("]")
|
|
467
489
|
expect(@prot.read_set_end).to eq(nil)
|
|
@@ -502,14 +524,14 @@ describe 'JsonProtocol' do
|
|
|
502
524
|
end
|
|
503
525
|
|
|
504
526
|
it 'should read string' do
|
|
505
|
-
@trans.write('"this is a test string"'.
|
|
527
|
+
@trans.write('"this is a test string"'.b)
|
|
506
528
|
a = @prot.read_string
|
|
507
529
|
expect(a).to eq('this is a test string')
|
|
508
530
|
expect(a.encoding).to eq(Encoding::UTF_8)
|
|
509
531
|
end
|
|
510
532
|
|
|
511
533
|
it 'should read string with unicode characters' do
|
|
512
|
-
@trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.
|
|
534
|
+
@trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.b)
|
|
513
535
|
a = @prot.read_string
|
|
514
536
|
expect(a).to eq("this is a test string with unicode characters: \u20AC \u20AD")
|
|
515
537
|
expect(a.encoding).to eq(Encoding::UTF_8)
|