Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
0.11.0, 0.12.0
-
None
-
None
Description
If exceptions are typedefed in the IDL, they're generated as pointers in Cpp. This causes a runtime crash (memory access violation) on the C++ client-side when a server sends that exception and the client tries to read it. Example follows:
service.thrift
namespace * thrifttest.service include "errors.thrift" typedef errors.FooError FooError service FooBarService { string getFooString(1: i32 stringLength) throws (1: FooError e); string getBarString(1: i32 stringLength) throws (1: errors.BarError e); }
errors.thrift
namespace * thrifttest.errors exception FooError { 1: string message } exception BarError { 1: string message }
FooBarService.h
class FooBarService_getFooString_presult { public: virtual ~FooBarService_getFooString_presult() throw(); std::string* success; FooError* e; //note pointer declaration of the exception field // snip... class FooBarService_getBarString_presult { public: virtual ~FooBarService_getBarString_presult() throw(); std::string* success; ::thrifttest::errors::BarError e; //note different declaration of the exception field //snip
FooBarService.cpp
uint32_t FooBarService_getFooString_presult::read(::apache::thrift::protocol::TProtocol* iprot) { // snip... while (true) { // snip... switch (fid) { // snip... case 1: if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += (*(this->e)).read(iprot); // <-- this line causes access violation crash because the pointer is not initialized this->__isset.e = true; // snip... uint32_t FooBarService_getBarString_presult::read(::apache::thrift::protocol::TProtocol* iprot) { // snip... while (true) { // snip... switch (fid) { // snip... case 1: if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->e.read(iprot); //<-- this gets read OK. this->__isset.e = true; //snip
This happens regardless of server language (reproducible if server throwing the exceptions is Java, Python or C++)
I guess this logic in t_cpp_generator.cc:1104 gets deceived in case of typedefed exceptions:
t_cpp_generator.cc
(pointers && !(*m_iter)->get_type()->is_xception()),
I'm no Thrift compiler expert, but I assume there is a reason why you don't want exceptions to be declared as pointers. Yet in this case they clearly are.