Greetings!
I have noticed that when using the BinaryProtocolAccelerated in Ruby, and
expecting a map<string,string> and getting something else, a segmentation
fault occurs. I was able to trace the segmentation fault back to
binary_protocol_accelerated.c, in r807972, the problem is in
RSTRING_LEN(str) inside write_string_direct(...).
Notice that, in the Python implementation, or when using BinaryProtocol as
opposed to BinaryProtocolAccelerated, an exception is raised when a value
has a type other than string in a map<string, string>.
Below is a patch that solved the problem for me, please advise on whether or
not this would be the right way to solve it (it appears to work properly in
different cases).
Index: lib/rb/ext/binary_protocol_accelerated.c
===================================================================
--- lib/rb/ext/binary_protocol_accelerated.c (revision 807972)
+++ lib/rb/ext/binary_protocol_accelerated.c (working copy)
@@ -76,6 +76,9 @@
}
static void write_string_direct(VALUE trans, VALUE str) {
+ if (TYPE(str) != T_STRING) {
+ rb_raise(rb_eStandardError, "Value should be a string");
+ }
write_i32_direct(trans, RSTRING_LEN(str));
rb_funcall(trans, write_method_id, 1, str);
}
Also, below you can find a set of files that can be used to reproduce the
segmentation fault mentioned:
test.thrift
===================================================================
service Test {
i32 c1(1: i32 p1, 2: i32 p2, 3: map<string,string> p3)
}
server.rb
===================================================================
require 'rubygems'
require 'thrift'
require 'extlib'
CURDIR = File.dirname(__FILE__)
$: << CURDIR / "gen-rb"
Dir[CURDIR / "gen-rb" / "**" / "*"].each { |f| require f unless
File.directory?(f) }
class TestHandler
def c1(p1, p2, p3)
p1 + p2
end
end
handler = TestHandler.new()
processor = Test::Processor.new(handler)
transport = Thrift::ServerSocket.new(9090)
transportFactory = Thrift::BufferedTransportFactory.new()
protocolFactory = Thrift::BinaryProtocolAcceleratedFactory.new
server = Thrift::ThreadPoolServer.new(processor, transport,
transportFactory, protocolFactory)
server.serve()
client.rb
===================================================================
require 'rubygems'
require 'thrift'
require 'extlib'
CURDIR = File.dirname(__FILE__)
$: << CURDIR / "gen-rb"
Dir[CURDIR / "gen-rb" / "**" / "*"].each { |f| require f unless
File.directory?(f) }
transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost',
9090))
protocol = Thrift::BinaryProtocolAccelerated.new(transport)
srv = Test::Client.new(protocol)
transport.open()
p srv.c1(1,1,{'asfd' => true}) # Causes segmentaion fault without the patch,
raises an error with the patch
Thank you!
-- Sinan Taifour