Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-14180

Crash with 'and' clause, $elemMatch, and nested $mod or regex

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.6.2, 2.7.2
    • Affects Version/s: 2.6.1
    • Component/s: Querying
    • Fully Compatible
    • ALL
    • Hide
      var t = db.elemMatchCrash;
      t.drop();
      
      t.ensureIndex({'a.b': 1});
      
      // one potential repro with regular expressions
      t.find({a: {$elemMatch: {b: /foo/}}, z:1})
      
      // alternative repro with $mod
      t.find({a: {$elemMatch: {b: {$mod: [1, 1]}}}, z:1})
      
      Show
      var t = db.elemMatchCrash; t.drop(); t.ensureIndex({'a.b': 1}); // one potential repro with regular expressions t.find({a: {$elemMatch: {b: /foo/}}, z:1}) // alternative repro with $mod t.find({a: {$elemMatch: {b: {$mod: [1, 1]}}}, z:1})

      Issue Status as of Jun 06, 2014

      ISSUE SUMMARY
      A query on an indexed field with an $elemMatch clause can crash the server if the $elemMatch clause is part of an 'and' clause and contains a nested $mod expression or a regular expression (regex).

      Example for regex case:

      db.coll.ensureIndex({'a.b': 1});
      db.coll.find({a: {$elemMatch: {b: /foo/}}, z:1})
      

      USER IMPACT
      A single query can crash the server, which has an effect on replica set quorum and can in the worst case lead to unavailability of a replica set.

      WORKAROUNDS

      AFFECTED VERSIONS
      Versions 2.6.0 and 2.6.1 are affected by this issue.

      FIX VERSION
      The fix is included in the 2.6.2 production release.

      RESOLUTION DETAILS
      Removed a double 'free' in the access planning code for $elemMatch. We now ensure that we never affix filters from inside an $elemMatch to index scan query solution nodes.

      Original description

      The server crashes when you query against an indexed field with an elemMatch clause that:

      1. is part of an 'and' clause and
      2. contains a nested $mod expression or regex

      Note: There may be other nested expressions that trigger the crash, but regular expressions and $mod were the only ones I found that triggered the crash. This bug does not affect 2.4.10.


      Backtrace:

      * thread #2: tid = 0x10b576, 0x0000000000000000, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
        * frame #0: 0x0000000000000000
          frame #1: 0x0000000100342139 mongod`~ElemMatchObjectMatchExpression [inlined] void boost::checked_delete<mongo::MatchExpression>(x=<unavailable>) + 41 at checked_delete.hpp:39
          frame #2: 0x0000000100342130 mongod`~ElemMatchObjectMatchExpression [inlined] ~scoped_ptr + 12 at scoped_ptr.hpp:80
          frame #3: 0x0000000100342124 mongod`~ElemMatchObjectMatchExpression [inlined] ~scoped_ptr at scoped_ptr.hpp:76
          frame #4: 0x0000000100342124 mongod`~ElemMatchObjectMatchExpression(this=0x0000000104bc8480) + 20 at expression_array.h:71
          frame #5: 0x000000010034169f mongod`~ElemMatchObjectMatchExpression(this=0x0000000104bc8480) + 15 at expression_array.h:71
          frame #6: 0x0000000100354115 mongod`~ListOfMatchExpression(this=0x0000000104c9e5d0) + 69 at expression_tree.cpp:42
          frame #7: 0x00000001003548df mongod`~AndMatchExpression(this=0x0000000104c9e5d0) + 15 at expression_tree.h:77
          frame #8: 0x000000010048b1e9 mongod`~QuerySolutionNode [inlined] void boost::checked_delete<mongo::MatchExpression>(x=<unavailable>) + 121 at checked_delete.hpp:39
          frame #9: 0x000000010048b1dd mongod`~QuerySolutionNode [inlined] ~scoped_ptr + 9 at scoped_ptr.hpp:80
          frame #10: 0x000000010048b1d4 mongod`~QuerySolutionNode [inlined] ~scoped_ptr at scoped_ptr.hpp:76
          frame #11: 0x000000010048b1d4 mongod`~QuerySolutionNode(this=0x0000000104b14ae0) + 100 at query_solution.h:53
          frame #12: 0x00000001004ad90a mongod`~FetchNode(this=0x0000000104b14ae0) + 90 at bsonobj.h:524
          frame #13: 0x000000010048b1b5 mongod`~QuerySolutionNode(this=0x0000000104b14ba0) + 69 at query_solution.h:51
          frame #14: 0x00000001004ad38a mongod`~KeepMutationsNode(this=0x0000000104b14ba0) + 90 at bsonobj.h:524
          frame #15: 0x0000000100283117 mongod`~QuerySolution [inlined] void boost::checked_delete<mongo::QuerySolutionNode>(x=<unavailable>) + 135 at checked_delete.hpp:39
          frame #16: 0x0000000100283111 mongod`~QuerySolution [inlined] ~scoped_ptr + 8 at scoped_ptr.hpp:80
          frame #17: 0x0000000100283109 mongod`~QuerySolution [inlined] ~scoped_ptr + 103 at scoped_ptr.hpp:76
          frame #18: 0x00000001002830a2 mongod`~QuerySolution(this=<unavailable>) + 18 at query_solution.h:174
          frame #19: 0x00000001004ae7c1 mongod`~SingleSolutionRunner [inlined] ~scoped_ptr + 17 at scoped_ptr.hpp:80
          frame #20: 0x00000001004ae7b0 mongod`~SingleSolutionRunner [inlined] ~scoped_ptr + 25 at scoped_ptr.hpp:76
          frame #21: 0x00000001004ae797 mongod`~SingleSolutionRunner(this=0x0000000104c9e5a0) + 23 at single_solution_runner.cpp:53
          frame #22: 0x00000001004ae74f mongod`~SingleSolutionRunner(this=0x0000000104c9e5a0) + 15 at single_solution_runner.cpp:53
          frame #23: 0x000000010046c37e mongod`mongo::newRunQuery(mongo::Message&, mongo::QueryMessage&, mongo::CurOp&, mongo::Message&) [inlined] ~auto_ptr + 8286 at memory:259
          frame #24: 0x000000010046c366 mongod`mongo::newRunQuery(mongo::Message&, mongo::QueryMessage&, mongo::CurOp&, mongo::Message&) [inlined] ~scoped_ptr(this=0x0000000104bc77e8, this=0x0000000104bc77e8, this=0x00007fff9754f2db, this=0x000000010628c7b0, this=0x0000000104b1bdb0, this=0x0000000104b1bdb0, this=0x0000000104bc7668, this=0x0000000000000000, this=0x0000000000000000, this=0x0000000104b3f825, this=0x0000000104b3f825, this=0x0000000000000000, this=0x0000000000000000) + 208 at memory:259
          frame #25: 0x000000010046c296 mongod`mongo::newRunQuery(m=<unavailable>, q=<unavailable>, curop=<unavailable>, result=<unavailable>) + 8054 at new_find.cpp:824
          frame #26: 0x0000000100304682 mongod`mongo::assembleResponse(mongo::Message&, mongo::DbResponse&, mongo::HostAndPort const&) [inlined] mongo::receivedQuery(mongo::Client&, mongo::DbResponse&, mongo::Message&) + 201 at instance.cpp:269
          frame #27: 0x00000001003045b9 mongod`mongo::assembleResponse(m=<unavailable>, dbresponse=0x000000010628cb90, remote=<unavailable>) + 1289 at instance.cpp:434
          frame #28: 0x000000010000e277 mongod`mongo::MyMessageHandler::process(this=<unavailable>, m=0x000000010628cd68, port=0x0000000104b1b450, le=0x0000000104b1b900) + 183 at db.cpp:202
          frame #29: 0x000000010078d0e1 mongod`mongo::PortMessageServer::handleIncomingMsg(arg=0x0000000104bdf8c0) + 929 at message_server_port.cpp:209
          frame #30: 0x000000010080e081 mongod`boost::(anonymous namespace)::thread_proxy(param=<unavailable>) + 177 at thread.cpp:121
          frame #31: 0x00007fff92094899 libsystem_pthread.dylib`_pthread_body + 138
          frame #32: 0x00007fff9209472a libsystem_pthread.dylib`_pthread_start + 137
      

      Version: 3b612717c5a5819dce90ccf6d02883108979488e

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            kamran.khan Kamran K.
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: