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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 90306a751b8d883922c4556778391d56c8c48fbf008187d3edfe411db4e9f6f7
|
|
4
|
+
data.tar.gz: 95287ba8714521389775a7d2ad265b3ad60a3ca44ada102abcf0c2ee152347cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7e052575e5b7e581440a9073d2f4c6ce828b79963f7ce5c077f77e7c759b3589d5671a9e6f37ff4df996061af6b77362cc6248c7d22ac414156594b3fd77339
|
|
7
|
+
data.tar.gz: 35f5ee1d30099e5c70fa49d420153442e2b0b97587a908dea86ad1f9a2bbc44df5ff1baa3474cbc48f4064e20571eab7aa00c5fb155202f05edcd17579cbaddf
|
data/README.md
CHANGED
|
@@ -47,49 +47,55 @@ clients and services.
|
|
|
47
47
|
The Ruby library does not include the Thrift compiler. Use a compiler built
|
|
48
48
|
from the root of this repository to generate Ruby bindings:
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
```bash
|
|
51
|
+
thrift --gen rb path/to/service.thrift
|
|
52
|
+
# with namespaced modules
|
|
53
|
+
thrift --gen rb:namespaced --recurse path/to/service.thrift
|
|
54
|
+
```
|
|
53
55
|
|
|
54
56
|
Generated files are typically written to `gen-rb/` and can be required
|
|
55
57
|
directly from your application.
|
|
56
58
|
|
|
57
59
|
## Basic Client Usage
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
```ruby
|
|
62
|
+
$:.push File.expand_path('gen-rb', __dir__)
|
|
63
|
+
require 'thrift'
|
|
64
|
+
require 'calculator'
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
socket = Thrift::Socket.new('localhost', 9090)
|
|
67
|
+
transport = Thrift::BufferedTransport.new(socket)
|
|
68
|
+
protocol = Thrift::BinaryProtocol.new(transport)
|
|
69
|
+
client = Calculator::Client.new(protocol)
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
transport.open
|
|
72
|
+
puts client.add(1, 1)
|
|
73
|
+
transport.close
|
|
74
|
+
```
|
|
71
75
|
|
|
72
76
|
## Basic Server Usage
|
|
73
77
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
```ruby
|
|
79
|
+
$:.push File.expand_path('gen-rb', __dir__)
|
|
80
|
+
require 'thrift'
|
|
81
|
+
require 'calculator'
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
class CalculatorHandler
|
|
84
|
+
def add(a, b)
|
|
85
|
+
a + b
|
|
86
|
+
end
|
|
87
|
+
end
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
handler = CalculatorHandler.new
|
|
90
|
+
processor = Calculator::Processor.new(handler)
|
|
91
|
+
server_transport = Thrift::ServerSocket.new(9090)
|
|
92
|
+
transport_factory = Thrift::BufferedTransportFactory.new
|
|
93
|
+
protocol_factory = Thrift::BinaryProtocolFactory.new
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
server = Thrift::ThreadedServer.new(processor, server_transport,
|
|
96
|
+
transport_factory, protocol_factory)
|
|
97
|
+
server.serve
|
|
98
|
+
```
|
|
93
99
|
|
|
94
100
|
## Development and Tests
|
|
95
101
|
|
|
@@ -111,6 +117,52 @@ directly from your application.
|
|
|
111
117
|
|
|
112
118
|
## Breaking Changes
|
|
113
119
|
|
|
120
|
+
### 0.24.0
|
|
121
|
+
|
|
122
|
+
Connect timeout handling changed for both `Thrift::Socket` and
|
|
123
|
+
`Thrift::SSLSocket`.
|
|
124
|
+
|
|
125
|
+
- `timeout == nil` and `timeout == 0` now use blocking connect/open semantics.
|
|
126
|
+
Older releases already treated `nil` that way, but treated `0` differently
|
|
127
|
+
across operations: `read` and `write` used the blocking path, plain TCP
|
|
128
|
+
`open` used a zero-length poll, and TLS `open` could spin in the handshake
|
|
129
|
+
retry loop.
|
|
130
|
+
- Positive timeouts now bound the whole connect/open operation instead of
|
|
131
|
+
effectively applying a fresh timeout window at each wait or address attempt.
|
|
132
|
+
For plain TCP this budget is shared across address fallback. For TLS it is
|
|
133
|
+
shared across the TCP connect and the SSL handshake.
|
|
134
|
+
- Connect/open timeout expiry now raises
|
|
135
|
+
`Thrift::TransportException::TIMED_OUT`. Older releases could report the same
|
|
136
|
+
condition as `NOT_OPEN`, and `Thrift::SSLSocket` could keep retrying the
|
|
137
|
+
handshake after the wait timed out.
|
|
138
|
+
|
|
139
|
+
If your application matched `NOT_OPEN` for connect timeout handling, update it
|
|
140
|
+
to handle `TIMED_OUT`. If you relied on `timeout = 0` meaning immediate failure
|
|
141
|
+
or on repeated retries extending the effective timeout during TCP fallback or
|
|
142
|
+
TLS handshake, update those call paths before upgrading.
|
|
143
|
+
|
|
144
|
+
Ruby server socket transports now apply a 5-second timeout to accepted client
|
|
145
|
+
sockets by default. This prevents stalled clients from blocking server threads
|
|
146
|
+
indefinitely during response writes. Applications that intentionally require
|
|
147
|
+
blocking accepted sockets can pass `client_timeout: nil` or `client_timeout: 0`
|
|
148
|
+
when constructing `Thrift::ServerSocket`, `Thrift::SSLServerSocket`, or
|
|
149
|
+
`Thrift::UNIXServerSocket`.
|
|
150
|
+
|
|
151
|
+
Generated Ruby structs and unions now suffix field ID constants as
|
|
152
|
+
`*_FIELD_ID` instead of exposing bare uppercased field names. For example,
|
|
153
|
+
`MyStruct::FOO` becomes `MyStruct::FOO_FIELD_ID`. This avoids collisions with
|
|
154
|
+
the generated `FIELDS` metadata hash for field names such as `fields`, but it
|
|
155
|
+
is a source-compatible break if your application referenced the old constants
|
|
156
|
+
directly. Regenerate Ruby code and update those constant references atomically.
|
|
157
|
+
|
|
158
|
+
Ruby binary protocol writers now enforce signed Thrift integer ranges before
|
|
159
|
+
serializing values. `byte`, `i16`, `i32`, and `i64` writes reject values outside
|
|
160
|
+
their declared signed ranges, and binary/string/container sizes must fit in a
|
|
161
|
+
non-negative signed `i32` length. Older releases could silently wrap or clip
|
|
162
|
+
some out-of-range values, such as writing `255` as a byte that read back as
|
|
163
|
+
`-1`. This applies to both `Thrift::BinaryProtocol` and
|
|
164
|
+
`Thrift::BinaryProtocolAccelerated`.
|
|
165
|
+
|
|
114
166
|
### 0.23.0
|
|
115
167
|
|
|
116
168
|
The documented source-build flow now effectively requires Ruby `2.7+`.
|
|
@@ -157,14 +209,22 @@ best-effort, not guaranteed.
|
|
|
157
209
|
`thrift --gen rb` and namespaced output from `thrift --gen rb:namespaced`
|
|
158
210
|
use different require paths, so switch them atomically with regenerated code.
|
|
159
211
|
|
|
160
|
-
|
|
161
|
-
|
|
212
|
+
```ruby
|
|
213
|
+
# --gen rb
|
|
214
|
+
require 'calculator'
|
|
162
215
|
|
|
163
|
-
|
|
164
|
-
|
|
216
|
+
# --gen rb:namespaced
|
|
217
|
+
require 'my_namespace/calculator'
|
|
218
|
+
```
|
|
165
219
|
|
|
166
220
|
## Migration Notes
|
|
167
221
|
|
|
222
|
+
- If you upgrade to `0.24.0`, treat `timeout` on `Thrift::Socket` and
|
|
223
|
+
`Thrift::SSLSocket` as one budget for the whole open path. For
|
|
224
|
+
`Thrift::SSLSocket`, that includes both the TCP connect and the TLS
|
|
225
|
+
handshake.
|
|
226
|
+
- If you upgrade to `0.24.0`, handle connect/open timeout expiry as
|
|
227
|
+
`Thrift::TransportException::TIMED_OUT` instead of `NOT_OPEN`.
|
|
168
228
|
- If you upgrade across the stricter reply-validation changes, regenerate all
|
|
169
229
|
Ruby stubs and deploy them with the matching Ruby runtime. Do not mix old
|
|
170
230
|
generated code, new generated code, and new runtime code on the same client
|
data/benchmark/benchmark.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
|
|
@@ -116,7 +117,7 @@ class BenchmarkManager
|
|
|
116
117
|
def collect_output
|
|
117
118
|
puts "Collecting output..."
|
|
118
119
|
# read from @pool until all sockets are closed
|
|
119
|
-
@buffers = Hash.new { |h, k| h[k] = '' }
|
|
120
|
+
@buffers = Hash.new { |h, k| h[k] = ''.b }
|
|
120
121
|
until @pool.empty?
|
|
121
122
|
rd, = select(@pool)
|
|
122
123
|
next if rd.nil?
|
data/benchmark/client.rb
CHANGED
data/benchmark/server.rb
CHANGED
data/benchmark/thin_server.rb
CHANGED
|
@@ -31,13 +31,59 @@ VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
|
|
|
31
31
|
return Qtrue;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
static int VERSION_1;
|
|
37
35
|
static int VERSION_MASK;
|
|
38
36
|
static int TYPE_MASK;
|
|
39
37
|
static ID rbuf_ivar_id;
|
|
40
38
|
|
|
39
|
+
static int64_t checked_integer_value(VALUE value) {
|
|
40
|
+
if (!RB_INTEGER_TYPE_P(value)) {
|
|
41
|
+
rb_raise(rb_eTypeError, "integer argument expected");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return NUM2LL(value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static int64_t checked_integer_range(VALUE value, int64_t min, int64_t max) {
|
|
48
|
+
int64_t integer = checked_integer_value(value);
|
|
49
|
+
|
|
50
|
+
if (integer < min || integer > max) {
|
|
51
|
+
rb_raise(rb_eRangeError, "integer out of bounds");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return integer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static int8_t checked_byte_value(VALUE value) {
|
|
58
|
+
return (int8_t)checked_integer_range(value, INT8_MIN, INT8_MAX);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static int16_t checked_i16_value(VALUE value) {
|
|
62
|
+
return (int16_t)checked_integer_range(value, INT16_MIN, INT16_MAX);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static int32_t checked_i32_value(VALUE value) {
|
|
66
|
+
return (int32_t)checked_integer_range(value, INT32_MIN, INT32_MAX);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static int32_t checked_size_value(VALUE value) {
|
|
70
|
+
return (int32_t)checked_integer_range(value, 0, INT32_MAX);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static int64_t checked_i64_value(VALUE value) {
|
|
74
|
+
return checked_integer_range(value, INT64_MIN, INT64_MAX);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static int32_t checked_string_length(VALUE str) {
|
|
78
|
+
long length = RSTRING_LEN(str);
|
|
79
|
+
|
|
80
|
+
if (length > INT32_MAX) {
|
|
81
|
+
rb_raise(rb_eRangeError, "string too long");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (int32_t)length;
|
|
85
|
+
}
|
|
86
|
+
|
|
41
87
|
static void write_byte_direct(VALUE trans, int8_t b) {
|
|
42
88
|
WRITE(trans, (char*)&b, 1);
|
|
43
89
|
}
|
|
@@ -83,7 +129,7 @@ static void write_string_direct(VALUE trans, VALUE str) {
|
|
|
83
129
|
rb_raise(rb_eStandardError, "Value should be a string");
|
|
84
130
|
}
|
|
85
131
|
str = convert_to_utf8_byte_buffer(str);
|
|
86
|
-
write_i32_direct(trans, (
|
|
132
|
+
write_i32_direct(trans, checked_string_length(str));
|
|
87
133
|
rb_funcall(trans, write_method_id, 1, str);
|
|
88
134
|
}
|
|
89
135
|
|
|
@@ -124,13 +170,14 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
|
|
|
124
170
|
VALUE strict_write = GET_STRICT_WRITE(self);
|
|
125
171
|
|
|
126
172
|
if (strict_write == Qtrue) {
|
|
127
|
-
|
|
173
|
+
int8_t message_type = checked_byte_value(type);
|
|
174
|
+
write_i32_direct(trans, VERSION_1 | message_type);
|
|
128
175
|
write_string_direct(trans, name);
|
|
129
|
-
write_i32_direct(trans,
|
|
176
|
+
write_i32_direct(trans, checked_i32_value(seqid));
|
|
130
177
|
} else {
|
|
131
178
|
write_string_direct(trans, name);
|
|
132
|
-
write_byte_direct(trans,
|
|
133
|
-
write_i32_direct(trans,
|
|
179
|
+
write_byte_direct(trans, checked_byte_value(type));
|
|
180
|
+
write_i32_direct(trans, checked_i32_value(seqid));
|
|
134
181
|
}
|
|
135
182
|
|
|
136
183
|
return Qnil;
|
|
@@ -138,8 +185,8 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
|
|
|
138
185
|
|
|
139
186
|
VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
|
|
140
187
|
VALUE trans = GET_TRANSPORT(self);
|
|
141
|
-
write_byte_direct(trans,
|
|
142
|
-
write_i16_direct(trans,
|
|
188
|
+
write_byte_direct(trans, checked_byte_value(type));
|
|
189
|
+
write_i16_direct(trans, checked_i16_value(id));
|
|
143
190
|
|
|
144
191
|
return Qnil;
|
|
145
192
|
}
|
|
@@ -151,17 +198,17 @@ VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) {
|
|
|
151
198
|
|
|
152
199
|
VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) {
|
|
153
200
|
VALUE trans = GET_TRANSPORT(self);
|
|
154
|
-
write_byte_direct(trans,
|
|
155
|
-
write_byte_direct(trans,
|
|
156
|
-
write_i32_direct(trans,
|
|
201
|
+
write_byte_direct(trans, checked_byte_value(ktype));
|
|
202
|
+
write_byte_direct(trans, checked_byte_value(vtype));
|
|
203
|
+
write_i32_direct(trans, checked_size_value(size));
|
|
157
204
|
|
|
158
205
|
return Qnil;
|
|
159
206
|
}
|
|
160
207
|
|
|
161
208
|
VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) {
|
|
162
209
|
VALUE trans = GET_TRANSPORT(self);
|
|
163
|
-
write_byte_direct(trans,
|
|
164
|
-
write_i32_direct(trans,
|
|
210
|
+
write_byte_direct(trans, checked_byte_value(etype));
|
|
211
|
+
write_i32_direct(trans, checked_size_value(size));
|
|
165
212
|
|
|
166
213
|
return Qnil;
|
|
167
214
|
}
|
|
@@ -178,25 +225,25 @@ VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) {
|
|
|
178
225
|
|
|
179
226
|
VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) {
|
|
180
227
|
CHECK_NIL(byte);
|
|
181
|
-
write_byte_direct(GET_TRANSPORT(self),
|
|
228
|
+
write_byte_direct(GET_TRANSPORT(self), checked_byte_value(byte));
|
|
182
229
|
return Qnil;
|
|
183
230
|
}
|
|
184
231
|
|
|
185
232
|
VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) {
|
|
186
233
|
CHECK_NIL(i16);
|
|
187
|
-
write_i16_direct(GET_TRANSPORT(self),
|
|
234
|
+
write_i16_direct(GET_TRANSPORT(self), checked_i16_value(i16));
|
|
188
235
|
return Qnil;
|
|
189
236
|
}
|
|
190
237
|
|
|
191
238
|
VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) {
|
|
192
239
|
CHECK_NIL(i32);
|
|
193
|
-
write_i32_direct(GET_TRANSPORT(self),
|
|
240
|
+
write_i32_direct(GET_TRANSPORT(self), checked_i32_value(i32));
|
|
194
241
|
return Qnil;
|
|
195
242
|
}
|
|
196
243
|
|
|
197
244
|
VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) {
|
|
198
245
|
CHECK_NIL(i64);
|
|
199
|
-
write_i64_direct(GET_TRANSPORT(self),
|
|
246
|
+
write_i64_direct(GET_TRANSPORT(self), checked_i64_value(i64));
|
|
200
247
|
return Qnil;
|
|
201
248
|
}
|
|
202
249
|
|
|
@@ -224,7 +271,7 @@ VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) {
|
|
|
224
271
|
CHECK_NIL(buf);
|
|
225
272
|
VALUE trans = GET_TRANSPORT(self);
|
|
226
273
|
buf = force_binary_encoding(buf);
|
|
227
|
-
write_i32_direct(trans, (
|
|
274
|
+
write_i32_direct(trans, checked_string_length(buf));
|
|
228
275
|
rb_funcall(trans, write_method_id, 1, buf);
|
|
229
276
|
return Qnil;
|
|
230
277
|
}
|
|
@@ -377,17 +424,24 @@ VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) {
|
|
|
377
424
|
}
|
|
378
425
|
}
|
|
379
426
|
|
|
427
|
+
#define CHECK_NEGATIVE_SIZE(size) \
|
|
428
|
+
if (RB_UNLIKELY((size) < 0)) { \
|
|
429
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_NEGATIVE_SIZE), rb_str_new2("Negative size"))); \
|
|
430
|
+
}
|
|
431
|
+
|
|
380
432
|
VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) {
|
|
381
433
|
VALUE ktype = rb_thrift_binary_proto_read_byte(self);
|
|
382
434
|
VALUE vtype = rb_thrift_binary_proto_read_byte(self);
|
|
383
|
-
|
|
384
|
-
|
|
435
|
+
int size = read_i32_direct(self);
|
|
436
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
437
|
+
return rb_ary_new3(3, ktype, vtype, INT2NUM(size));
|
|
385
438
|
}
|
|
386
439
|
|
|
387
440
|
VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) {
|
|
388
441
|
VALUE etype = rb_thrift_binary_proto_read_byte(self);
|
|
389
|
-
|
|
390
|
-
|
|
442
|
+
int size = read_i32_direct(self);
|
|
443
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
444
|
+
return rb_ary_new3(2, etype, INT2NUM(size));
|
|
391
445
|
}
|
|
392
446
|
|
|
393
447
|
VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) {
|
|
@@ -431,6 +485,7 @@ VALUE rb_thrift_binary_proto_read_string(VALUE self) {
|
|
|
431
485
|
|
|
432
486
|
VALUE rb_thrift_binary_proto_read_binary(VALUE self) {
|
|
433
487
|
int size = read_i32_direct(self);
|
|
488
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
434
489
|
return READ(self, size);
|
|
435
490
|
}
|
|
436
491
|
|
data/ext/bytes.c
CHANGED
|
@@ -24,6 +24,20 @@
|
|
|
24
24
|
#include <constants.h>
|
|
25
25
|
|
|
26
26
|
VALUE force_binary_encoding(VALUE buffer) {
|
|
27
|
+
if (RB_TYPE_P(buffer, T_STRING)) {
|
|
28
|
+
if (rb_enc_get_index(buffer) == rb_ascii8bit_encindex()) {
|
|
29
|
+
return buffer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (RB_OBJ_FROZEN(buffer)) {
|
|
33
|
+
buffer = rb_obj_dup(buffer);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
rb_enc_associate_index(buffer, rb_ascii8bit_encindex());
|
|
37
|
+
|
|
38
|
+
return buffer;
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
return rb_funcall(thrift_bytes_module, force_binary_encoding_id, 1, buffer);
|
|
28
42
|
}
|
|
29
43
|
|
data/ext/compact_protocol.c
CHANGED
|
@@ -124,21 +124,29 @@ static void write_field_begin_internal(VALUE self, VALUE type, VALUE id_value, V
|
|
|
124
124
|
SET_LAST_ID(self, id_value);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
static
|
|
128
|
-
return (n << 1) ^ (n
|
|
127
|
+
static uint32_t int_to_zig_zag(int32_t n) {
|
|
128
|
+
return (((uint32_t)n) << 1) ^ (0U - (uint32_t)(n < 0));
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
static uint64_t ll_to_zig_zag(int64_t n) {
|
|
132
|
-
return (n << 1) ^ (n
|
|
132
|
+
return (((uint64_t)n) << 1) ^ (0ULL - (uint64_t)(n < 0));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static uint32_t message_seqid_to_varint32(int32_t seqid) {
|
|
136
|
+
return seqid < 0 ? (uint32_t)((int64_t)seqid + (INT64_C(1) << 32)) : (uint32_t)seqid;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static int32_t message_seqid_from_varint32(uint32_t seqid) {
|
|
140
|
+
return seqid > INT32_MAX ? (int32_t)((int64_t)seqid - (INT64_C(1) << 32)) : (int32_t)seqid;
|
|
133
141
|
}
|
|
134
142
|
|
|
135
143
|
static void write_varint32(VALUE transport, uint32_t n) {
|
|
136
144
|
while (true) {
|
|
137
|
-
if ((n & ~
|
|
138
|
-
write_byte_direct(transport, n &
|
|
145
|
+
if ((n & ~0x7FU) == 0U) {
|
|
146
|
+
write_byte_direct(transport, n & 0x7FU);
|
|
139
147
|
break;
|
|
140
148
|
} else {
|
|
141
|
-
write_byte_direct(transport, (n &
|
|
149
|
+
write_byte_direct(transport, (n & 0x7FU) | 0x80U);
|
|
142
150
|
n = n >> 7;
|
|
143
151
|
}
|
|
144
152
|
}
|
|
@@ -146,11 +154,11 @@ static void write_varint32(VALUE transport, uint32_t n) {
|
|
|
146
154
|
|
|
147
155
|
static void write_varint64(VALUE transport, uint64_t n) {
|
|
148
156
|
while (true) {
|
|
149
|
-
if ((n & ~
|
|
150
|
-
write_byte_direct(transport, n &
|
|
157
|
+
if ((n & ~0x7FULL) == 0ULL) {
|
|
158
|
+
write_byte_direct(transport, n & 0x7FULL);
|
|
151
159
|
break;
|
|
152
160
|
} else {
|
|
153
|
-
write_byte_direct(transport, (n &
|
|
161
|
+
write_byte_direct(transport, (n & 0x7FULL) | 0x80ULL);
|
|
154
162
|
n = n >> 7;
|
|
155
163
|
}
|
|
156
164
|
}
|
|
@@ -208,9 +216,10 @@ VALUE rb_thrift_compact_proto_write_set_end(VALUE self) {
|
|
|
208
216
|
|
|
209
217
|
VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) {
|
|
210
218
|
VALUE transport = GET_TRANSPORT(self);
|
|
219
|
+
int32_t seqid_value = FIX2INT(seqid);
|
|
211
220
|
write_byte_direct(transport, PROTOCOL_ID);
|
|
212
221
|
write_byte_direct(transport, (VERSION & VERSION_MASK) | ((FIX2INT(type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
|
|
213
|
-
write_varint32(transport,
|
|
222
|
+
write_varint32(transport, message_seqid_to_varint32(seqid_value));
|
|
214
223
|
rb_thrift_compact_proto_write_string(self, name);
|
|
215
224
|
|
|
216
225
|
return Qnil;
|
|
@@ -419,30 +428,49 @@ static char read_byte_direct(VALUE self) {
|
|
|
419
428
|
return (char)(FIX2INT(byte));
|
|
420
429
|
}
|
|
421
430
|
|
|
422
|
-
static int64_t zig_zag_to_ll(
|
|
423
|
-
return (((
|
|
431
|
+
static int64_t zig_zag_to_ll(uint64_t n) {
|
|
432
|
+
return (int64_t)((n >> 1) ^ (0ULL - (n & 1ULL)));
|
|
424
433
|
}
|
|
425
434
|
|
|
426
|
-
static int32_t zig_zag_to_int(
|
|
427
|
-
return (((
|
|
435
|
+
static int32_t zig_zag_to_int(uint32_t n) {
|
|
436
|
+
return (int32_t)((n >> 1) ^ (0U - (n & 1U)));
|
|
428
437
|
}
|
|
429
438
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
439
|
+
#define MAX_VARINT32_BYTES 5 /* ceil(32/7); matches protobuf wire format */
|
|
440
|
+
#define MAX_VARINT64_BYTES 10 /* ceil(64/7); matches protobuf wire format */
|
|
441
|
+
|
|
442
|
+
static uint64_t read_varint64(VALUE self) {
|
|
443
|
+
int i, shift = 0;
|
|
444
|
+
uint64_t result = 0;
|
|
445
|
+
for (i = 0; i < MAX_VARINT64_BYTES; i++) {
|
|
434
446
|
int8_t b = read_byte_direct(self);
|
|
435
|
-
result
|
|
447
|
+
result |= ((uint64_t)(b & 0x7f) << shift);
|
|
436
448
|
if ((b & 0x80) != 0x80) {
|
|
437
|
-
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
shift += 7;
|
|
452
|
+
}
|
|
453
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Variable-length int over 10 bytes.")));
|
|
454
|
+
return 0; /* unreachable */
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
static uint32_t read_varint32(VALUE self) {
|
|
458
|
+
int i, shift = 0;
|
|
459
|
+
uint32_t result = 0;
|
|
460
|
+
for (i = 0; i < MAX_VARINT32_BYTES; i++) {
|
|
461
|
+
int8_t b = read_byte_direct(self);
|
|
462
|
+
result |= ((uint32_t)(b & 0x7f) << shift);
|
|
463
|
+
if ((b & 0x80) != 0x80) {
|
|
464
|
+
return result;
|
|
438
465
|
}
|
|
439
466
|
shift += 7;
|
|
440
467
|
}
|
|
441
|
-
|
|
468
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Variable-length int over 5 bytes.")));
|
|
469
|
+
return 0; /* unreachable */
|
|
442
470
|
}
|
|
443
471
|
|
|
444
472
|
static int16_t read_i16(VALUE self) {
|
|
445
|
-
return zig_zag_to_int((
|
|
473
|
+
return (int16_t)zig_zag_to_int(read_varint32(self));
|
|
446
474
|
}
|
|
447
475
|
|
|
448
476
|
VALUE rb_thrift_compact_proto_read_message_end(VALUE self) {
|
|
@@ -494,7 +522,7 @@ VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) {
|
|
|
494
522
|
}
|
|
495
523
|
|
|
496
524
|
int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS;
|
|
497
|
-
int32_t seqid = (
|
|
525
|
+
int32_t seqid = message_seqid_from_varint32(read_varint32(self));
|
|
498
526
|
VALUE messageName = rb_thrift_compact_proto_read_string(self);
|
|
499
527
|
return rb_ary_new3(3, messageName, INT2FIX(type), INT2NUM(seqid));
|
|
500
528
|
}
|
|
@@ -532,19 +560,19 @@ VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) {
|
|
|
532
560
|
}
|
|
533
561
|
|
|
534
562
|
VALUE rb_thrift_compact_proto_read_map_begin(VALUE self) {
|
|
535
|
-
|
|
563
|
+
uint32_t size = read_varint32(self);
|
|
536
564
|
uint8_t key_and_value_type = size == 0 ? 0 : read_byte_direct(self);
|
|
537
|
-
return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)),
|
|
565
|
+
return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)), UINT2NUM(size));
|
|
538
566
|
}
|
|
539
567
|
|
|
540
568
|
VALUE rb_thrift_compact_proto_read_list_begin(VALUE self) {
|
|
541
569
|
uint8_t size_and_type = read_byte_direct(self);
|
|
542
|
-
|
|
570
|
+
uint32_t size = (size_and_type >> 4) & 0x0f;
|
|
543
571
|
if (size == 15) {
|
|
544
|
-
size = (
|
|
572
|
+
size = read_varint32(self);
|
|
545
573
|
}
|
|
546
574
|
uint8_t type = get_ttype(size_and_type & 0x0f);
|
|
547
|
-
return rb_ary_new3(2, INT2FIX(type),
|
|
575
|
+
return rb_ary_new3(2, INT2FIX(type), UINT2NUM(size));
|
|
548
576
|
}
|
|
549
577
|
|
|
550
578
|
VALUE rb_thrift_compact_proto_read_set_begin(VALUE self) {
|
|
@@ -570,7 +598,7 @@ VALUE rb_thrift_compact_proto_read_i16(VALUE self) {
|
|
|
570
598
|
}
|
|
571
599
|
|
|
572
600
|
VALUE rb_thrift_compact_proto_read_i32(VALUE self) {
|
|
573
|
-
return INT2NUM(zig_zag_to_int((
|
|
601
|
+
return INT2NUM(zig_zag_to_int(read_varint32(self)));
|
|
574
602
|
}
|
|
575
603
|
|
|
576
604
|
VALUE rb_thrift_compact_proto_read_i64(VALUE self) {
|
|
@@ -603,8 +631,8 @@ VALUE rb_thrift_compact_proto_read_string(VALUE self) {
|
|
|
603
631
|
}
|
|
604
632
|
|
|
605
633
|
VALUE rb_thrift_compact_proto_read_binary(VALUE self) {
|
|
606
|
-
|
|
607
|
-
return
|
|
634
|
+
uint32_t size = read_varint32(self);
|
|
635
|
+
return rb_funcall(GET_TRANSPORT(self), read_all_method_id, 1, UINT2NUM(size));
|
|
608
636
|
}
|
|
609
637
|
|
|
610
638
|
VALUE rb_thrift_compact_proto_read_uuid(VALUE self) {
|
data/ext/extconf.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
|
|
@@ -24,6 +25,13 @@ else
|
|
|
24
25
|
|
|
25
26
|
append_cflags(["-fsigned-char", "-g", "-O2", "-Wall", "-Werror", "-Werror=old-style-definition"])
|
|
26
27
|
|
|
28
|
+
# clang 21+ introduced -Wdefault-const-init-field-unsafe, which fires on
|
|
29
|
+
# Ruby 3.2's rstring.h (struct RString has a const field via RBasic).
|
|
30
|
+
# This is a Ruby header issue, not a Thrift bug, so suppress the warning here.
|
|
31
|
+
# append_cflags silently ignores flags unsupported by the compiler, so this
|
|
32
|
+
# is safe across all clang versions.
|
|
33
|
+
append_cflags("-Wno-default-const-init-field-unsafe")
|
|
34
|
+
|
|
27
35
|
# Makes all symbols private by default to avoid unintended conflict
|
|
28
36
|
# with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
|
|
29
37
|
# selectively, or entirely remove this flag.
|