thrift 0.23.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 +203 -40
- data/ext/binary_protocol_accelerated.c +130 -40
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +184 -91
- data/ext/constants.h +3 -0
- data/ext/extconf.rb +12 -4
- data/ext/macros.h +11 -0
- data/ext/memory_buffer.c +67 -12
- data/ext/struct.c +192 -71
- data/ext/thrift_native.c +7 -0
- data/lib/thrift/bytes.rb +6 -3
- data/lib/thrift/client.rb +31 -33
- data/lib/thrift/exceptions.rb +11 -8
- data/lib/thrift/multiplexed_processor.rb +17 -8
- data/lib/thrift/processor.rb +25 -3
- data/lib/thrift/protocol/base_protocol.rb +66 -31
- data/lib/thrift/protocol/binary_protocol.rb +80 -37
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +7 -2
- data/lib/thrift/protocol/compact_protocol.rb +204 -88
- data/lib/thrift/protocol/header_protocol.rb +15 -3
- data/lib/thrift/protocol/json_protocol.rb +158 -109
- data/lib/thrift/protocol/multiplexed_protocol.rb +3 -3
- data/lib/thrift/protocol/protocol_decorator.rb +6 -2
- data/lib/thrift/serializer/deserializer.rb +1 -0
- data/lib/thrift/serializer/serializer.rb +7 -0
- data/lib/thrift/server/base_server.rb +11 -2
- data/lib/thrift/server/nonblocking_server.rb +69 -20
- data/lib/thrift/server/rack_application.rb +69 -0
- data/lib/thrift/server/simple_server.rb +27 -15
- data/lib/thrift/server/thin_http_server.rb +21 -44
- data/lib/thrift/server/thread_pool_server.rb +21 -17
- data/lib/thrift/server/threaded_server.rb +22 -18
- data/lib/thrift/struct.rb +34 -18
- data/lib/thrift/struct_union.rb +37 -36
- 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 +26 -4
- data/lib/thrift/transport/buffered_transport.rb +5 -4
- data/lib/thrift/transport/framed_transport.rb +33 -7
- data/lib/thrift/transport/header_transport.rb +159 -33
- data/lib/thrift/transport/http_client_transport.rb +28 -14
- data/lib/thrift/transport/io_stream_transport.rb +3 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +14 -9
- data/lib/thrift/transport/server_socket.rb +10 -8
- data/lib/thrift/transport/socket.rb +85 -48
- data/lib/thrift/transport/ssl_server_socket.rb +67 -6
- data/lib/thrift/transport/ssl_socket.rb +73 -14
- data/lib/thrift/transport/unix_server_socket.rb +6 -2
- data/lib/thrift/transport/unix_socket.rb +5 -6
- data/lib/thrift/types.rb +23 -22
- data/lib/thrift/union.rb +21 -11
- data/lib/thrift/uuid.rb +9 -8
- data/lib/thrift.rb +40 -39
- metadata +7 -266
- data/benchmark/Benchmark.thrift +0 -24
- data/benchmark/benchmark.rb +0 -285
- data/benchmark/client.rb +0 -117
- data/benchmark/server.rb +0 -120
- data/benchmark/thin_server.rb +0 -45
- data/lib/thrift/server/mongrel_http_server.rb +0 -60
- 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 -187
- data/spec/base_protocol_spec.rb +0 -224
- data/spec/base_transport_spec.rb +0 -387
- data/spec/binary_protocol_accelerated_spec.rb +0 -46
- data/spec/binary_protocol_spec.rb +0 -72
- data/spec/binary_protocol_spec_shared.rb +0 -445
- data/spec/bytes_spec.rb +0 -99
- data/spec/client_spec.rb +0 -166
- data/spec/compact_protocol_spec.rb +0 -196
- data/spec/constants_demo_spec.rb +0 -101
- data/spec/exception_spec.rb +0 -140
- data/spec/flat_spec.rb +0 -62
- data/spec/header_protocol_spec.rb +0 -475
- data/spec/header_transport_spec.rb +0 -386
- data/spec/http_client_spec.rb +0 -159
- data/spec/json_protocol_spec.rb +0 -552
- data/spec/namespaced_spec.rb +0 -66
- data/spec/nonblocking_server_spec.rb +0 -361
- data/spec/processor_spec.rb +0 -79
- data/spec/serializer_spec.rb +0 -66
- data/spec/server_socket_spec.rb +0 -84
- data/spec/server_spec.rb +0 -186
- data/spec/socket_spec.rb +0 -67
- data/spec/socket_spec_shared.rb +0 -167
- data/spec/spec_helper.rb +0 -69
- data/spec/ssl_server_socket_spec.rb +0 -45
- data/spec/ssl_socket_spec.rb +0 -87
- data/spec/struct_nested_containers_spec.rb +0 -190
- data/spec/struct_spec.rb +0 -397
- data/spec/support/header_protocol_helper.rb +0 -54
- data/spec/thin_http_server_spec.rb +0 -126
- data/spec/types_spec.rb +0 -117
- data/spec/union_spec.rb +0 -272
- data/spec/unix_socket_spec.rb +0 -115
- data/spec/uuid_validation_spec.rb +0 -238
- data/test/fuzz/Makefile.am +0 -173
- data/test/fuzz/README.md +0 -149
- data/test/fuzz/fuzz_common.rb +0 -95
- data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_tracer.rb +0 -28
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,50 +151,61 @@ 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
|
-
static
|
|
128
|
-
return (n << 1) ^ (n
|
|
160
|
+
static uint32_t int_to_zig_zag(int32_t n) {
|
|
161
|
+
return (((uint32_t)n) << 1) ^ (0U - (uint32_t)(n < 0));
|
|
129
162
|
}
|
|
130
163
|
|
|
131
164
|
static uint64_t ll_to_zig_zag(int64_t n) {
|
|
132
|
-
return (n << 1) ^ (n
|
|
165
|
+
return (((uint64_t)n) << 1) ^ (0ULL - (uint64_t)(n < 0));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static uint32_t message_seqid_to_varint32(int32_t seqid) {
|
|
169
|
+
return seqid < 0 ? (uint32_t)((int64_t)seqid + (INT64_C(1) << 32)) : (uint32_t)seqid;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static int32_t message_seqid_from_varint32(uint32_t seqid) {
|
|
173
|
+
return seqid > INT32_MAX ? (int32_t)((int64_t)seqid - (INT64_C(1) << 32)) : (int32_t)seqid;
|
|
133
174
|
}
|
|
134
175
|
|
|
135
176
|
static void write_varint32(VALUE transport, uint32_t n) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
n = n >> 7;
|
|
143
|
-
}
|
|
177
|
+
unsigned char bytes[5];
|
|
178
|
+
long length = 0;
|
|
179
|
+
|
|
180
|
+
while ((n & ~0x7FU) != 0U) {
|
|
181
|
+
bytes[length++] = (n & 0x7FU) | 0x80U;
|
|
182
|
+
n >>= 7;
|
|
144
183
|
}
|
|
184
|
+
bytes[length++] = n;
|
|
185
|
+
|
|
186
|
+
WRITE(transport, (const char*)bytes, length);
|
|
145
187
|
}
|
|
146
188
|
|
|
147
189
|
static void write_varint64(VALUE transport, uint64_t n) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
n = n >> 7;
|
|
155
|
-
}
|
|
190
|
+
unsigned char bytes[10];
|
|
191
|
+
long length = 0;
|
|
192
|
+
|
|
193
|
+
while ((n & ~0x7FULL) != 0ULL) {
|
|
194
|
+
bytes[length++] = (n & 0x7FULL) | 0x80ULL;
|
|
195
|
+
n >>= 7;
|
|
156
196
|
}
|
|
197
|
+
bytes[length++] = n;
|
|
198
|
+
|
|
199
|
+
WRITE(transport, (const char*)bytes, length);
|
|
157
200
|
}
|
|
158
201
|
|
|
159
202
|
static void write_collection_begin(VALUE transport, VALUE elem_type, VALUE size_value) {
|
|
160
|
-
int size =
|
|
203
|
+
int size = checked_size_value(size_value);
|
|
204
|
+
int compact_type = get_compact_type(elem_type);
|
|
161
205
|
if (size <= 14) {
|
|
162
|
-
write_byte_direct(transport, size << 4 |
|
|
206
|
+
write_byte_direct(transport, size << 4 | compact_type);
|
|
163
207
|
} else {
|
|
164
|
-
write_byte_direct(transport, 0xf0 |
|
|
208
|
+
write_byte_direct(transport, 0xf0 | compact_type);
|
|
165
209
|
write_varint32(transport, size);
|
|
166
210
|
}
|
|
167
211
|
}
|
|
@@ -208,20 +252,23 @@ VALUE rb_thrift_compact_proto_write_set_end(VALUE self) {
|
|
|
208
252
|
|
|
209
253
|
VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) {
|
|
210
254
|
VALUE transport = GET_TRANSPORT(self);
|
|
255
|
+
uint32_t type_value = (uint32_t)FIX2INT(type);
|
|
256
|
+
int32_t seqid_value = checked_i32_value(seqid);
|
|
211
257
|
write_byte_direct(transport, PROTOCOL_ID);
|
|
212
|
-
write_byte_direct(transport, (VERSION & VERSION_MASK) | ((
|
|
213
|
-
write_varint32(transport,
|
|
258
|
+
write_byte_direct(transport, (VERSION & VERSION_MASK) | ((type_value << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
|
|
259
|
+
write_varint32(transport, message_seqid_to_varint32(seqid_value));
|
|
214
260
|
rb_thrift_compact_proto_write_string(self, name);
|
|
215
261
|
|
|
216
262
|
return Qnil;
|
|
217
263
|
}
|
|
218
264
|
|
|
219
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);
|
|
220
267
|
if (FIX2INT(type) == TTYPE_BOOL) {
|
|
221
268
|
// we want to possibly include the value, so we'll wait.
|
|
222
|
-
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)));
|
|
223
270
|
} else {
|
|
224
|
-
write_field_begin_internal(self, type,
|
|
271
|
+
write_field_begin_internal(self, type, field_id, 0);
|
|
225
272
|
}
|
|
226
273
|
|
|
227
274
|
return Qnil;
|
|
@@ -233,7 +280,7 @@ VALUE rb_thrift_compact_proto_write_field_stop(VALUE self) {
|
|
|
233
280
|
}
|
|
234
281
|
|
|
235
282
|
VALUE rb_thrift_compact_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size_value) {
|
|
236
|
-
int size =
|
|
283
|
+
int size = checked_size_value(size_value);
|
|
237
284
|
VALUE transport = GET_TRANSPORT(self);
|
|
238
285
|
if (size == 0) {
|
|
239
286
|
write_byte_direct(transport, 0);
|
|
@@ -255,39 +302,36 @@ VALUE rb_thrift_compact_proto_write_set_begin(VALUE self, VALUE etype, VALUE siz
|
|
|
255
302
|
}
|
|
256
303
|
|
|
257
304
|
VALUE rb_thrift_compact_proto_write_bool(VALUE self, VALUE b) {
|
|
258
|
-
int8_t type = b
|
|
305
|
+
int8_t type = RTEST(b) ? CTYPE_BOOLEAN_TRUE : CTYPE_BOOLEAN_FALSE;
|
|
259
306
|
VALUE boolean_field = rb_ivar_get(self, boolean_field_id);
|
|
260
307
|
if (NIL_P(boolean_field)) {
|
|
261
308
|
// we're not part of a field, so just write the value.
|
|
262
309
|
write_byte_direct(GET_TRANSPORT(self), type);
|
|
263
310
|
} else {
|
|
264
311
|
// we haven't written the field header yet
|
|
265
|
-
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);
|
|
266
313
|
rb_ivar_set(self, boolean_field_id, Qnil);
|
|
267
314
|
}
|
|
268
315
|
return Qnil;
|
|
269
316
|
}
|
|
270
317
|
|
|
271
318
|
VALUE rb_thrift_compact_proto_write_byte(VALUE self, VALUE byte) {
|
|
272
|
-
|
|
273
|
-
write_byte_direct(GET_TRANSPORT(self), FIX2INT(byte));
|
|
319
|
+
write_byte_direct(GET_TRANSPORT(self), checked_byte_value(byte));
|
|
274
320
|
return Qnil;
|
|
275
321
|
}
|
|
276
322
|
|
|
277
323
|
VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16) {
|
|
278
|
-
|
|
324
|
+
write_varint32(GET_TRANSPORT(self), int_to_zig_zag(checked_i16_value(i16)));
|
|
279
325
|
return Qnil;
|
|
280
326
|
}
|
|
281
327
|
|
|
282
328
|
VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32) {
|
|
283
|
-
|
|
284
|
-
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)));
|
|
285
330
|
return Qnil;
|
|
286
331
|
}
|
|
287
332
|
|
|
288
333
|
VALUE rb_thrift_compact_proto_write_i64(VALUE self, VALUE i64) {
|
|
289
|
-
|
|
290
|
-
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)));
|
|
291
335
|
return Qnil;
|
|
292
336
|
}
|
|
293
337
|
|
|
@@ -321,8 +365,12 @@ VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str) {
|
|
|
321
365
|
VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf) {
|
|
322
366
|
buf = force_binary_encoding(buf);
|
|
323
367
|
VALUE transport = GET_TRANSPORT(self);
|
|
324
|
-
|
|
325
|
-
|
|
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);
|
|
326
374
|
return Qnil;
|
|
327
375
|
}
|
|
328
376
|
|
|
@@ -407,10 +455,20 @@ static int8_t get_ttype(int8_t ctype) {
|
|
|
407
455
|
} else if (ctype == CTYPE_UUID) {
|
|
408
456
|
return TTYPE_UUID;
|
|
409
457
|
} else {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
+
));
|
|
414
472
|
}
|
|
415
473
|
}
|
|
416
474
|
|
|
@@ -419,30 +477,57 @@ static char read_byte_direct(VALUE self) {
|
|
|
419
477
|
return (char)(FIX2INT(byte));
|
|
420
478
|
}
|
|
421
479
|
|
|
422
|
-
static int64_t zig_zag_to_ll(
|
|
423
|
-
return (((
|
|
480
|
+
static int64_t zig_zag_to_ll(uint64_t n) {
|
|
481
|
+
return (int64_t)((n >> 1) ^ (0ULL - (n & 1ULL)));
|
|
424
482
|
}
|
|
425
483
|
|
|
426
|
-
static int32_t zig_zag_to_int(
|
|
427
|
-
return (((
|
|
484
|
+
static int32_t zig_zag_to_int(uint32_t n) {
|
|
485
|
+
return (int32_t)((n >> 1) ^ (0U - (n & 1U)));
|
|
428
486
|
}
|
|
429
487
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
488
|
+
#define MAX_VARINT32_BYTES 5 /* ceil(32/7); matches protobuf wire format */
|
|
489
|
+
#define MAX_VARINT32_LAST_BYTE 0x0f
|
|
490
|
+
#define MAX_VARINT64_BYTES 10 /* ceil(64/7); matches protobuf wire format */
|
|
491
|
+
|
|
492
|
+
static uint64_t read_varint64(VALUE self) {
|
|
493
|
+
int i, shift = 0;
|
|
494
|
+
uint64_t result = 0;
|
|
495
|
+
for (i = 0; i < MAX_VARINT64_BYTES; i++) {
|
|
434
496
|
int8_t b = read_byte_direct(self);
|
|
435
|
-
result
|
|
497
|
+
result |= ((uint64_t)(b & 0x7f) << shift);
|
|
436
498
|
if ((b & 0x80) != 0x80) {
|
|
437
|
-
|
|
499
|
+
return result;
|
|
438
500
|
}
|
|
439
501
|
shift += 7;
|
|
440
502
|
}
|
|
441
|
-
|
|
503
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Variable-length int over 10 bytes.")));
|
|
504
|
+
return 0; /* unreachable */
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
static uint32_t read_varint32(VALUE self) {
|
|
508
|
+
int i, shift = 0;
|
|
509
|
+
uint32_t result = 0;
|
|
510
|
+
for (i = 0; i < MAX_VARINT32_BYTES - 1; i++) {
|
|
511
|
+
int8_t b = read_byte_direct(self);
|
|
512
|
+
result |= ((uint32_t)(b & 0x7f) << shift);
|
|
513
|
+
if ((b & 0x80) != 0x80) {
|
|
514
|
+
return result;
|
|
515
|
+
}
|
|
516
|
+
shift += 7;
|
|
517
|
+
}
|
|
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);
|
|
442
527
|
}
|
|
443
528
|
|
|
444
529
|
static int16_t read_i16(VALUE self) {
|
|
445
|
-
return zig_zag_to_int((
|
|
530
|
+
return (int16_t)zig_zag_to_int(read_varint32(self));
|
|
446
531
|
}
|
|
447
532
|
|
|
448
533
|
VALUE rb_thrift_compact_proto_read_message_end(VALUE self) {
|
|
@@ -476,25 +561,27 @@ VALUE rb_thrift_compact_proto_read_set_end(VALUE self) {
|
|
|
476
561
|
}
|
|
477
562
|
|
|
478
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
|
+
|
|
479
568
|
int8_t protocol_id = read_byte_direct(self);
|
|
480
569
|
if (protocol_id != PROTOCOL_ID) {
|
|
481
570
|
char buf[100];
|
|
482
|
-
|
|
483
|
-
buf
|
|
484
|
-
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)));
|
|
485
573
|
}
|
|
486
574
|
|
|
487
575
|
int8_t version_and_type = read_byte_direct(self);
|
|
488
576
|
int8_t version = version_and_type & VERSION_MASK;
|
|
489
577
|
if (version != VERSION) {
|
|
490
578
|
char buf[100];
|
|
491
|
-
|
|
492
|
-
buf
|
|
493
|
-
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)));
|
|
494
581
|
}
|
|
495
582
|
|
|
496
583
|
int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS;
|
|
497
|
-
int32_t seqid = (
|
|
584
|
+
int32_t seqid = message_seqid_from_varint32(read_varint32(self));
|
|
498
585
|
VALUE messageName = rb_thrift_compact_proto_read_string(self);
|
|
499
586
|
return rb_ary_new3(3, messageName, INT2FIX(type), INT2NUM(seqid));
|
|
500
587
|
}
|
|
@@ -532,19 +619,21 @@ VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) {
|
|
|
532
619
|
}
|
|
533
620
|
|
|
534
621
|
VALUE rb_thrift_compact_proto_read_map_begin(VALUE self) {
|
|
535
|
-
|
|
622
|
+
uint32_t size = read_varint32(self);
|
|
623
|
+
validate_container_size(size);
|
|
536
624
|
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)),
|
|
625
|
+
return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)), UINT2NUM(size));
|
|
538
626
|
}
|
|
539
627
|
|
|
540
628
|
VALUE rb_thrift_compact_proto_read_list_begin(VALUE self) {
|
|
541
629
|
uint8_t size_and_type = read_byte_direct(self);
|
|
542
|
-
|
|
630
|
+
uint32_t size = (size_and_type >> 4) & 0x0f;
|
|
543
631
|
if (size == 15) {
|
|
544
|
-
size = (
|
|
632
|
+
size = read_varint32(self);
|
|
545
633
|
}
|
|
634
|
+
validate_container_size(size);
|
|
546
635
|
uint8_t type = get_ttype(size_and_type & 0x0f);
|
|
547
|
-
return rb_ary_new3(2, INT2FIX(type),
|
|
636
|
+
return rb_ary_new3(2, INT2FIX(type), UINT2NUM(size));
|
|
548
637
|
}
|
|
549
638
|
|
|
550
639
|
VALUE rb_thrift_compact_proto_read_set_begin(VALUE self) {
|
|
@@ -570,7 +659,7 @@ VALUE rb_thrift_compact_proto_read_i16(VALUE self) {
|
|
|
570
659
|
}
|
|
571
660
|
|
|
572
661
|
VALUE rb_thrift_compact_proto_read_i32(VALUE self) {
|
|
573
|
-
return INT2NUM(zig_zag_to_int((
|
|
662
|
+
return INT2NUM(zig_zag_to_int(read_varint32(self)));
|
|
574
663
|
}
|
|
575
664
|
|
|
576
665
|
VALUE rb_thrift_compact_proto_read_i64(VALUE self) {
|
|
@@ -580,19 +669,19 @@ VALUE rb_thrift_compact_proto_read_i64(VALUE self) {
|
|
|
580
669
|
VALUE rb_thrift_compact_proto_read_double(VALUE self) {
|
|
581
670
|
union {
|
|
582
671
|
double f;
|
|
583
|
-
|
|
672
|
+
uint64_t l;
|
|
584
673
|
} transfer;
|
|
585
674
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
586
675
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8));
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
| ((
|
|
590
|
-
| ((
|
|
591
|
-
|
|
592
|
-
| ((
|
|
593
|
-
| ((
|
|
594
|
-
| ((
|
|
595
|
-
|
|
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);
|
|
596
685
|
|
|
597
686
|
return rb_float_new(transfer.f);
|
|
598
687
|
}
|
|
@@ -603,8 +692,12 @@ VALUE rb_thrift_compact_proto_read_string(VALUE self) {
|
|
|
603
692
|
}
|
|
604
693
|
|
|
605
694
|
VALUE rb_thrift_compact_proto_read_binary(VALUE self) {
|
|
606
|
-
|
|
607
|
-
|
|
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);
|
|
700
|
+
return rb_funcall(GET_TRANSPORT(self), read_all_method_id, 1, UINT2NUM(size));
|
|
608
701
|
}
|
|
609
702
|
|
|
610
703
|
VALUE rb_thrift_compact_proto_read_uuid(VALUE self) {
|
data/ext/constants.h
CHANGED
|
@@ -77,14 +77,17 @@ extern ID skip_method_id;
|
|
|
77
77
|
extern ID write_method_id;
|
|
78
78
|
extern ID read_all_method_id;
|
|
79
79
|
extern ID read_into_buffer_method_id;
|
|
80
|
+
extern ID reset_message_size_method_id;
|
|
80
81
|
extern ID force_binary_encoding_id;
|
|
81
82
|
extern ID convert_to_utf8_byte_buffer_id;
|
|
82
83
|
extern ID convert_to_string_id;
|
|
83
84
|
|
|
84
85
|
extern ID fields_const_id;
|
|
85
86
|
extern ID transport_ivar_id;
|
|
87
|
+
extern ID reset_message_size_ivar_id;
|
|
86
88
|
extern ID strict_read_ivar_id;
|
|
87
89
|
extern ID strict_write_ivar_id;
|
|
90
|
+
extern ID max_string_size_ivar_id;
|
|
88
91
|
|
|
89
92
|
extern VALUE type_sym;
|
|
90
93
|
extern VALUE name_sym;
|
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
|
|
@@ -17,13 +18,20 @@
|
|
|
17
18
|
# under the License.
|
|
18
19
|
#
|
|
19
20
|
|
|
20
|
-
if defined?(RUBY_ENGINE) && RUBY_ENGINE
|
|
21
|
-
File.open(
|
|
21
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
|
22
|
+
File.open("Makefile", "w") { |f| f.puts "all:\n\ninstall:\n" }
|
|
22
23
|
else
|
|
23
|
-
require
|
|
24
|
+
require "mkmf"
|
|
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.
|
|
@@ -31,5 +39,5 @@ else
|
|
|
31
39
|
|
|
32
40
|
have_func("strlcpy", "string.h")
|
|
33
41
|
|
|
34
|
-
create_makefile
|
|
42
|
+
create_makefile "thrift_native"
|
|
35
43
|
end
|
data/ext/macros.h
CHANGED
|
@@ -24,6 +24,17 @@
|
|
|
24
24
|
#define CHECK_NIL(obj) if (NIL_P(obj)) { rb_raise(rb_eStandardError, "nil argument not allowed!");}
|
|
25
25
|
#define READ(obj, length) rb_funcall(GET_TRANSPORT(obj), read_all_method_id, 1, INT2FIX(length))
|
|
26
26
|
|
|
27
|
+
// Refuse a declared string length over the protocol's @max_string_size (nil
|
|
28
|
+
// means no limit) before it becomes a read size.
|
|
29
|
+
#define CHECK_STRING_SIZE(obj, size) \
|
|
30
|
+
do { \
|
|
31
|
+
VALUE max_string_size_ = rb_ivar_get(obj, max_string_size_ivar_id); \
|
|
32
|
+
if (!NIL_P(max_string_size_) && RB_UNLIKELY((long long)(size) > NUM2LL(max_string_size_))) { \
|
|
33
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_SIZE_LIMIT), \
|
|
34
|
+
rb_sprintf("String size %lld larger than the maximum %lld", (long long)(size), NUM2LL(max_string_size_)))); \
|
|
35
|
+
} \
|
|
36
|
+
} while (0)
|
|
37
|
+
|
|
27
38
|
#ifndef RFLOAT_VALUE
|
|
28
39
|
# define RFLOAT_VALUE(v) RFLOAT(rb_Float(v))->value
|
|
29
40
|
#endif
|