thrift 0.24.0 → 0.25.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 +107 -4
- data/ext/binary_protocol_accelerated.c +52 -17
- data/ext/compact_protocol.c +135 -70
- data/ext/constants.h +3 -0
- data/ext/extconf.rb +4 -4
- data/ext/macros.h +11 -0
- data/ext/memory_buffer.c +35 -17
- data/ext/struct.c +185 -64
- data/ext/thrift_native.c +6 -0
- data/lib/thrift/bytes.rb +2 -2
- data/lib/thrift/client.rb +31 -22
- data/lib/thrift/exceptions.rb +10 -8
- data/lib/thrift/multiplexed_processor.rb +5 -6
- data/lib/thrift/processor.rb +24 -3
- data/lib/thrift/protocol/base_protocol.rb +53 -27
- data/lib/thrift/protocol/binary_protocol.rb +54 -40
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -2
- data/lib/thrift/protocol/compact_protocol.rb +193 -88
- data/lib/thrift/protocol/header_protocol.rb +14 -3
- data/lib/thrift/protocol/json_protocol.rb +146 -104
- data/lib/thrift/protocol/multiplexed_protocol.rb +2 -3
- data/lib/thrift/protocol/protocol_decorator.rb +5 -2
- data/lib/thrift/serializer/serializer.rb +6 -0
- data/lib/thrift/server/base_server.rb +10 -2
- data/lib/thrift/server/nonblocking_server.rb +49 -26
- data/lib/thrift/server/rack_application.rb +69 -0
- data/lib/thrift/server/simple_server.rb +27 -23
- data/lib/thrift/server/thin_http_server.rb +20 -44
- data/lib/thrift/server/thread_pool_server.rb +20 -17
- data/lib/thrift/server/threaded_server.rb +22 -26
- data/lib/thrift/struct.rb +33 -18
- data/lib/thrift/struct_union.rb +36 -30
- data/lib/thrift/transport/base_transport.rb +23 -5
- data/lib/thrift/transport/buffered_transport.rb +4 -4
- data/lib/thrift/transport/framed_transport.rb +32 -7
- data/lib/thrift/transport/header_transport.rb +130 -50
- data/lib/thrift/transport/http_client_transport.rb +27 -14
- data/lib/thrift/transport/io_stream_transport.rb +2 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +8 -10
- data/lib/thrift/transport/server_socket.rb +4 -5
- data/lib/thrift/transport/socket.rb +20 -22
- data/lib/thrift/transport/ssl_server_socket.rb +64 -4
- data/lib/thrift/transport/ssl_socket.rb +32 -5
- data/lib/thrift/transport/unix_server_socket.rb +1 -1
- data/lib/thrift/transport/unix_socket.rb +4 -6
- data/lib/thrift/types.rb +22 -22
- data/lib/thrift/union.rb +20 -11
- data/lib/thrift/uuid.rb +8 -8
- data/lib/thrift.rb +39 -39
- metadata +5 -230
- data/benchmark/Benchmark.thrift +0 -24
- data/benchmark/benchmark.rb +0 -286
- data/benchmark/client.rb +0 -118
- data/benchmark/server.rb +0 -121
- data/benchmark/thin_server.rb +0 -46
- data/lib/thrift/server/mongrel_http_server.rb +0 -61
- data/spec/BaseService.thrift +0 -27
- data/spec/ExtendedService.thrift +0 -25
- data/spec/Referenced.thrift +0 -44
- data/spec/ThriftNamespacedSpec.thrift +0 -53
- data/spec/ThriftSpec.thrift +0 -203
- data/spec/base_protocol_spec.rb +0 -244
- data/spec/base_transport_spec.rb +0 -428
- data/spec/binary_protocol_accelerated_spec.rb +0 -47
- data/spec/binary_protocol_spec.rb +0 -73
- data/spec/binary_protocol_spec_shared.rb +0 -509
- data/spec/bytes_spec.rb +0 -117
- data/spec/client_spec.rb +0 -167
- data/spec/compact_protocol_spec.rb +0 -295
- data/spec/constants_demo_spec.rb +0 -102
- data/spec/exception_spec.rb +0 -141
- data/spec/flat_spec.rb +0 -63
- data/spec/header_protocol_spec.rb +0 -476
- data/spec/header_transport_spec.rb +0 -431
- data/spec/http_client_spec.rb +0 -160
- data/spec/json_protocol_spec.rb +0 -574
- data/spec/multiplexed_processor_spec.rb +0 -75
- data/spec/namespaced_spec.rb +0 -67
- data/spec/nonblocking_server_spec.rb +0 -429
- data/spec/processor_spec.rb +0 -80
- data/spec/recursion_depth_spec.rb +0 -223
- data/spec/serializer_spec.rb +0 -67
- data/spec/server_socket_spec.rb +0 -121
- data/spec/server_spec.rb +0 -238
- data/spec/socket_spec.rb +0 -174
- data/spec/socket_spec_shared.rb +0 -168
- data/spec/spec_helper.rb +0 -70
- data/spec/ssl_server_socket_spec.rb +0 -85
- data/spec/ssl_socket_spec.rb +0 -248
- data/spec/struct_nested_containers_spec.rb +0 -191
- data/spec/struct_spec.rb +0 -398
- data/spec/support/header_protocol_helper.rb +0 -55
- data/spec/thin_http_server_spec.rb +0 -127
- data/spec/types_spec.rb +0 -118
- data/spec/union_spec.rb +0 -273
- data/spec/unix_socket_spec.rb +0 -131
- data/spec/uuid_validation_spec.rb +0 -239
- data/test/fuzz/Makefile +0 -779
- data/test/fuzz/Makefile.am +0 -173
- data/test/fuzz/Makefile.in +0 -775
- data/test/fuzz/README.md +0 -149
- data/test/fuzz/fuzz_common.rb +0 -96
- data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_json_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_tracer.rb +0 -29
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0eacf1574da356dba55962561224cd683bf1c073e531b8402f469e91cb964dd8
|
|
4
|
+
data.tar.gz: b7f8aed51a240fab797e8137d56bd65c25d04291b292be40b3475831b945d4f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35f22ce7f4d25a25c18611548eaf575a33a62bdd3a673876ac36fa783ccb44bd7b0066ebf2b1158ad6687aaf49182a9af2a9f6c1955addcf71e8c7738f615a66
|
|
7
|
+
data.tar.gz: 0edd8cdaccb60eb0082da2aed7169f46b167ef821d68ba126c22945738165d20bca3a505fb09969c8abb5dccd212ea23d296ffcc02c2b6e46a29d361e925efcf
|
data/README.md
CHANGED
|
@@ -27,7 +27,7 @@ clients and services.
|
|
|
27
27
|
|
|
28
28
|
## Compatibility
|
|
29
29
|
|
|
30
|
-
- Ruby MRI >=
|
|
30
|
+
- Ruby MRI >= 3.0 (tested against current supported releases).
|
|
31
31
|
- JRuby works with the pure-Ruby implementation; the native extension is
|
|
32
32
|
skipped automatically.
|
|
33
33
|
- For the repo-wide transport, protocol, and server support matrix, see
|
|
@@ -36,7 +36,7 @@ clients and services.
|
|
|
36
36
|
|
|
37
37
|
## Installation
|
|
38
38
|
|
|
39
|
-
- Requirements: Ruby >=
|
|
39
|
+
- Requirements: Ruby >= 3.0.
|
|
40
40
|
- From RubyGems: `gem install thrift`
|
|
41
41
|
- From source: `bundle install`, `gem build thrift.gemspec`, then install the
|
|
42
42
|
resulting `thrift-*.gem`. The native accelerator is built when the gem is
|
|
@@ -97,6 +97,31 @@ server = Thrift::ThreadedServer.new(processor, server_transport,
|
|
|
97
97
|
server.serve
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
## Rack HTTP Endpoint
|
|
101
|
+
|
|
102
|
+
Ruby HTTP transport can be mounted as a Rack application, so applications can
|
|
103
|
+
run Thrift on an existing Rack server such as Puma or Falcon.
|
|
104
|
+
The examples below use the generated `Calculator::Processor` and the
|
|
105
|
+
`CalculatorHandler` from [Basic Server Usage](#basic-server-usage).
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
# config.ru
|
|
109
|
+
require 'thrift'
|
|
110
|
+
require 'thrift/server/rack_application'
|
|
111
|
+
|
|
112
|
+
processor = Calculator::Processor.new(CalculatorHandler.new)
|
|
113
|
+
run Thrift::RackApplication.new(processor)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For Rails or another Rack router, mount the endpoint at the route that should
|
|
117
|
+
receive Thrift HTTP requests:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
# config/routes.rb
|
|
121
|
+
processor = Calculator::Processor.new(CalculatorHandler.new)
|
|
122
|
+
mount Thrift::RackApplication.new(processor) => "/thrift"
|
|
123
|
+
```
|
|
124
|
+
|
|
100
125
|
## Development and Tests
|
|
101
126
|
|
|
102
127
|
- `bundle exec rake spec` runs the Ruby specs. It expects a built Thrift
|
|
@@ -117,6 +142,63 @@ server.serve
|
|
|
117
142
|
|
|
118
143
|
## Breaking Changes
|
|
119
144
|
|
|
145
|
+
### 0.25.0
|
|
146
|
+
|
|
147
|
+
Ruby 2.7 support has been removed because the runtime reached end of life on
|
|
148
|
+
March 31, 2023. The Thrift gem now requires Ruby 3.0 or newer. Applications
|
|
149
|
+
still running Ruby 2.7 must upgrade Ruby before installing Thrift 0.25.0 or
|
|
150
|
+
remain on an earlier Thrift release.
|
|
151
|
+
|
|
152
|
+
Ruby HTTP servers now share one Rack endpoint. Run `Thrift::RackApplication`
|
|
153
|
+
as a Rack app, or mount it at one path in an app such as Rails. The
|
|
154
|
+
cross-language HTTP tests now cover Puma and Falcon.
|
|
155
|
+
|
|
156
|
+
`Thrift::MongrelHTTPServer` has been removed because Mongrel no longer works
|
|
157
|
+
with supported Ruby versions. To migrate, mount `Thrift::RackApplication` in
|
|
158
|
+
a supported Rack server. See [Rack HTTP Endpoint](#rack-http-endpoint).
|
|
159
|
+
|
|
160
|
+
`Thrift::ThinHTTPServer` is deprecated because Thin is no longer maintained.
|
|
161
|
+
Its EventMachine dependency also does not build on new Ruby development
|
|
162
|
+
versions. Creating a Thin server now prints a warning. Move to
|
|
163
|
+
`Thrift::RackApplication` with a supported Rack server such as Puma or Falcon.
|
|
164
|
+
|
|
165
|
+
`Thrift::SSLSocket` now verifies peers by default when no SSL context is
|
|
166
|
+
provided. It creates a context that uses the system certificate store. A
|
|
167
|
+
supplied SSL context is not reconfigured by Thrift, so the application is
|
|
168
|
+
responsible for its verification mode and trust sources. A newly constructed
|
|
169
|
+
`OpenSSL::SSL::SSLContext` defaults to `OpenSSL::SSL::VERIFY_NONE`; configuring
|
|
170
|
+
a trust source alone does not enable certificate chain verification. The server
|
|
171
|
+
certificate must still match the connection hostname.
|
|
172
|
+
|
|
173
|
+
`Thrift::NonblockingServer` now closes a connection whose frame declares more than
|
|
174
|
+
`max_frame_size` before it collects the frame. `max_frame_size` is a new keyword argument
|
|
175
|
+
and defaults to `Thrift::FramedTransport::DEFAULT_MAX_FRAME_SIZE` (16,384,000 bytes), the
|
|
176
|
+
limit `FramedTransport` already applies to the frame the worker reads back. A server that
|
|
177
|
+
accepted larger frames must pass a higher `max_frame_size:` to keep doing so.
|
|
178
|
+
|
|
179
|
+
`Thrift::Socket#open` now raises
|
|
180
|
+
`Thrift::TransportException::ALREADY_OPEN` when the TCP transport is already
|
|
181
|
+
open. Close the transport before opening it again.
|
|
182
|
+
|
|
183
|
+
Ruby struct, union, and exception serialization methods now accept an optional
|
|
184
|
+
remaining struct depth: `read(protocol, depth = 64)` and
|
|
185
|
+
`write(protocol, depth = 64)`.
|
|
186
|
+
Unknown and mismatched fields remain independently bounded by
|
|
187
|
+
`Thrift::BaseProtocol#skip`. The `write_field` and `write_type` helpers accept
|
|
188
|
+
an optional `remaining_depth`: custom writers must use
|
|
189
|
+
`write_field(field_info, fid, value, remaining_depth)` or
|
|
190
|
+
`write_type(field_info, value, remaining_depth)` for struct values. Custom
|
|
191
|
+
protocols and custom struct, union, or exception serialization overrides with
|
|
192
|
+
exact argument counts must accept and forward the optional depth argument (or
|
|
193
|
+
use `*args`) before upgrading.
|
|
194
|
+
|
|
195
|
+
`Thrift::BinaryProtocol`, `Thrift::BinaryProtocolAccelerated` and `Thrift::CompactProtocol`
|
|
196
|
+
now refuse a string or binary field longer than `max_string_size` before reading it,
|
|
197
|
+
with a `ProtocolException` of type `SIZE_LIMIT`. The maximum defaults to
|
|
198
|
+
`Thrift::BaseProtocol::DEFAULT_MAX_STRING_SIZE`, 16384000 bytes, the frame size limit
|
|
199
|
+
the framed transports apply, and is a keyword argument of the three protocols and
|
|
200
|
+
their factories. Pass `max_string_size: nil` to read strings of any length, as before.
|
|
201
|
+
|
|
120
202
|
### 0.24.0
|
|
121
203
|
|
|
122
204
|
Connect timeout handling changed for both `Thrift::Socket` and
|
|
@@ -219,6 +301,14 @@ best-effort, not guaranteed.
|
|
|
219
301
|
|
|
220
302
|
## Migration Notes
|
|
221
303
|
|
|
304
|
+
- If you upgrade to `0.25.0`, note that `Thrift::SSLSocket` now verifies peers
|
|
305
|
+
by default when it creates the SSL context. Supplied contexts are used
|
|
306
|
+
unchanged and must configure their own verification mode and trust sources.
|
|
307
|
+
A blank supplied context defaults to `OpenSSL::SSL::VERIFY_NONE`. Hostname
|
|
308
|
+
checking is performed for both supplied and default contexts.
|
|
309
|
+
- If you upgrade to `0.25.0`, close a `Thrift::Socket` before calling `open`
|
|
310
|
+
again. A duplicate open now raises
|
|
311
|
+
`Thrift::TransportException::ALREADY_OPEN`.
|
|
222
312
|
- If you upgrade to `0.24.0`, treat `timeout` on `Thrift::Socket` and
|
|
223
313
|
`Thrift::SSLSocket` as one budget for the whole open path. For
|
|
224
314
|
`Thrift::SSLSocket`, that includes both the TCP connect and the TLS
|
|
@@ -257,5 +347,18 @@ best-effort, not guaranteed.
|
|
|
257
347
|
- Client and server must agree on transport and protocol choices. If you
|
|
258
348
|
switch to SSL, HTTP, header transport, compact protocol, or namespaced
|
|
259
349
|
generated code, update both ends together.
|
|
260
|
-
- HTTPS client transport
|
|
261
|
-
|
|
350
|
+
- HTTPS client transport and `Thrift::SSLSocket` verify peers by default.
|
|
351
|
+
When no SSL context is provided, `Thrift::SSLSocket` creates one with peer
|
|
352
|
+
verification and the system certificate store. Thrift passes a supplied
|
|
353
|
+
context to OpenSSL without reconfiguring it. `Thrift::SSLSocket` always
|
|
354
|
+
checks the certificate against `server_hostname` (or the connection host by
|
|
355
|
+
default). `OpenSSL::SSL::SSLContext.new` defaults to
|
|
356
|
+
`OpenSSL::SSL::VERIFY_NONE`, and setting `ca_file`, `ca_path`, or `cert_store`
|
|
357
|
+
does not enable verification by itself. Set `verify_mode` explicitly when
|
|
358
|
+
supplying a context. For example, to disable certificate chain verification:
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
context = OpenSSL::SSL::SSLContext.new
|
|
362
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
363
|
+
socket = Thrift::SSLSocket.new(host, port, nil, context)
|
|
364
|
+
```
|
|
@@ -331,33 +331,62 @@ static char read_byte_direct(VALUE self) {
|
|
|
331
331
|
return (char)(FIX2INT(byte));
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
static int16_t uint16_to_int16(uint16_t value) {
|
|
335
|
+
if (value <= INT16_MAX) {
|
|
336
|
+
return (int16_t)value;
|
|
337
|
+
}
|
|
338
|
+
return (int16_t)((int32_t)value - ((int32_t)UINT16_MAX + 1));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
static int32_t uint32_to_int32(uint32_t value) {
|
|
342
|
+
if (value <= INT32_MAX) {
|
|
343
|
+
return (int32_t)value;
|
|
344
|
+
}
|
|
345
|
+
return (int32_t)((int64_t)value - (INT64_C(1) << 32));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
static int64_t uint64_to_int64(uint64_t value) {
|
|
349
|
+
if (value <= INT64_MAX) {
|
|
350
|
+
return (int64_t)value;
|
|
351
|
+
}
|
|
352
|
+
return -(int64_t)(~value) - INT64_C(1);
|
|
353
|
+
}
|
|
354
|
+
|
|
334
355
|
static int16_t read_i16_direct(VALUE self) {
|
|
335
356
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
336
357
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(2));
|
|
337
|
-
|
|
358
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
359
|
+
uint16_t value = ((uint16_t)bytes[0] << 8) | (uint16_t)bytes[1];
|
|
360
|
+
return uint16_to_int16(value);
|
|
338
361
|
}
|
|
339
362
|
|
|
340
363
|
static int32_t read_i32_direct(VALUE self) {
|
|
341
364
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
342
365
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(4));
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
((
|
|
346
|
-
((
|
|
366
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
367
|
+
uint32_t value = ((uint32_t)bytes[0] << 24) |
|
|
368
|
+
((uint32_t)bytes[1] << 16) |
|
|
369
|
+
((uint32_t)bytes[2] << 8) |
|
|
370
|
+
(uint32_t)bytes[3];
|
|
371
|
+
return uint32_to_int32(value);
|
|
347
372
|
}
|
|
348
373
|
|
|
349
|
-
static
|
|
374
|
+
static uint64_t read_u64_direct(VALUE self) {
|
|
350
375
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
351
376
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8));
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
((
|
|
355
|
-
((
|
|
356
|
-
|
|
357
|
-
((
|
|
358
|
-
((
|
|
359
|
-
((
|
|
360
|
-
|
|
377
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
378
|
+
return ((uint64_t)bytes[0] << 56) |
|
|
379
|
+
((uint64_t)bytes[1] << 48) |
|
|
380
|
+
((uint64_t)bytes[2] << 40) |
|
|
381
|
+
((uint64_t)bytes[3] << 32) |
|
|
382
|
+
((uint64_t)bytes[4] << 24) |
|
|
383
|
+
((uint64_t)bytes[5] << 16) |
|
|
384
|
+
((uint64_t)bytes[6] << 8) |
|
|
385
|
+
(uint64_t)bytes[7];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
static int64_t read_i64_direct(VALUE self) {
|
|
389
|
+
return uint64_to_int64(read_u64_direct(self));
|
|
361
390
|
}
|
|
362
391
|
|
|
363
392
|
VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
|
|
@@ -393,6 +422,10 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
|
|
|
393
422
|
VALUE name, seqid;
|
|
394
423
|
int type;
|
|
395
424
|
|
|
425
|
+
if (RTEST(rb_ivar_get(self, reset_message_size_ivar_id))) {
|
|
426
|
+
rb_funcall(GET_TRANSPORT(self), reset_message_size_method_id, 0);
|
|
427
|
+
}
|
|
428
|
+
|
|
396
429
|
int version = read_i32_direct(self);
|
|
397
430
|
|
|
398
431
|
if (version < 0) {
|
|
@@ -406,6 +439,7 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
|
|
|
406
439
|
if (strict_read == Qtrue) {
|
|
407
440
|
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
|
|
408
441
|
}
|
|
442
|
+
CHECK_STRING_SIZE(self, version);
|
|
409
443
|
name = READ(self, version);
|
|
410
444
|
type = read_byte_direct(self);
|
|
411
445
|
seqid = rb_thrift_binary_proto_read_i32(self);
|
|
@@ -472,9 +506,9 @@ VALUE rb_thrift_binary_proto_read_i64(VALUE self) {
|
|
|
472
506
|
VALUE rb_thrift_binary_proto_read_double(VALUE self) {
|
|
473
507
|
union {
|
|
474
508
|
double f;
|
|
475
|
-
|
|
509
|
+
uint64_t t;
|
|
476
510
|
} transfer;
|
|
477
|
-
transfer.t =
|
|
511
|
+
transfer.t = read_u64_direct(self);
|
|
478
512
|
return rb_float_new(transfer.f);
|
|
479
513
|
}
|
|
480
514
|
|
|
@@ -486,6 +520,7 @@ VALUE rb_thrift_binary_proto_read_string(VALUE self) {
|
|
|
486
520
|
VALUE rb_thrift_binary_proto_read_binary(VALUE self) {
|
|
487
521
|
int size = read_i32_direct(self);
|
|
488
522
|
CHECK_NEGATIVE_SIZE(size);
|
|
523
|
+
CHECK_STRING_SIZE(self, size);
|
|
489
524
|
return READ(self, size);
|
|
490
525
|
}
|
|
491
526
|
|
data/ext/compact_protocol.c
CHANGED
|
@@ -62,9 +62,43 @@ static int CTYPE_MAP = 0x0B;
|
|
|
62
62
|
static int CTYPE_STRUCT = 0x0C;
|
|
63
63
|
static int CTYPE_UUID = 0x0D;
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
static uint32_t int_to_zig_zag(int32_t n);
|
|
66
|
+
static void write_varint32(VALUE transport, uint32_t n);
|
|
67
|
+
|
|
68
|
+
static int64_t checked_integer_range(VALUE value, int64_t min, int64_t max) {
|
|
69
|
+
CHECK_NIL(value);
|
|
70
|
+
if (RB_UNLIKELY(!RB_INTEGER_TYPE_P(value))) {
|
|
71
|
+
rb_raise(rb_eTypeError, "integer argument expected");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
int64_t integer = NUM2LL(value);
|
|
75
|
+
if (RB_UNLIKELY(integer < min || integer > max)) {
|
|
76
|
+
rb_raise(rb_eRangeError, "integer out of bounds");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return integer;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static int8_t checked_byte_value(VALUE value) {
|
|
83
|
+
return (int8_t)checked_integer_range(value, INT8_MIN, INT8_MAX);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static int16_t checked_i16_value(VALUE value) {
|
|
87
|
+
return (int16_t)checked_integer_range(value, INT16_MIN, INT16_MAX);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static int32_t checked_i32_value(VALUE value) {
|
|
91
|
+
return (int32_t)checked_integer_range(value, INT32_MIN, INT32_MAX);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static int32_t checked_size_value(VALUE value) {
|
|
95
|
+
return (int32_t)checked_integer_range(value, 0, INT32_MAX);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static int64_t checked_i64_value(VALUE value) {
|
|
99
|
+
return checked_integer_range(value, INT64_MIN, INT64_MAX);
|
|
100
|
+
}
|
|
66
101
|
|
|
67
|
-
// TODO: implement this
|
|
68
102
|
static int get_compact_type(VALUE type_value) {
|
|
69
103
|
int type = FIX2INT(type_value);
|
|
70
104
|
if (type == TTYPE_BOOL) {
|
|
@@ -92,10 +126,11 @@ static int get_compact_type(VALUE type_value) {
|
|
|
92
126
|
} else if (type == TTYPE_UUID) {
|
|
93
127
|
return CTYPE_UUID;
|
|
94
128
|
} else {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
129
|
+
rb_exc_raise(get_protocol_exception(
|
|
130
|
+
INT2FIX(PROTOERR_INVALID_DATA),
|
|
131
|
+
rb_sprintf("Unknown compact type: %d", type)
|
|
132
|
+
));
|
|
133
|
+
return 0; /* unreachable */
|
|
99
134
|
}
|
|
100
135
|
}
|
|
101
136
|
|
|
@@ -103,13 +138,11 @@ static void write_byte_direct(VALUE transport, int8_t b) {
|
|
|
103
138
|
WRITE(transport, (char*)&b, 1);
|
|
104
139
|
}
|
|
105
140
|
|
|
106
|
-
static void write_field_begin_internal(VALUE self, VALUE type,
|
|
107
|
-
|
|
141
|
+
static void write_field_begin_internal(VALUE self, VALUE type, int16_t id, int8_t type_override) {
|
|
142
|
+
int8_t type_to_write = type_override == 0 ? get_compact_type(type) : type_override;
|
|
108
143
|
int last_id = LAST_ID(self);
|
|
109
144
|
VALUE transport = GET_TRANSPORT(self);
|
|
110
145
|
|
|
111
|
-
// if there's a type override, use that.
|
|
112
|
-
int8_t type_to_write = RTEST(type_override) ? FIX2INT(type_override) : get_compact_type(type);
|
|
113
146
|
// check if we can use delta encoding for the field id
|
|
114
147
|
int diff = id - last_id;
|
|
115
148
|
if (diff > 0 && diff <= 15) {
|
|
@@ -118,10 +151,10 @@ static void write_field_begin_internal(VALUE self, VALUE type, VALUE id_value, V
|
|
|
118
151
|
} else {
|
|
119
152
|
// write them separate
|
|
120
153
|
write_byte_direct(transport, type_to_write & 0x0f);
|
|
121
|
-
|
|
154
|
+
write_varint32(transport, int_to_zig_zag(id));
|
|
122
155
|
}
|
|
123
156
|
|
|
124
|
-
SET_LAST_ID(self,
|
|
157
|
+
SET_LAST_ID(self, INT2FIX(id));
|
|
125
158
|
}
|
|
126
159
|
|
|
127
160
|
static uint32_t int_to_zig_zag(int32_t n) {
|
|
@@ -141,35 +174,38 @@ static int32_t message_seqid_from_varint32(uint32_t seqid) {
|
|
|
141
174
|
}
|
|
142
175
|
|
|
143
176
|
static void write_varint32(VALUE transport, uint32_t n) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
n = n >> 7;
|
|
151
|
-
}
|
|
177
|
+
unsigned char bytes[5];
|
|
178
|
+
long length = 0;
|
|
179
|
+
|
|
180
|
+
while ((n & ~0x7FU) != 0U) {
|
|
181
|
+
bytes[length++] = (n & 0x7FU) | 0x80U;
|
|
182
|
+
n >>= 7;
|
|
152
183
|
}
|
|
184
|
+
bytes[length++] = n;
|
|
185
|
+
|
|
186
|
+
WRITE(transport, (const char*)bytes, length);
|
|
153
187
|
}
|
|
154
188
|
|
|
155
189
|
static void write_varint64(VALUE transport, uint64_t n) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
n = n >> 7;
|
|
163
|
-
}
|
|
190
|
+
unsigned char bytes[10];
|
|
191
|
+
long length = 0;
|
|
192
|
+
|
|
193
|
+
while ((n & ~0x7FULL) != 0ULL) {
|
|
194
|
+
bytes[length++] = (n & 0x7FULL) | 0x80ULL;
|
|
195
|
+
n >>= 7;
|
|
164
196
|
}
|
|
197
|
+
bytes[length++] = n;
|
|
198
|
+
|
|
199
|
+
WRITE(transport, (const char*)bytes, length);
|
|
165
200
|
}
|
|
166
201
|
|
|
167
202
|
static void write_collection_begin(VALUE transport, VALUE elem_type, VALUE size_value) {
|
|
168
|
-
int size =
|
|
203
|
+
int size = checked_size_value(size_value);
|
|
204
|
+
int compact_type = get_compact_type(elem_type);
|
|
169
205
|
if (size <= 14) {
|
|
170
|
-
write_byte_direct(transport, size << 4 |
|
|
206
|
+
write_byte_direct(transport, size << 4 | compact_type);
|
|
171
207
|
} else {
|
|
172
|
-
write_byte_direct(transport, 0xf0 |
|
|
208
|
+
write_byte_direct(transport, 0xf0 | compact_type);
|
|
173
209
|
write_varint32(transport, size);
|
|
174
210
|
}
|
|
175
211
|
}
|
|
@@ -216,9 +252,10 @@ VALUE rb_thrift_compact_proto_write_set_end(VALUE self) {
|
|
|
216
252
|
|
|
217
253
|
VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) {
|
|
218
254
|
VALUE transport = GET_TRANSPORT(self);
|
|
219
|
-
|
|
255
|
+
uint32_t type_value = (uint32_t)FIX2INT(type);
|
|
256
|
+
int32_t seqid_value = checked_i32_value(seqid);
|
|
220
257
|
write_byte_direct(transport, PROTOCOL_ID);
|
|
221
|
-
write_byte_direct(transport, (VERSION & VERSION_MASK) | ((
|
|
258
|
+
write_byte_direct(transport, (VERSION & VERSION_MASK) | ((type_value << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
|
|
222
259
|
write_varint32(transport, message_seqid_to_varint32(seqid_value));
|
|
223
260
|
rb_thrift_compact_proto_write_string(self, name);
|
|
224
261
|
|
|
@@ -226,11 +263,12 @@ VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE
|
|
|
226
263
|
}
|
|
227
264
|
|
|
228
265
|
VALUE rb_thrift_compact_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
|
|
266
|
+
int16_t field_id = checked_i16_value(id);
|
|
229
267
|
if (FIX2INT(type) == TTYPE_BOOL) {
|
|
230
268
|
// we want to possibly include the value, so we'll wait.
|
|
231
|
-
rb_ivar_set(self, boolean_field_id, rb_ary_new3(2, type,
|
|
269
|
+
rb_ivar_set(self, boolean_field_id, rb_ary_new3(2, type, INT2FIX(field_id)));
|
|
232
270
|
} else {
|
|
233
|
-
write_field_begin_internal(self, type,
|
|
271
|
+
write_field_begin_internal(self, type, field_id, 0);
|
|
234
272
|
}
|
|
235
273
|
|
|
236
274
|
return Qnil;
|
|
@@ -242,7 +280,7 @@ VALUE rb_thrift_compact_proto_write_field_stop(VALUE self) {
|
|
|
242
280
|
}
|
|
243
281
|
|
|
244
282
|
VALUE rb_thrift_compact_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size_value) {
|
|
245
|
-
int size =
|
|
283
|
+
int size = checked_size_value(size_value);
|
|
246
284
|
VALUE transport = GET_TRANSPORT(self);
|
|
247
285
|
if (size == 0) {
|
|
248
286
|
write_byte_direct(transport, 0);
|
|
@@ -264,39 +302,36 @@ VALUE rb_thrift_compact_proto_write_set_begin(VALUE self, VALUE etype, VALUE siz
|
|
|
264
302
|
}
|
|
265
303
|
|
|
266
304
|
VALUE rb_thrift_compact_proto_write_bool(VALUE self, VALUE b) {
|
|
267
|
-
int8_t type = b
|
|
305
|
+
int8_t type = RTEST(b) ? CTYPE_BOOLEAN_TRUE : CTYPE_BOOLEAN_FALSE;
|
|
268
306
|
VALUE boolean_field = rb_ivar_get(self, boolean_field_id);
|
|
269
307
|
if (NIL_P(boolean_field)) {
|
|
270
308
|
// we're not part of a field, so just write the value.
|
|
271
309
|
write_byte_direct(GET_TRANSPORT(self), type);
|
|
272
310
|
} else {
|
|
273
311
|
// we haven't written the field header yet
|
|
274
|
-
write_field_begin_internal(self, rb_ary_entry(boolean_field, 0), rb_ary_entry(boolean_field, 1),
|
|
312
|
+
write_field_begin_internal(self, rb_ary_entry(boolean_field, 0), FIX2INT(rb_ary_entry(boolean_field, 1)), type);
|
|
275
313
|
rb_ivar_set(self, boolean_field_id, Qnil);
|
|
276
314
|
}
|
|
277
315
|
return Qnil;
|
|
278
316
|
}
|
|
279
317
|
|
|
280
318
|
VALUE rb_thrift_compact_proto_write_byte(VALUE self, VALUE byte) {
|
|
281
|
-
|
|
282
|
-
write_byte_direct(GET_TRANSPORT(self), FIX2INT(byte));
|
|
319
|
+
write_byte_direct(GET_TRANSPORT(self), checked_byte_value(byte));
|
|
283
320
|
return Qnil;
|
|
284
321
|
}
|
|
285
322
|
|
|
286
323
|
VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16) {
|
|
287
|
-
|
|
324
|
+
write_varint32(GET_TRANSPORT(self), int_to_zig_zag(checked_i16_value(i16)));
|
|
288
325
|
return Qnil;
|
|
289
326
|
}
|
|
290
327
|
|
|
291
328
|
VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32) {
|
|
292
|
-
|
|
293
|
-
write_varint32(GET_TRANSPORT(self), int_to_zig_zag(NUM2INT(i32)));
|
|
329
|
+
write_varint32(GET_TRANSPORT(self), int_to_zig_zag(checked_i32_value(i32)));
|
|
294
330
|
return Qnil;
|
|
295
331
|
}
|
|
296
332
|
|
|
297
333
|
VALUE rb_thrift_compact_proto_write_i64(VALUE self, VALUE i64) {
|
|
298
|
-
|
|
299
|
-
write_varint64(GET_TRANSPORT(self), ll_to_zig_zag(NUM2LL(i64)));
|
|
334
|
+
write_varint64(GET_TRANSPORT(self), ll_to_zig_zag(checked_i64_value(i64)));
|
|
300
335
|
return Qnil;
|
|
301
336
|
}
|
|
302
337
|
|
|
@@ -330,8 +365,12 @@ VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str) {
|
|
|
330
365
|
VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf) {
|
|
331
366
|
buf = force_binary_encoding(buf);
|
|
332
367
|
VALUE transport = GET_TRANSPORT(self);
|
|
333
|
-
|
|
334
|
-
|
|
368
|
+
long size = RSTRING_LEN(buf);
|
|
369
|
+
if (RB_UNLIKELY(size > INT32_MAX)) {
|
|
370
|
+
rb_raise(rb_eRangeError, "integer out of bounds");
|
|
371
|
+
}
|
|
372
|
+
write_varint32(transport, (uint32_t)size);
|
|
373
|
+
WRITE(transport, StringValuePtr(buf), size);
|
|
335
374
|
return Qnil;
|
|
336
375
|
}
|
|
337
376
|
|
|
@@ -416,10 +455,20 @@ static int8_t get_ttype(int8_t ctype) {
|
|
|
416
455
|
} else if (ctype == CTYPE_UUID) {
|
|
417
456
|
return TTYPE_UUID;
|
|
418
457
|
} else {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
458
|
+
rb_exc_raise(get_protocol_exception(
|
|
459
|
+
INT2FIX(PROTOERR_INVALID_DATA),
|
|
460
|
+
rb_sprintf("Unknown compact type: %d", ctype)
|
|
461
|
+
));
|
|
462
|
+
return 0; /* unreachable */
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
static inline void validate_container_size(uint32_t size) {
|
|
467
|
+
if (RB_UNLIKELY(size > INT32_MAX)) {
|
|
468
|
+
rb_exc_raise(get_protocol_exception(
|
|
469
|
+
INT2FIX(PROTOERR_SIZE_LIMIT),
|
|
470
|
+
rb_str_new2("Container size limit exceeded")
|
|
471
|
+
));
|
|
423
472
|
}
|
|
424
473
|
}
|
|
425
474
|
|
|
@@ -437,6 +486,7 @@ static int32_t zig_zag_to_int(uint32_t n) {
|
|
|
437
486
|
}
|
|
438
487
|
|
|
439
488
|
#define MAX_VARINT32_BYTES 5 /* ceil(32/7); matches protobuf wire format */
|
|
489
|
+
#define MAX_VARINT32_LAST_BYTE 0x0f
|
|
440
490
|
#define MAX_VARINT64_BYTES 10 /* ceil(64/7); matches protobuf wire format */
|
|
441
491
|
|
|
442
492
|
static uint64_t read_varint64(VALUE self) {
|
|
@@ -457,7 +507,7 @@ static uint64_t read_varint64(VALUE self) {
|
|
|
457
507
|
static uint32_t read_varint32(VALUE self) {
|
|
458
508
|
int i, shift = 0;
|
|
459
509
|
uint32_t result = 0;
|
|
460
|
-
for (i = 0; i < MAX_VARINT32_BYTES; i++) {
|
|
510
|
+
for (i = 0; i < MAX_VARINT32_BYTES - 1; i++) {
|
|
461
511
|
int8_t b = read_byte_direct(self);
|
|
462
512
|
result |= ((uint32_t)(b & 0x7f) << shift);
|
|
463
513
|
if ((b & 0x80) != 0x80) {
|
|
@@ -465,8 +515,15 @@ static uint32_t read_varint32(VALUE self) {
|
|
|
465
515
|
}
|
|
466
516
|
shift += 7;
|
|
467
517
|
}
|
|
468
|
-
|
|
469
|
-
|
|
518
|
+
|
|
519
|
+
int8_t b = read_byte_direct(self);
|
|
520
|
+
if (RB_UNLIKELY((b & 0x80) != 0)) {
|
|
521
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Variable-length int over 5 bytes.")));
|
|
522
|
+
}
|
|
523
|
+
if (RB_UNLIKELY((b & ~MAX_VARINT32_LAST_BYTE) != 0)) {
|
|
524
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Variable-length int overflows uint32.")));
|
|
525
|
+
}
|
|
526
|
+
return result | ((uint32_t)b << shift);
|
|
470
527
|
}
|
|
471
528
|
|
|
472
529
|
static int16_t read_i16(VALUE self) {
|
|
@@ -504,21 +561,23 @@ VALUE rb_thrift_compact_proto_read_set_end(VALUE self) {
|
|
|
504
561
|
}
|
|
505
562
|
|
|
506
563
|
VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) {
|
|
564
|
+
if (RTEST(rb_ivar_get(self, reset_message_size_ivar_id))) {
|
|
565
|
+
rb_funcall(GET_TRANSPORT(self), reset_message_size_method_id, 0);
|
|
566
|
+
}
|
|
567
|
+
|
|
507
568
|
int8_t protocol_id = read_byte_direct(self);
|
|
508
569
|
if (protocol_id != PROTOCOL_ID) {
|
|
509
570
|
char buf[100];
|
|
510
|
-
|
|
511
|
-
buf
|
|
512
|
-
rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf)));
|
|
571
|
+
snprintf(buf, sizeof(buf), "Expected protocol id %d but got %d", PROTOCOL_ID, protocol_id);
|
|
572
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2(buf)));
|
|
513
573
|
}
|
|
514
574
|
|
|
515
575
|
int8_t version_and_type = read_byte_direct(self);
|
|
516
576
|
int8_t version = version_and_type & VERSION_MASK;
|
|
517
577
|
if (version != VERSION) {
|
|
518
578
|
char buf[100];
|
|
519
|
-
|
|
520
|
-
buf
|
|
521
|
-
rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf)));
|
|
579
|
+
snprintf(buf, sizeof(buf), "Expected version %d but got %d", VERSION, version);
|
|
580
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2(buf)));
|
|
522
581
|
}
|
|
523
582
|
|
|
524
583
|
int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS;
|
|
@@ -561,6 +620,7 @@ VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) {
|
|
|
561
620
|
|
|
562
621
|
VALUE rb_thrift_compact_proto_read_map_begin(VALUE self) {
|
|
563
622
|
uint32_t size = read_varint32(self);
|
|
623
|
+
validate_container_size(size);
|
|
564
624
|
uint8_t key_and_value_type = size == 0 ? 0 : read_byte_direct(self);
|
|
565
625
|
return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)), UINT2NUM(size));
|
|
566
626
|
}
|
|
@@ -571,6 +631,7 @@ VALUE rb_thrift_compact_proto_read_list_begin(VALUE self) {
|
|
|
571
631
|
if (size == 15) {
|
|
572
632
|
size = read_varint32(self);
|
|
573
633
|
}
|
|
634
|
+
validate_container_size(size);
|
|
574
635
|
uint8_t type = get_ttype(size_and_type & 0x0f);
|
|
575
636
|
return rb_ary_new3(2, INT2FIX(type), UINT2NUM(size));
|
|
576
637
|
}
|
|
@@ -608,19 +669,19 @@ VALUE rb_thrift_compact_proto_read_i64(VALUE self) {
|
|
|
608
669
|
VALUE rb_thrift_compact_proto_read_double(VALUE self) {
|
|
609
670
|
union {
|
|
610
671
|
double f;
|
|
611
|
-
|
|
672
|
+
uint64_t l;
|
|
612
673
|
} transfer;
|
|
613
674
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
614
675
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8));
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
| ((
|
|
618
|
-
| ((
|
|
619
|
-
|
|
620
|
-
| ((
|
|
621
|
-
| ((
|
|
622
|
-
| ((
|
|
623
|
-
|
|
676
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
677
|
+
transfer.l = (uint64_t)bytes[0]
|
|
678
|
+
| ((uint64_t)bytes[1] << 8)
|
|
679
|
+
| ((uint64_t)bytes[2] << 16)
|
|
680
|
+
| ((uint64_t)bytes[3] << 24)
|
|
681
|
+
| ((uint64_t)bytes[4] << 32)
|
|
682
|
+
| ((uint64_t)bytes[5] << 40)
|
|
683
|
+
| ((uint64_t)bytes[6] << 48)
|
|
684
|
+
| ((uint64_t)bytes[7] << 56);
|
|
624
685
|
|
|
625
686
|
return rb_float_new(transfer.f);
|
|
626
687
|
}
|
|
@@ -632,6 +693,10 @@ VALUE rb_thrift_compact_proto_read_string(VALUE self) {
|
|
|
632
693
|
|
|
633
694
|
VALUE rb_thrift_compact_proto_read_binary(VALUE self) {
|
|
634
695
|
uint32_t size = read_varint32(self);
|
|
696
|
+
if (RB_UNLIKELY(size > INT32_MAX)) {
|
|
697
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_SIZE_LIMIT), rb_str_new2("Binary size limit exceeded")));
|
|
698
|
+
}
|
|
699
|
+
CHECK_STRING_SIZE(self, size);
|
|
635
700
|
return rb_funcall(GET_TRANSPORT(self), read_all_method_id, 1, UINT2NUM(size));
|
|
636
701
|
}
|
|
637
702
|
|