[SERVER-14180] Crash with 'and' clause, $elemMatch, and nested $mod or regex Created: 05/Jun/14  Updated: 11/Mar/15  Resolved: 06/Jun/14

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 2.6.1
Fix Version/s: 2.6.2, 2.7.2

Type: Bug Priority: Major - P3
Reporter: Kamran K. Assignee: David Storch
Resolution: Done Votes: 0
Labels: 28qa
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Tested
Backwards Compatibility: Fully Compatible
Operating System: ALL
Backport Completed:
Steps To Reproduce:

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})

Participants:

 Description   
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



 Comments   
Comment by Githook User [ 06/Jun/14 ]

Author:

{u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}

Message: SERVER-14180 fix double free in access planning for $elemMatch

(cherry picked from commit 2453cec627bb8f6100980dea273ac9eb54ecd645)
Branch: v2.6
https://github.com/mongodb/mongo/commit/e52e4e2deb3732a7414cf64b9525843360f4c26d

Comment by Githook User [ 06/Jun/14 ]

Author:

{u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}

Message: SERVER-14180 fix double free in access planning for $elemMatch
Branch: master
https://github.com/mongodb/mongo/commit/2453cec627bb8f6100980dea273ac9eb54ecd645

Generated at Thu Feb 08 03:34:05 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.