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:
- is part of an 'and' clause and
- 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