thrift 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +93 -33
- data/benchmark/benchmark.rb +2 -1
- data/benchmark/client.rb +1 -0
- data/benchmark/server.rb +1 -0
- data/benchmark/thin_server.rb +1 -0
- data/ext/binary_protocol_accelerated.c +78 -23
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +59 -31
- data/ext/extconf.rb +8 -0
- data/ext/memory_buffer.c +37 -0
- data/ext/struct.c +14 -14
- data/ext/thrift_native.c +1 -0
- data/lib/thrift/bytes.rb +4 -1
- data/lib/thrift/client.rb +1 -12
- data/lib/thrift/exceptions.rb +1 -0
- data/lib/thrift/multiplexed_processor.rb +14 -4
- data/lib/thrift/processor.rb +1 -0
- data/lib/thrift/protocol/base_protocol.rb +15 -6
- data/lib/thrift/protocol/binary_protocol.rb +41 -12
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +1 -0
- data/lib/thrift/protocol/compact_protocol.rb +15 -4
- data/lib/thrift/protocol/header_protocol.rb +1 -0
- data/lib/thrift/protocol/json_protocol.rb +18 -11
- data/lib/thrift/protocol/multiplexed_protocol.rb +1 -0
- data/lib/thrift/protocol/protocol_decorator.rb +1 -0
- data/lib/thrift/serializer/deserializer.rb +1 -0
- data/lib/thrift/serializer/serializer.rb +1 -0
- data/lib/thrift/server/base_server.rb +1 -0
- data/lib/thrift/server/mongrel_http_server.rb +1 -0
- data/lib/thrift/server/nonblocking_server.rb +28 -2
- data/lib/thrift/server/simple_server.rb +9 -1
- data/lib/thrift/server/thin_http_server.rb +1 -0
- data/lib/thrift/server/thread_pool_server.rb +1 -0
- data/lib/thrift/server/threaded_server.rb +9 -1
- data/lib/thrift/struct.rb +1 -0
- data/lib/thrift/struct_union.rb +4 -9
- data/lib/thrift/thrift_native.rb +2 -1
- data/lib/thrift/transport/base_server_transport.rb +3 -0
- data/lib/thrift/transport/base_transport.rb +6 -2
- data/lib/thrift/transport/buffered_transport.rb +1 -0
- data/lib/thrift/transport/framed_transport.rb +1 -0
- data/lib/thrift/transport/header_transport.rb +47 -1
- data/lib/thrift/transport/http_client_transport.rb +1 -0
- data/lib/thrift/transport/io_stream_transport.rb +1 -0
- data/lib/thrift/transport/memory_buffer_transport.rb +7 -0
- data/lib/thrift/transport/server_socket.rb +6 -3
- data/lib/thrift/transport/socket.rb +68 -29
- data/lib/thrift/transport/ssl_server_socket.rb +3 -2
- data/lib/thrift/transport/ssl_socket.rb +43 -11
- data/lib/thrift/transport/unix_server_socket.rb +5 -1
- data/lib/thrift/transport/unix_socket.rb +1 -0
- data/lib/thrift/types.rb +1 -0
- data/lib/thrift/union.rb +1 -0
- data/lib/thrift/uuid.rb +1 -0
- data/lib/thrift.rb +1 -0
- data/spec/ThriftSpec.thrift +16 -0
- data/spec/base_protocol_spec.rb +20 -0
- data/spec/base_transport_spec.rb +42 -1
- data/spec/binary_protocol_accelerated_spec.rb +1 -0
- data/spec/binary_protocol_spec.rb +1 -0
- data/spec/binary_protocol_spec_shared.rb +79 -15
- data/spec/bytes_spec.rb +19 -1
- data/spec/client_spec.rb +1 -0
- data/spec/compact_protocol_spec.rb +99 -0
- data/spec/constants_demo_spec.rb +1 -0
- data/spec/exception_spec.rb +1 -0
- data/spec/flat_spec.rb +1 -0
- data/spec/header_protocol_spec.rb +1 -0
- data/spec/header_transport_spec.rb +45 -0
- data/spec/http_client_spec.rb +1 -0
- data/spec/json_protocol_spec.rb +26 -4
- data/spec/multiplexed_processor_spec.rb +75 -0
- data/spec/namespaced_spec.rb +1 -0
- data/spec/nonblocking_server_spec.rb +86 -18
- data/spec/processor_spec.rb +1 -0
- data/spec/recursion_depth_spec.rb +223 -0
- data/spec/serializer_spec.rb +1 -0
- data/spec/server_socket_spec.rb +37 -0
- data/spec/server_spec.rb +52 -0
- data/spec/socket_spec.rb +119 -12
- data/spec/socket_spec_shared.rb +1 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/ssl_server_socket_spec.rb +40 -0
- data/spec/ssl_socket_spec.rb +171 -10
- data/spec/struct_nested_containers_spec.rb +1 -0
- data/spec/struct_spec.rb +1 -0
- data/spec/support/header_protocol_helper.rb +2 -1
- data/spec/thin_http_server_spec.rb +1 -0
- data/spec/types_spec.rb +1 -0
- data/spec/union_spec.rb +1 -0
- data/spec/unix_socket_spec.rb +16 -0
- data/spec/uuid_validation_spec.rb +1 -0
- data/test/fuzz/Makefile +779 -0
- data/test/fuzz/Makefile.in +775 -0
- data/test/fuzz/fuzz_common.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +1 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +1 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +1 -0
- data/test/fuzz/fuzz_tracer.rb +1 -0
- metadata +12 -46
data/ext/memory_buffer.c
CHANGED
|
@@ -28,11 +28,15 @@ ID index_ivar_id;
|
|
|
28
28
|
ID slice_method_id;
|
|
29
29
|
|
|
30
30
|
int GARBAGE_BUFFER_SIZE;
|
|
31
|
+
static VALUE transport_exception_class;
|
|
32
|
+
static VALUE transport_negative_size;
|
|
33
|
+
static ID new_method_id;
|
|
31
34
|
|
|
32
35
|
#define GET_BUF(self) rb_ivar_get(self, buf_ivar_id)
|
|
33
36
|
|
|
34
37
|
VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str);
|
|
35
38
|
VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value);
|
|
39
|
+
VALUE rb_thrift_memory_buffer_read_all(VALUE self, VALUE length_value);
|
|
36
40
|
VALUE rb_thrift_memory_buffer_read_byte(VALUE self);
|
|
37
41
|
VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value);
|
|
38
42
|
|
|
@@ -69,6 +73,33 @@ VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) {
|
|
|
69
73
|
return data;
|
|
70
74
|
}
|
|
71
75
|
|
|
76
|
+
VALUE rb_thrift_memory_buffer_read_all(VALUE self, VALUE length_value) {
|
|
77
|
+
int length = FIX2INT(length_value);
|
|
78
|
+
|
|
79
|
+
if (RB_UNLIKELY(length < 0)) {
|
|
80
|
+
rb_exc_raise(rb_funcall(transport_exception_class, new_method_id, 2, transport_negative_size, rb_str_new2("Negative size")));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
VALUE index_value = rb_ivar_get(self, index_ivar_id);
|
|
84
|
+
int index = FIX2INT(index_value);
|
|
85
|
+
VALUE buf = GET_BUF(self);
|
|
86
|
+
|
|
87
|
+
if (RB_UNLIKELY(length > RSTRING_LEN(buf) - index)) {
|
|
88
|
+
rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
VALUE data = rb_str_subseq(buf, index, length);
|
|
92
|
+
|
|
93
|
+
index += length;
|
|
94
|
+
if (index >= GARBAGE_BUFFER_SIZE) {
|
|
95
|
+
rb_ivar_set(self, buf_ivar_id, rb_str_subseq(buf, index, RSTRING_LEN(buf) - index));
|
|
96
|
+
index = 0;
|
|
97
|
+
}
|
|
98
|
+
rb_ivar_set(self, index_ivar_id, INT2FIX(index));
|
|
99
|
+
|
|
100
|
+
return data;
|
|
101
|
+
}
|
|
102
|
+
|
|
72
103
|
VALUE rb_thrift_memory_buffer_read_byte(VALUE self) {
|
|
73
104
|
VALUE index_value = rb_ivar_get(self, index_ivar_id);
|
|
74
105
|
int index = FIX2INT(index_value);
|
|
@@ -122,6 +153,7 @@ void Init_memory_buffer(void) {
|
|
|
122
153
|
VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport"));
|
|
123
154
|
rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1);
|
|
124
155
|
rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1);
|
|
156
|
+
rb_define_method(thrift_memory_buffer_class, "read_all", rb_thrift_memory_buffer_read_all, 1);
|
|
125
157
|
rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0);
|
|
126
158
|
rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2);
|
|
127
159
|
|
|
@@ -129,6 +161,11 @@ void Init_memory_buffer(void) {
|
|
|
129
161
|
index_ivar_id = rb_intern("@index");
|
|
130
162
|
|
|
131
163
|
slice_method_id = rb_intern("slice");
|
|
164
|
+
new_method_id = rb_intern("new");
|
|
132
165
|
|
|
133
166
|
GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE")));
|
|
167
|
+
transport_exception_class = rb_const_get(thrift_module, rb_intern("TransportException"));
|
|
168
|
+
transport_negative_size = rb_const_get(transport_exception_class, rb_intern("NEGATIVE_SIZE"));
|
|
169
|
+
rb_global_variable(&transport_exception_class);
|
|
170
|
+
rb_global_variable(&transport_negative_size);
|
|
134
171
|
}
|
data/ext/struct.c
CHANGED
|
@@ -35,8 +35,8 @@ static ID sorted_field_ids_method_id;
|
|
|
35
35
|
#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
|
|
36
36
|
#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
|
|
37
37
|
|
|
38
|
-
static
|
|
39
|
-
if (size < 0) {
|
|
38
|
+
static void validate_container_size(int size) {
|
|
39
|
+
if (RB_UNLIKELY(size < 0)) {
|
|
40
40
|
rb_exc_raise(
|
|
41
41
|
get_protocol_exception(
|
|
42
42
|
INT2FIX(PROTOERR_NEGATIVE_SIZE),
|
|
@@ -44,7 +44,10 @@ static VALUE new_container_array(int size) {
|
|
|
44
44
|
)
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
+
}
|
|
47
48
|
|
|
49
|
+
static VALUE new_container_array(int size) {
|
|
50
|
+
validate_container_size(size);
|
|
48
51
|
return rb_ary_new2(size > 1024 ? 1024 : size);
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -252,8 +255,6 @@ static void write_container(int ttype, VALUE field_info, VALUE value, VALUE prot
|
|
|
252
255
|
|
|
253
256
|
if (ttype == TTYPE_MAP) {
|
|
254
257
|
VALUE keys;
|
|
255
|
-
VALUE key;
|
|
256
|
-
VALUE val;
|
|
257
258
|
|
|
258
259
|
Check_Type(value, T_HASH);
|
|
259
260
|
|
|
@@ -272,8 +273,8 @@ static void write_container(int ttype, VALUE field_info, VALUE value, VALUE prot
|
|
|
272
273
|
default_write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));
|
|
273
274
|
|
|
274
275
|
for (i = 0; i < sz; i++) {
|
|
275
|
-
key = rb_ary_entry(keys, i);
|
|
276
|
-
val = rb_hash_aref(value, key);
|
|
276
|
+
VALUE key = rb_ary_entry(keys, i);
|
|
277
|
+
VALUE val = rb_hash_aref(value, key);
|
|
277
278
|
|
|
278
279
|
if (IS_CONTAINER(keytype)) {
|
|
279
280
|
write_container(keytype, key_info, key, protocol);
|
|
@@ -489,8 +490,6 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
489
490
|
rb_thrift_struct_read(result, protocol);
|
|
490
491
|
}
|
|
491
492
|
} else if (ttype == TTYPE_MAP) {
|
|
492
|
-
int i;
|
|
493
|
-
|
|
494
493
|
VALUE map_header = default_read_map_begin(protocol);
|
|
495
494
|
int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
|
|
496
495
|
int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
|
|
@@ -511,7 +510,7 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
511
510
|
if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) {
|
|
512
511
|
result = rb_hash_new();
|
|
513
512
|
|
|
514
|
-
for (i = 0; i < num_entries; ++i) {
|
|
513
|
+
for (int i = 0; i < num_entries; ++i) {
|
|
515
514
|
VALUE key, val;
|
|
516
515
|
|
|
517
516
|
key = read_anything(protocol, key_ttype, key_info);
|
|
@@ -528,8 +527,6 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
528
527
|
|
|
529
528
|
default_read_map_end(protocol);
|
|
530
529
|
} else if (ttype == TTYPE_LIST) {
|
|
531
|
-
int i;
|
|
532
|
-
|
|
533
530
|
VALUE list_header = default_read_list_begin(protocol);
|
|
534
531
|
int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
|
|
535
532
|
int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
|
|
@@ -542,20 +539,21 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
542
539
|
if (specified_element_type == element_ttype) {
|
|
543
540
|
result = new_container_array(num_elements);
|
|
544
541
|
|
|
545
|
-
for (i = 0; i < num_elements; ++i) {
|
|
542
|
+
for (int i = 0; i < num_elements; ++i) {
|
|
546
543
|
rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
547
544
|
}
|
|
548
545
|
} else {
|
|
546
|
+
validate_container_size(num_elements);
|
|
549
547
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
550
548
|
}
|
|
551
549
|
} else {
|
|
550
|
+
validate_container_size(num_elements);
|
|
552
551
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
553
552
|
}
|
|
554
553
|
|
|
555
554
|
default_read_list_end(protocol);
|
|
556
555
|
} else if (ttype == TTYPE_SET) {
|
|
557
556
|
VALUE items;
|
|
558
|
-
int i;
|
|
559
557
|
|
|
560
558
|
VALUE set_header = default_read_set_begin(protocol);
|
|
561
559
|
int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
|
|
@@ -569,15 +567,17 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
569
567
|
if (specified_element_type == element_ttype) {
|
|
570
568
|
items = new_container_array(num_elements);
|
|
571
569
|
|
|
572
|
-
for (i = 0; i < num_elements; ++i) {
|
|
570
|
+
for (int i = 0; i < num_elements; ++i) {
|
|
573
571
|
rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
574
572
|
}
|
|
575
573
|
|
|
576
574
|
result = rb_class_new_instance(1, &items, rb_cSet);
|
|
577
575
|
} else {
|
|
576
|
+
validate_container_size(num_elements);
|
|
578
577
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
579
578
|
}
|
|
580
579
|
} else {
|
|
580
|
+
validate_container_size(num_elements);
|
|
581
581
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
582
582
|
}
|
|
583
583
|
|
data/ext/thrift_native.c
CHANGED
|
@@ -121,6 +121,7 @@ int PROTOERR_BAD_VERSION;
|
|
|
121
121
|
int PROTOERR_NOT_IMPLEMENTED;
|
|
122
122
|
int PROTOERR_DEPTH_LIMIT;
|
|
123
123
|
|
|
124
|
+
// cppcheck-suppress unusedFunction
|
|
124
125
|
RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
125
126
|
// cached classes
|
|
126
127
|
thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
|
data/lib/thrift/bytes.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -36,13 +37,15 @@ module Thrift
|
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# Forces the encoding of the buffer to BINARY. If the buffer
|
|
39
|
-
# passed is frozen, then it will be duplicated.
|
|
40
|
+
# passed is frozen and not already BINARY, then it will be duplicated.
|
|
40
41
|
#
|
|
41
42
|
# buffer - The String to force the encoding of.
|
|
42
43
|
#
|
|
43
44
|
# Returns the String passed with an encoding of BINARY; returned
|
|
44
45
|
# String may be a duplicate.
|
|
45
46
|
def self.force_binary_encoding(buffer)
|
|
47
|
+
return buffer if buffer.encoding == Encoding::BINARY
|
|
48
|
+
|
|
46
49
|
buffer = buffer.dup if buffer.frozen?
|
|
47
50
|
buffer.force_encoding(Encoding::BINARY)
|
|
48
51
|
end
|
data/lib/thrift/client.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
|
|
@@ -61,11 +62,6 @@ module Thrift
|
|
|
61
62
|
[fname, mtype, rseqid]
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
def reply_seqid(rseqid)
|
|
65
|
-
expected_seqid = dequeue_pending_seqid
|
|
66
|
-
!expected_seqid.nil? && rseqid == expected_seqid
|
|
67
|
-
end
|
|
68
|
-
|
|
69
65
|
def validate_message_begin(fname, mtype, rseqid, expected_name)
|
|
70
66
|
expected_seqid = dequeue_pending_seqid
|
|
71
67
|
|
|
@@ -102,13 +98,6 @@ module Thrift
|
|
|
102
98
|
result
|
|
103
99
|
end
|
|
104
100
|
|
|
105
|
-
def handle_exception(mtype)
|
|
106
|
-
if mtype == MessageTypes::EXCEPTION
|
|
107
|
-
dequeue_pending_seqid
|
|
108
|
-
raise_application_exception
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
101
|
private
|
|
113
102
|
|
|
114
103
|
def next_seqid!
|
data/lib/thrift/exceptions.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
|
|
@@ -23,17 +24,26 @@ module Thrift
|
|
|
23
24
|
class MultiplexedProcessor
|
|
24
25
|
def initialize
|
|
25
26
|
@actual_processors = {}
|
|
27
|
+
@default_processor = nil
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def register_processor(service_name, processor)
|
|
29
31
|
@actual_processors[service_name] = processor
|
|
30
32
|
end
|
|
31
33
|
|
|
34
|
+
def register_default(processor)
|
|
35
|
+
@default_processor = processor
|
|
36
|
+
end
|
|
37
|
+
|
|
32
38
|
def process(iprot, oprot)
|
|
33
39
|
name, type, seqid = iprot.read_message_begin
|
|
34
40
|
check_type(type)
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
if name.count(':') < 1
|
|
42
|
+
check_default_processor(name)
|
|
43
|
+
return @default_processor.process(StoredMessageProtocol.new(iprot, [name, type, seqid]), oprot)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
service_name, method = name.split(':', 2)
|
|
37
47
|
processor(service_name).process(StoredMessageProtocol.new(iprot, [method, type, seqid]), oprot)
|
|
38
48
|
end
|
|
39
49
|
|
|
@@ -53,8 +63,8 @@ module Thrift
|
|
|
53
63
|
end
|
|
54
64
|
end
|
|
55
65
|
|
|
56
|
-
def
|
|
57
|
-
|
|
66
|
+
def check_default_processor(name)
|
|
67
|
+
unless @default_processor
|
|
58
68
|
raise Thrift::Exception.new("Service name not found in message name: #{name}. Did you forget to use a Thrift::Protocol::MultiplexedProtocol in your client?")
|
|
59
69
|
end
|
|
60
70
|
end
|
data/lib/thrift/processor.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
|
|
@@ -341,7 +342,8 @@ module Thrift
|
|
|
341
342
|
end
|
|
342
343
|
end
|
|
343
344
|
|
|
344
|
-
def skip(type)
|
|
345
|
+
def skip(type, max_depth = 64)
|
|
346
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, 'Maximum skip depth exceeded') if max_depth <= 0
|
|
345
347
|
case type
|
|
346
348
|
when Types::BOOL
|
|
347
349
|
read_bool
|
|
@@ -364,27 +366,30 @@ module Thrift
|
|
|
364
366
|
while true
|
|
365
367
|
name, type, id = read_field_begin
|
|
366
368
|
break if type == Types::STOP
|
|
367
|
-
skip(type)
|
|
369
|
+
skip(type, max_depth - 1)
|
|
368
370
|
read_field_end
|
|
369
371
|
end
|
|
370
372
|
read_struct_end
|
|
371
373
|
when Types::MAP
|
|
372
374
|
ktype, vtype, size = read_map_begin
|
|
375
|
+
validate_container_size(size)
|
|
373
376
|
size.times do
|
|
374
|
-
skip(ktype)
|
|
375
|
-
skip(vtype)
|
|
377
|
+
skip(ktype, max_depth - 1)
|
|
378
|
+
skip(vtype, max_depth - 1)
|
|
376
379
|
end
|
|
377
380
|
read_map_end
|
|
378
381
|
when Types::SET
|
|
379
382
|
etype, size = read_set_begin
|
|
383
|
+
validate_container_size(size)
|
|
380
384
|
size.times do
|
|
381
|
-
skip(etype)
|
|
385
|
+
skip(etype, max_depth - 1)
|
|
382
386
|
end
|
|
383
387
|
read_set_end
|
|
384
388
|
when Types::LIST
|
|
385
389
|
etype, size = read_list_begin
|
|
390
|
+
validate_container_size(size)
|
|
386
391
|
size.times do
|
|
387
|
-
skip(etype)
|
|
392
|
+
skip(etype, max_depth - 1)
|
|
388
393
|
end
|
|
389
394
|
read_list_end
|
|
390
395
|
else
|
|
@@ -392,6 +397,10 @@ module Thrift
|
|
|
392
397
|
end
|
|
393
398
|
end
|
|
394
399
|
|
|
400
|
+
def validate_container_size(size)
|
|
401
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size') unless size >= 0
|
|
402
|
+
end
|
|
403
|
+
|
|
395
404
|
def to_s
|
|
396
405
|
"#{trans.to_s}"
|
|
397
406
|
end
|
|
@@ -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
|
|
@@ -22,6 +23,14 @@ module Thrift
|
|
|
22
23
|
VERSION_MASK = 0xffff0000
|
|
23
24
|
VERSION_1 = 0x80010000
|
|
24
25
|
TYPE_MASK = 0x000000ff
|
|
26
|
+
BYTE_MIN = -2**7
|
|
27
|
+
BYTE_MAX = 2**7 - 1
|
|
28
|
+
I16_MIN = -2**15
|
|
29
|
+
I16_MAX = 2**15 - 1
|
|
30
|
+
I32_MIN = -2**31
|
|
31
|
+
I32_MAX = 2**31 - 1
|
|
32
|
+
I64_MIN = -2**63
|
|
33
|
+
I64_MAX = 2**63 - 1
|
|
25
34
|
|
|
26
35
|
attr_reader :strict_read, :strict_write
|
|
27
36
|
|
|
@@ -36,11 +45,10 @@ module Thrift
|
|
|
36
45
|
end
|
|
37
46
|
|
|
38
47
|
def write_message_begin(name, type, seqid)
|
|
39
|
-
# this is necessary because we added (needed) bounds checking to
|
|
40
|
-
# write_i32, and 0x80010000 is too big for that.
|
|
41
48
|
if strict_write
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
raise ::TypeError, 'integer argument expected' unless type.is_a?(Integer)
|
|
50
|
+
raise RangeError if type < BYTE_MIN || type > BYTE_MAX
|
|
51
|
+
trans.write([VERSION_1 | type].pack('N'))
|
|
44
52
|
write_string(name)
|
|
45
53
|
write_i32(seqid)
|
|
46
54
|
else
|
|
@@ -64,17 +72,17 @@ module Thrift
|
|
|
64
72
|
def write_map_begin(ktype, vtype, size)
|
|
65
73
|
write_byte(ktype)
|
|
66
74
|
write_byte(vtype)
|
|
67
|
-
|
|
75
|
+
write_i32_size(size)
|
|
68
76
|
end
|
|
69
77
|
|
|
70
78
|
def write_list_begin(etype, size)
|
|
71
79
|
write_byte(etype)
|
|
72
|
-
|
|
80
|
+
write_i32_size(size)
|
|
73
81
|
end
|
|
74
82
|
|
|
75
83
|
def write_set_begin(etype, size)
|
|
76
84
|
write_byte(etype)
|
|
77
|
-
|
|
85
|
+
write_i32_size(size)
|
|
78
86
|
end
|
|
79
87
|
|
|
80
88
|
def write_bool(bool)
|
|
@@ -83,24 +91,29 @@ module Thrift
|
|
|
83
91
|
|
|
84
92
|
def write_byte(byte)
|
|
85
93
|
raise 'nil argument not allowed!' if byte.nil?
|
|
86
|
-
raise
|
|
94
|
+
raise ::TypeError, 'integer argument expected' unless byte.is_a?(Integer)
|
|
95
|
+
raise RangeError if byte < BYTE_MIN || byte > BYTE_MAX
|
|
87
96
|
trans.write([byte].pack('c'))
|
|
88
97
|
end
|
|
89
98
|
|
|
90
99
|
def write_i16(i16)
|
|
91
100
|
raise 'nil argument not allowed!' if i16.nil?
|
|
101
|
+
raise ::TypeError, 'integer argument expected' unless i16.is_a?(Integer)
|
|
102
|
+
raise RangeError if i16 < I16_MIN || i16 > I16_MAX
|
|
92
103
|
trans.write([i16].pack('n'))
|
|
93
104
|
end
|
|
94
105
|
|
|
95
106
|
def write_i32(i32)
|
|
96
107
|
raise 'nil argument not allowed!' if i32.nil?
|
|
97
|
-
raise
|
|
108
|
+
raise ::TypeError, 'integer argument expected' unless i32.is_a?(Integer)
|
|
109
|
+
raise RangeError if i32 < I32_MIN || i32 > I32_MAX
|
|
98
110
|
trans.write([i32].pack('N'))
|
|
99
111
|
end
|
|
100
112
|
|
|
101
113
|
def write_i64(i64)
|
|
102
114
|
raise 'nil argument not allowed!' if i64.nil?
|
|
103
|
-
raise
|
|
115
|
+
raise ::TypeError, 'integer argument expected' unless i64.is_a?(Integer)
|
|
116
|
+
raise RangeError if i64 < I64_MIN || i64 > I64_MAX
|
|
104
117
|
hi = i64 >> 32
|
|
105
118
|
lo = i64 & 0xffffffff
|
|
106
119
|
trans.write([hi, lo].pack('N2'))
|
|
@@ -119,7 +132,7 @@ module Thrift
|
|
|
119
132
|
|
|
120
133
|
def write_binary(buf)
|
|
121
134
|
raise 'nil argument not allowed!' if buf.nil?
|
|
122
|
-
|
|
135
|
+
write_i32_size(buf.bytesize)
|
|
123
136
|
trans.write(buf)
|
|
124
137
|
end
|
|
125
138
|
|
|
@@ -165,18 +178,21 @@ module Thrift
|
|
|
165
178
|
ktype = read_byte
|
|
166
179
|
vtype = read_byte
|
|
167
180
|
size = read_i32
|
|
181
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size') unless size >= 0
|
|
168
182
|
[ktype, vtype, size]
|
|
169
183
|
end
|
|
170
184
|
|
|
171
185
|
def read_list_begin
|
|
172
186
|
etype = read_byte
|
|
173
187
|
size = read_i32
|
|
188
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size') unless size >= 0
|
|
174
189
|
[etype, size]
|
|
175
190
|
end
|
|
176
191
|
|
|
177
192
|
def read_set_begin
|
|
178
193
|
etype = read_byte
|
|
179
194
|
size = read_i32
|
|
195
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size') unless size >= 0
|
|
180
196
|
[etype, size]
|
|
181
197
|
end
|
|
182
198
|
|
|
@@ -236,7 +252,11 @@ module Thrift
|
|
|
236
252
|
|
|
237
253
|
def read_binary
|
|
238
254
|
size = read_i32
|
|
239
|
-
|
|
255
|
+
if size >= 0
|
|
256
|
+
trans.read_all(size)
|
|
257
|
+
else
|
|
258
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size')
|
|
259
|
+
end
|
|
240
260
|
end
|
|
241
261
|
|
|
242
262
|
def read_uuid
|
|
@@ -246,6 +266,15 @@ module Thrift
|
|
|
246
266
|
def to_s
|
|
247
267
|
"binary(#{super.to_s})"
|
|
248
268
|
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
def write_i32_size(size)
|
|
273
|
+
raise 'nil argument not allowed!' if size.nil?
|
|
274
|
+
raise ::TypeError, 'integer argument expected' unless size.is_a?(Integer)
|
|
275
|
+
raise RangeError if size < 0 || size > I32_MAX
|
|
276
|
+
trans.write([size].pack('N'))
|
|
277
|
+
end
|
|
249
278
|
end
|
|
250
279
|
|
|
251
280
|
class BinaryProtocolFactory < BaseProtocolFactory
|
|
@@ -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
|
|
@@ -26,6 +27,8 @@ module Thrift
|
|
|
26
27
|
TYPE_MASK = 0xE0
|
|
27
28
|
TYPE_BITS = 0x07
|
|
28
29
|
TYPE_SHIFT_AMOUNT = 5
|
|
30
|
+
MAX_VARINT32_BYTES = 5 # ceil(32/7); matches protobuf wire format
|
|
31
|
+
MAX_VARINT_BYTES = 10 # ceil(64/7); matches protobuf wire format
|
|
29
32
|
|
|
30
33
|
TSTOP = [nil, Types::STOP, 0]
|
|
31
34
|
|
|
@@ -410,19 +413,27 @@ module Thrift
|
|
|
410
413
|
end
|
|
411
414
|
|
|
412
415
|
def read_varint32()
|
|
413
|
-
|
|
416
|
+
shift = 0
|
|
417
|
+
result = 0
|
|
418
|
+
MAX_VARINT32_BYTES.times do
|
|
419
|
+
b = read_byte()
|
|
420
|
+
result |= (b & 0x7f) << shift
|
|
421
|
+
return result if (b & 0x80) != 0x80
|
|
422
|
+
shift += 7
|
|
423
|
+
end
|
|
424
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Variable-length int over 5 bytes.')
|
|
414
425
|
end
|
|
415
426
|
|
|
416
427
|
def read_varint64()
|
|
417
428
|
shift = 0
|
|
418
429
|
result = 0
|
|
419
|
-
|
|
430
|
+
MAX_VARINT_BYTES.times do
|
|
420
431
|
b = read_byte()
|
|
421
432
|
result |= (b & 0x7f) << shift
|
|
422
|
-
|
|
433
|
+
return result if (b & 0x80) != 0x80
|
|
423
434
|
shift += 7
|
|
424
435
|
end
|
|
425
|
-
|
|
436
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Variable-length int over 10 bytes.')
|
|
426
437
|
end
|
|
427
438
|
|
|
428
439
|
def int_to_zig_zag(n)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -500,10 +501,10 @@ module Thrift
|
|
|
500
501
|
# characters above the BMP are encoded as two escape sequences (surrogate pairs),
|
|
501
502
|
# which is not yet implemented
|
|
502
503
|
def read_json_escape_char
|
|
503
|
-
str =
|
|
504
|
-
str
|
|
505
|
-
str
|
|
506
|
-
str
|
|
504
|
+
str = +@reader.read
|
|
505
|
+
str << @reader.read
|
|
506
|
+
str << @reader.read
|
|
507
|
+
str << @reader.read
|
|
507
508
|
str.hex.chr(Encoding::UTF_8)
|
|
508
509
|
end
|
|
509
510
|
|
|
@@ -524,8 +525,7 @@ module Thrift
|
|
|
524
525
|
@context.read(@reader)
|
|
525
526
|
end
|
|
526
527
|
read_json_syntax_char(@@kJSONStringDelimiter)
|
|
527
|
-
|
|
528
|
-
str = ""
|
|
528
|
+
str = +''
|
|
529
529
|
while (true)
|
|
530
530
|
ch = @reader.read
|
|
531
531
|
if (ch == @@kJSONStringDelimiter)
|
|
@@ -543,7 +543,7 @@ module Thrift
|
|
|
543
543
|
ch = escape_char_vals[pos]
|
|
544
544
|
end
|
|
545
545
|
end
|
|
546
|
-
str
|
|
546
|
+
str << ch
|
|
547
547
|
end
|
|
548
548
|
return str
|
|
549
549
|
end
|
|
@@ -564,14 +564,14 @@ module Thrift
|
|
|
564
564
|
# Reads a sequence of characters, stopping at the first one that is not
|
|
565
565
|
# a valid JSON numeric character.
|
|
566
566
|
def read_json_numeric_chars
|
|
567
|
-
str =
|
|
567
|
+
str = String.new(encoding: Encoding::UTF_8)
|
|
568
568
|
while (true)
|
|
569
569
|
ch = @reader.peek
|
|
570
570
|
if (!is_json_numeric(ch))
|
|
571
571
|
break;
|
|
572
572
|
end
|
|
573
573
|
ch = @reader.read
|
|
574
|
-
str
|
|
574
|
+
str << ch
|
|
575
575
|
end
|
|
576
576
|
return str
|
|
577
577
|
end
|
|
@@ -712,6 +712,7 @@ module Thrift
|
|
|
712
712
|
key_type = get_type_id_for_type_name(read_json_string)
|
|
713
713
|
val_type = get_type_id_for_type_name(read_json_string)
|
|
714
714
|
size = read_json_integer
|
|
715
|
+
validate_container_size(size)
|
|
715
716
|
read_json_object_start
|
|
716
717
|
[key_type, val_type, size]
|
|
717
718
|
end
|
|
@@ -723,7 +724,10 @@ module Thrift
|
|
|
723
724
|
|
|
724
725
|
def read_list_begin
|
|
725
726
|
read_json_array_start
|
|
726
|
-
|
|
727
|
+
type = get_type_id_for_type_name(read_json_string)
|
|
728
|
+
size = read_json_integer
|
|
729
|
+
validate_container_size(size)
|
|
730
|
+
[type, size]
|
|
727
731
|
end
|
|
728
732
|
|
|
729
733
|
def read_list_end
|
|
@@ -732,7 +736,10 @@ module Thrift
|
|
|
732
736
|
|
|
733
737
|
def read_set_begin
|
|
734
738
|
read_json_array_start
|
|
735
|
-
|
|
739
|
+
type = get_type_id_for_type_name(read_json_string)
|
|
740
|
+
size = read_json_integer
|
|
741
|
+
validate_container_size(size)
|
|
742
|
+
[type, size]
|
|
736
743
|
end
|
|
737
744
|
|
|
738
745
|
def read_set_end
|