Uploaded image for project: 'Thrift'
  1. Thrift
  2. THRIFT-4781

C++ clients crash when exceptions are typedefed in the IDL

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 0.11.0, 0.12.0
    • Fix Version/s: None
    • Component/s: C++ - Compiler
    • Labels:
      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.

        Attachments

        1. image-2020-05-06-20-15-44-986.png
          17 kB
          Xusheng Zhang
        2. image-2020-05-06-21-37-46-809.png
          306 kB
          Xusheng Zhang

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              andrejn Andrej Nazarov
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated: