Uploaded image for project: 'C++ Driver'
  1. C++ Driver
  2. CXX-1187

mongocxx::uri::database() segfaults if no database specified in URL

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.2.0-rc0
    • Component/s: Implementation
    • Labels:
      None
    • Story Points:
      1
    • Sprint:
      Perl/CXX 2017-02-10, Perl/CXX 2017-03-03

      Description

      Reproducer:

      mongocxx::uri uri{mongocxx::uri::k_default_uri};
      std::cout << uri.database() << std::endl;
      

      Expected:

      • Should print out the empty string. Or, well, there's some room for debase here. It would also be ok if it asserted, if there were some sort of "has_database()" method so I can check whether a database is present.

      Actual:

      • On my Mac (OS X Sierra), crashes with a segmentation fault. On my Linux box (Ubuntu 16.04), dumps some scary-looking memory debug information and exits.

      Analysis:

      The root of the problem appears to be in the deceptively-simple-looking "mongocxx::uri::database()":

      std::string uri::database() const {
          return libmongoc::uri_get_database(_impl->uri_t);
      }
      

      libmongoc::uri_get_database() returns a char*. Because we are returning a std::string, C++ performs an implicit cast.

      If no database was specified in the URI, uri_get_database() returns NULL, not (for example) "". I think this is an entirely reasonable C API. However, the implicit std::string(const char*) constructor requires/assumes that the char* point to a valid string. When passed a NULL pointer, it dereferences that pointer and causes a segfault.

      A trivial solution would be to add a helper that handles NULL somehow. For example:

      std::string safe_string(const char* ch)
      {
          if (!ch) { return ""; }
          return std::string(ch);
      }
      std::string uri::database() const {
          return safe_string(libmongoc::uri_get_database(_impl->uri_t));
      }
      

      But there are a bunch of design decisions here. Also, just glancing at the code in this file, I suspect that some other accessors on this class may be affected by the same issue.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: