[SERVER-9803] Handle regular expression parse errors without seg faulting Created: 29/May/13  Updated: 24/Oct/19  Resolved: 27/Jul/13

Status: Closed
Project: Core Server
Component/s: JavaScript, Shell
Affects Version/s: None
Fix Version/s: 2.5.2

Type: Bug Priority: Minor - P4
Reporter: Mihai Lacatusu Assignee: Tad Marshall
Resolution: Done Votes: 0
Labels: regex, todo_in_code
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:
  1. uname -a
    Linux testvm1 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2 x86_64 GNU/Linux
  1. /opt/mongodb/bin/mongo --version
    MongoDB shell version: 2.4.3
  1. /opt/mongodb/bin/mongod --version
    db version v2.4.3
    Wed May 29 11:14:08.146 git version: fe1743177a5ea03e91e0052fb5e2cb2945f6d95f

Issue Links:
Related
related to SERVER-44197 Complete TODO listed in SERVER-9803 Closed
Operating System: ALL
Steps To Reproduce:

root@testvm1:~# /opt/mongodb/bin/mongo
MongoDB shell version: 2.4.3
connecting to: test
mongos> db.test_coll.insert([

{"name":"mihai"}

,

{"name":"foo"}

,

{"name":"bar"}

])
mongos> db.test_coll.count()
3
mongos> db.test_coll.find({"name" : {$regex: "(?i)^mih"}}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 3,
"nscanned" : 3,
"nscannedObjectsAllPlans" : 3,
"nscannedAllPlans" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {

},
"server" : "testvm1:2001",
"millis" : 0
}
mongos> db.test_coll.ensureIndex(

{"name":1}

)
mongos> db.test_coll.getIndexes()
[
{
"v" : 1,
"key" :

{ "_id" : 1 }

,
"ns" : "test.test_coll",
"name" : "id"
},
{
"v" : 1,
"key" :

{ "name" : 1 }

,
"ns" : "test.test_coll",
"name" : "name_1"
}
]
mongos> db.test_coll.find({"name" : {$regex: "(?i)^mih"}}).explain()
Wed May 29 11:04:05.464 mongo got signal 11 (Segmentation fault), stack trace:

Wed May 29 11:04:05.469 0x746df1 0x5dce32 0x7fee00e724f0 0x99d71c 0x7f3457 0x6ee4d3 0x6ee4c6 0x6f2b30 0x990293 0x98fc73 0x9ecc30 0x34df04206362
/opt/mongodb/bin/mongo(_ZN5mongo15printStackTraceERSo+0x21) [0x746df1]
/opt/mongodb/bin/mongo(_Z12quitAbruptlyi+0x382) [0x5dce32]
/lib/x86_64-linux-gnu/libc.so.6(+0x324f0) [0x7fee00e724f0]
/opt/mongodb/bin/mongo(_ZN2v88internal8JSObject10SetElementENS0_6HandleIS1_EEjNS2_INS0_6ObjectEEE18PropertyAttributesNS0_14StrictModeFlagENS0_15SetPropertyModeE+0x7c) [0x99d71c]
/opt/mongodb/bin/mongo(_ZN2v86Object3SetEjNS_6HandleINS_5ValueEEE+0xf7) [0x7f3457]
/opt/mongodb/bin/mongo(_ZN5mongo7V8Scope16mongoToV8ElementERKNS_11BSONElementEb+0x1113) [0x6ee4d3]
/opt/mongodb/bin/mongo(_ZN5mongo7V8Scope16mongoToV8ElementERKNS_11BSONElementEb+0x1106) [0x6ee4c6]
/opt/mongodb/bin/mongo() [0x6f2b30]
/opt/mongodb/bin/mongo(_ZN2v88internal8JSObject35GetPropertyAttributeWithInterceptorEPS1_PNS0_6StringEb+0x453) [0x990293]
/opt/mongodb/bin/mongo(_ZN2v88internal10JSReceiver32GetPropertyAttributeWithReceiverEPS1_PNS0_6StringE+0xb3) [0x98fc73]
/opt/mongodb/bin/mongo(_ZN2v88internal19Runtime_HasPropertyENS0_9ArgumentsEPNS0_7IsolateE+0x70) [0x9ecc30]
[0x34df04206362]

root@testvm1:~#

Participants:

 Description   

Do not seg fault when there is an error in parsing/creating regular expressions in javascript.

Old description
MongoDB shell client crashes when running a find(...).explain() query on a field which is indexed.
Reproduced on Debian 7 64 bit, on both MongoDB 2.4.1 and 2.4.3. Reproduced on both MongoDB standalone and mongos + replica set environment.



 Comments   
Comment by Tad Marshall [ 27/Jul/13 ]

I can't find anything actually broken at this point (after Mathias' fixes). The original report no longer produces bad behavior, and I get the expected SyntaxError when I try to use invalid Regex options.

> db.test_coll.stats()
{
        "ns" : "test.test_coll",
        "count" : 3,
        "size" : 112,
        "avgObjSize" : 37.333333333333336,
        "storageSize" : 4096,
        "numExtents" : 1,
        "nindexes" : 1,
        "lastExtentSize" : 4096,
        "paddingFactor" : 1,
        "systemFlags" : 1,
        "userFlags" : 0,
        "totalIndexSize" : 8176,
        "indexSizes" : {
                "_id_" : 8176
        },
        "ok" : 1
}
> db.test_coll.find()
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e5"), "name" : "mihai" }
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e6"), "name" : "foo" }
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e7"), "name" : "bar" }
> db.test_coll.find({"name" : {$regex: "(?i)^mih"}}).explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 3,
        "nscanned" : 3,
        "nscannedObjectsAllPlans" : 3,
        "nscannedAllPlans" : 3,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
 
        },
        "server" : "MissLucy:27017"
}
> db.test_coll.find({"name" : {$regex: "(?i)^mih"}})
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e5"), "name" : "mihai" }
> db.test_coll.find({"name" : {$regex: "(?i)^miH"}})
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e5"), "name" : "mihai" }
> db.test_coll.find({"name" : {$regex: "(?-i)^miH"}})
> db.test_coll.find({"name" : {$regex: "miH"}})
> db.test_coll.find({"name" : {$regex: "mih"}})
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e5"), "name" : "mihai" }
> db.test_coll.find({"name" : /miH/i})
{ "_id" : ObjectId("51a7251b6ddb78b24347f4e5"), "name" : "mihai" }
> db.test_coll.find({"name" : /miH/x})
Sat Jul 27 08:50:47.005 SyntaxError: Invalid flags supplied to RegExp constructor 'x'

We don't return RegExp objects as RegExp objects, but that seems like a separate issue. We do seem to parse them correctly and catch SyntaxErrors properly.

> db.eval("return /f/")
{ }
> db.eval("return /f/i")
{ }
> db.eval("return /f/x")
Sat Jul 27 08:54:59.176 {
        "errmsg" : "exception: SyntaxError: Invalid flags supplied to RegExp constructor 'x'",
        "code" : 16722,
        "ok" : 0
} at src/mongo/shell/db.js:645
>

I think that this issue should be resolved as Fixed and separate issues opened for other issues. We no longer segfault on invalid Regex expressions.

Comment by auto [ 19/Jun/13 ]

Author:

{u'username': u'RedBeard0531', u'name': u'Mathias Stearn', u'email': u'mathias@10gen.com'}

Message: SERVER-9878 Add type checks to V8 C++ bindings

The main focus of this ticket is tightening up input validation in
our V8 bindings. Doing this required normalizing the way we create
custom types in JS that have special C++-driven behavior. All special
types now use FunctionTemplates that are attached to the V8Scope object.
This allows us to test if an object is of the correct type before using
it.

Other related tickets partially addressed:
SERVER-8961 Differences in argument validation of custom types between v8 and Spidermonkey
SERVER-9803 Handle regular expression parse errors without seg faulting

Conflicts:

jstests/constructors.js
src/mongo/scripting/engine_v8.cpp
Branch: v2.4
https://github.com/mongodb/mongo/commit/7c1b35e0b2cc69c93074c6d1d76879b3ed525f56

Comment by auto [ 17/Jun/13 ]

Author:

{u'username': u'RedBeard0531', u'name': u'Mathias Stearn', u'email': u'mathias@10gen.com'}

Message: SERVER-9878 Add type checks to V8 C++ bindings

The main focus of this ticket is tightening up input validation in
our V8 bindings. Doing this required normalizing the way we create
custom types in JS that have special C++-driven behavior. All special
types now use FunctionTemplates that are attached to the V8Scope object.
This allows us to test if an object is of the correct type before using
it.

Other related tickets partially addressed:
SERVER-8961 Differences in argument validation of custom types between v8 and Spidermonkey
SERVER-9803 Handle regular expression parse errors without seg faulting
Branch: master
https://github.com/mongodb/mongo/commit/fda4a2342614e4ca1fb26c868a5adef0e050eb5e

Comment by Scott Hernandez (Inactive) [ 31/May/13 ]

That javascript engine (V8), and many other client languages, have different regular expression engines. This is one of those cases where support exists on the server (in one way), but the client cannot parse/create it. The $regex+$options separates things in a consistent way so each language can handle it explicitly but when you use the match group/option syntax it does not do this and can create "bad" regex strings (mixing options with the regular expression) that many langauges/clients cannot parse or which invalid.

The reason this fails in the shell is that the server sends back a regular expression object with the "(?i)" in the front just like you had in the explain output. This fails on the client (V8 javascript) when parsing the regex to display the explain results, and might fail on other clients/languages as well. But constructing the regular expression object in the native language (using RegExp(<expr>, <opts>) or /<expr>/<opts>) will produce the correct separation of options from expression, and not cause problems.

The goal of this issue to keep the client from seg faulting when there is an error in parsing/creating regular expressions.

Comment by Mihai Lacatusu [ 31/May/13 ]

Thanks I'll take your suggestion on changing the regex.

However I wouldn't say the regexp is "bad" because MongoDB documentation does state that "$regex uses PCRE as the matching engine", so (?i) syntax should be valid.
This seems to be true because the actual find query ( db.test_coll.find({"name" : {$regex: "(?i)^mih"}}) ) does work and return correct results. Only the explain crashes.

Comment by Scott Hernandez (Inactive) [ 30/May/13 ]

Also note that the correct $regex format for your query is {$regex:"^mih", $options:"i"} as defined here: http://docs.mongodb.org/manual/reference/operator/regex/

Comment by Tad Marshall [ 30/May/13 ]

Hi Mihai,

Thanks for the report!

I reproduced your crash in the current master branch (testing a debug version on Windows in the debugger).

mongo shell:

MongoDB shell version: 2.5.1-pre-
connecting to: test
Server has startup warnings:
Thu May 30 06:20:00.341 [initandlisten]
Thu May 30 06:20:00.342 [initandlisten] ** NOTE: This is a development version (2.5.1-pre-) of MongoDB.
Thu May 30 06:20:00.343 [initandlisten] **       Not recommended for production.
Thu May 30 06:20:00.343 [initandlisten]
> db.test_coll.insert([{"name":"mihai"}, {"name":"foo"}, {"name":"bar"}])
> db.test_coll.count()
3
> db.test_coll.find({"name" : {$regex: "(?i)^mih"}}).explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 3,
        "nscanned" : 3,
        "nscannedObjectsAllPlans" : 3,
        "nscannedAllPlans" : 3,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
 
        },
        "server" : "MissLucy:27017"
}
> db.test_coll.ensureIndex({"name":1})
> db.test_coll.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "ns" : "test.test_coll",
                "name" : "_id_"
        },
        {
                "v" : 1,
                "key" : {
                        "name" : 1
                },
                "ns" : "test.test_coll",
                "name" : "name_1"
        }
]
> db.test_coll.find({"name" : {$regex: "(?i)^mih"}}).explain()
 
 
#
# Fatal error in ..\..\third_party\v8\src\api.cc, line 2787
# CHECK(!(isolate)->external_caught_exception()) failed
#
 
 
==== Stack trace ============================================
 
Security context: 00000000D1706361 <JS Object>#0#
    1: FILTER_KEY [native runtime.js:400] (this=00000000F3F51ED1 <JS Object>#1#,a=00000000F3F543D1 <String[4]: name>)
    2: tojsonObject [shell/types.js:612] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51ED1 <JS Object>#1#,indent=00000000F3F54391 <String[2]\: \x09\x09>,nolint=000000
00D1704121 <undefined>)
    3: tojson [shell/types.js:560] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51ED1 <JS Object>#1#,indent=00000000DEF2AA99 <String[1]\: \x09>,nolint=00000000D1704121
 <undefined>)
    4: tojsonObject [shell/types.js:630] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#,indent=00000000DEF2AA99 <String[1]\: \x09>,nolint=00000000D1
704121 <undefined>)
    5: tojson [shell/types.js:560] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#,indent=00000000DEF044E1 <String[0]: >,nolint=00000000D1704121 <und
efined>)
    6: arguments adaptor frame: 1->3
    7: shellPrintHelper [shell/utils.js:558] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#)
    8: /* anonymous */ [(shell2):1] (this=00000000D1706479 <JS Global Object>#2#)
 
==== Details ================================================
 
[1]: FILTER_KEY [native runtime.js:400] (this=00000000F3F51ED1 <JS Object>#1#,a=00000000F3F543D1 <String[4]: name>) {
  // stack-allocated locals
  var b = 00000000F3F543D1 <String[4]: name>
  // expression stack (top to bottom)
  [02] : 00000000F3F543D1 <String[4]: name>
  [01] : 00000000F3F51ED1 <JS Object>#1#
--------- s o u r c e   c o d e ---------
function FILTER_KEY(a){?var b=%ToString(a);?if(%HasProperty(this,b))return b;?return 0;?}
-----------------------------------------
}
 
[2]: tojsonObject [shell/types.js:612] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51ED1 <JS Object>#1#,indent=00000000F3F54391 <String[2]\: \x09\x09>,nolint=00000000
D1704121 <undefined>) {
  // stack-allocated locals
  var val = 00000000D1704121 <undefined>
  var k = 00000000D1704121 <undefined>
  var lineEnding = 00000000DEF16C61 <String[1]\: \n>
  var tabSpace = 00000000DEF2AA99 <String[1]\: \x09>
  var s = 00000000DEF1A351 <String[2]\: {\n>
  var total = 0
  var num = 00000000D1704121 <undefined>
  var keys = 00000000D1704121 <undefined>
  // expression stack (top to bottom)
  [14] : 00000000F3F543D1 <String[4]: name>
  [13] : 00000000F3F51ED1 <JS Object>#1#
  [12] : 0
  [11] : 1
  [10] : 00000000F3F544A9 <FixedArray[1]>#4#
  [09] : 1
  [08] : 00000000F3F51ED1 <JS Object>#1#
--------- s o u r c e   c o d e ---------
function (x, indent, nolint){?    var lineEnding = nolint ? " " : "\n";?    var tabSpace = nolint ? "" : "\t";?    assert.eq((typeof x), "object", "tojsonObject needs object, not [
" + (typeof x) + "]");??    if (!indent)?        indent = "";??    if (typeof(x.tojson) == "function" && x.tojson != tojson) {?  ...
 
-----------------------------------------
}
 
[3]: tojson [shell/types.js:560] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51ED1 <JS Object>#1#,indent=00000000DEF2AA99 <String[1]\: \x09>,nolint=00000000D1704121 <
undefined>) {
  // stack-allocated locals
  var code = 00000000D1704121 <undefined>
  var i = 00000000D1704121 <undefined>
  var s = 00000000D1704121 <undefined>
  var out = 00000000D1704121 <undefined>
  // expression stack (top to bottom)
  [07] : 00000000D1704121 <undefined>
  [06] : 00000000F3F54391 <String[2]\: \x09\x09>
  [05] : 00000000F3F51ED1 <JS Object>#1#
  [04] : 00000000D1706479 <JS Global Object>#2#
--------- s o u r c e   c o d e ---------
function (x, indent, nolint){?    if (x === null)?        return "null";??    if (x === undefined)?        return "undefined";??    if (!indent)?        indent = "";??    switch (t
ypeof x) {?    case "string": {?        var out = new Array(x.length+1);?        out[0] = '"';?        for (var i=0; i<x.length; ...
 
-----------------------------------------
}
 
[4]: tojsonObject [shell/types.js:630] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#,indent=00000000DEF2AA99 <String[1]\: \x09>,nolint=00000000D170
4121 <undefined>) {
  // stack-allocated locals
  var val = 00000000F3F51ED1 <JS Object>#1#
  var k = 00000000F3F52509 <String[11]: indexBounds>
  var lineEnding = 00000000DEF16C61 <String[1]\: \n>
  var tabSpace = 00000000DEF2AA99 <String[1]\: \x09>
  var s = 00000000F3F541B9 <String[271]\: {\n\x09"cursor" : "BtreeCursor name_1 multi",\n\x09"isMultiKey" : false,\n\x09"n" : 1,\n\x09"nscannedObjects" : 1,\n\x09"nscanned" : 3,\n\
x09"nscannedObjectsAllPlans" : 1,\n\x09"nscannedAllPlans" : 3,\n\x09"scanAndOrder" : false,\n\x09"indexOnly" : false,\n\x09"nYields" : 0,\n\x09"nChunkSkips" : 0,\n\x09"millis" : 1,
\n>
  var total = 14
  var num = 13
  var keys = 00000000F3F51449 <JS Object>#3#
  // expression stack (top to bottom)
  [18] : 00000000D1704121 <undefined>
  [17] : 00000000DEF2AA99 <String[1]\: \x09>
  [16] : 00000000F3F51ED1 <JS Object>#1#
  [15] : 00000000D1706479 <JS Global Object>#2#
  [14] : 00000000F3F54229 <String[17]\: \x09"indexBounds" : >
  [13] : 00000000F3F541B9 <String[271]\: {\n\x09"cursor" : "BtreeCursor name_1 multi",\n\x09"isMultiKey" : false,\n\x09"n" : 1,\n\x09"nscannedObjects" : 1,\n\x09"nscanned" : 3,\n\x
09"nscannedObjectsAllPlans" : 1,\n\x09"nscannedAllPlans" : 3,\n\x09"scanAndOrder" : false,\n\x09"indexOnly" : false,\n\x09"nYields" : 0,\n\x09"nChunkSkips" : 0,\n\x09"millis" : 1,\
n>
  [12] : 12
  [11] : 14
  [10] : 00000000F3F52771 <FixedArray[14]>#5#
  [09] : 1
  [08] : 00000000F3F51449 <JS Object>#3#
--------- s o u r c e   c o d e ---------
function (x, indent, nolint){?    var lineEnding = nolint ? " " : "\n";?    var tabSpace = nolint ? "" : "\t";?    assert.eq((typeof x), "object", "tojsonObject needs object, not [
" + (typeof x) + "]");??    if (!indent)?        indent = "";??    if (typeof(x.tojson) == "function" && x.tojson != tojson) {?  ...
 
-----------------------------------------
}
 
[5]: tojson [shell/types.js:560] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#,indent=00000000DEF044E1 <String[0]: >,nolint=00000000D1704121 <undef
ined>) {
  // stack-allocated locals
  var code = 00000000D1704121 <undefined>
  var i = 00000000D1704121 <undefined>
  var s = 00000000D1704121 <undefined>
  var out = 00000000D1704121 <undefined>
  // expression stack (top to bottom)
  [07] : 00000000D1704121 <undefined>
  [06] : 00000000DEF2AA99 <String[1]\: \x09>
  [05] : 00000000F3F51449 <JS Object>#3#
  [04] : 00000000D1706479 <JS Global Object>#2#
--------- s o u r c e   c o d e ---------
function (x, indent, nolint){?    if (x === null)?        return "null";??    if (x === undefined)?        return "undefined";??    if (!indent)?        indent = "";??    switch (t
ypeof x) {?    case "string": {?        var out = new Array(x.length+1);?        out[0] = '"';?        for (var i=0; i<x.length; ...
 
-----------------------------------------
}
 
[6]: arguments adaptor frame: 1->3 {
  // actual arguments
  [00] : 00000000F3F51449 <JS Object>#3#
}
 
[7]: shellPrintHelper [shell/utils.js:558] (this=00000000D1706479 <JS Global Object>#2#,x=00000000F3F51449 <JS Object>#3#) {
  // stack-allocated locals
  var err = 00000000D1704121 <undefined>
  var p = 00000000D1704121 <undefined>
  // expression stack (top to bottom)
  [04] : 00000000F3F51449 <JS Object>#3#
  [03] : 00000000D1706479 <JS Global Object>#2#
  [02] : 00000000D1706361 <JS Object>#0#
--------- s o u r c e   c o d e ---------
function (x) {?    if (typeof (x) == "undefined") {?        // Make sure that we have a db var before we use it?        // TODO: This implicit calling of GLE can cause subtle, hard
 to track issues - remove??        if (__callLastError && typeof( db ) != "undefined" && db.getMongo ) {?            __callLastEr...
 
-----------------------------------------
}
 
[8]: /* anonymous */ [(shell2):1] (this=00000000D1706479 <JS Global Object>#2#) {
  // stack-allocated locals
  var .result = 00000000D1704121 <undefined>
  // expression stack (top to bottom)
  [02] : 00000000F3F51449 <JS Object>#3#
  [01] : 00000000D1706479 <JS Global Object>#2#
--------- s o u r c e   c o d e ---------
shellPrintHelper( __lastres__ );
-----------------------------------------
}
 
==== Key         ============================================
 
 #0# 00000000D1706361: 00000000D1706361 <JS Object>
 #1# 00000000F3F51ED1: 00000000F3F51ED1 <JS Object>
 #2# 00000000D1706479: 00000000D1706479 <JS Global Object>
 #3# 00000000F3F51449: 00000000F3F51449 <JS Object>
 #4# 00000000F3F544A9: 00000000F3F544A9 <FixedArray[1]>
                 0: 00000000F3F543D1 <String[4]: name>
 #5# 00000000F3F52771: 00000000F3F52771 <FixedArray[14]>
                 0: 00000000F3F522D1 <String[6]: cursor>
                 1: 00000000F3F52389 <String[10]: isMultiKey>
                 2: 00000000DEF0ED79 <String[1]: n>
                 3: 00000000F3F523B1 <String[15]: nscannedObjects>
                 4: 00000000F3F523D9 <String[8]: nscanned>
                 5: 00000000F3F523F9 <String[23]: nscannedObjectsAllPlans>
                 6: 00000000F3F52429 <String[16]: nscannedAllPlans>
                 7: 00000000F3F52451 <String[12]: scanAndOrder>
                 8: 00000000F3F52479 <String[9]: indexOnly>
                 9: 00000000F3F524A1 <String[7]: nYields>
                  ...
=====================

Program call stack from debugger:

>Debug.ListCallStack
 Index  Function
--------------------------------------------------------------------------------
*1      mongo.exe!v8::internal::OS::DebugBreak() 
 2      mongo.exe!v8::internal::OS::Abort() 
 3      mongo.exe!V8_Fatal(const char * file=0x000000014034c170, int line=0x00000ae3, const char * format=0x000000014034c158, ...) 
 4      mongo.exe!v8::Object::Set(unsigned int index=0x00000000, v8::Handle<v8::Value> value={...}) 
 5      mongo.exe!mongo::V8Scope::mongoToV8Element(const mongo::BSONElement & elem={...}, bool readOnly=false) 
 6      mongo.exe!mongo::V8Scope::mongoToV8Element(const mongo::BSONElement & elem={...}, bool readOnly=false) 
 7      mongo.exe!mongo::namedGet(v8::Local<v8::String> name={...}, const v8::AccessorInfo & info={...}) 
 8      mongo.exe!v8::internal::JSObject::GetPropertyAttributeWithInterceptor(v8::internal::JSObject * receiver=0x00000000f3f51ed1, v8::internal::String * name=0x00000000f3f543d1, bool continue_search=true) 
 9      mongo.exe!v8::internal::JSReceiver::GetPropertyAttribute(v8::internal::JSReceiver * receiver=0x00000000f3f51ed1, v8::internal::LookupResult * result=0x000000000015cea8, v8::internal::String * name=0x00000000f3f543d1, bool continue_search=true) 
 10     mongo.exe!v8::internal::JSReceiver::GetPropertyAttributeWithReceiver(v8::internal::JSReceiver * receiver=0x00000000f3f51ed1, v8::internal::String * key=0x00000000f3f543d1) 
 11     mongo.exe!v8::internal::JSReceiver::GetPropertyAttribute(v8::internal::String * key=0x00000000f3f543d1) 
 12     mongo.exe!v8::internal::JSReceiver::HasProperty(v8::internal::String * name=0x00000000f3f543d1) 
 13     mongo.exe!v8::internal::Runtime_HasProperty(v8::internal::Arguments args={...}, v8::internal::Isolate * isolate=0x0000000001b46190) 
 14     00000000fc40636c()
 15     000000000015d030()
 16     0000000001b46190()
 17     cccccccccccccccc()
 18     000000000201d448()
 19     0000000000000002()
 20     000000000015d068()
 21     00000000fc4062c1()
 22     000000000015d010()
 23     000000000015d088()
 24     00000000fc4173de()
 25     00000000f3f543d1()
 26     00000000f3f51ed1()
 27     00000000f3f543d1()
 28     00000000d170a429()
 29     00000000f3f0c679()
 30     000000000015d120()
 31     00000000fc45864b()
 32     00000000f3f543d1()
 33     00000000f3f51ed1()
 
>

The fatal error is thrown by V8 because we are trying to use the Set API function to associate a zero V8 handle to store data for a BSON object. Our code has called mongoToV8Element(subElem, readOnly) and this function has returned a NULL handle, but we do not check for this before calling V8 to store it.

It seems that the flavor of regular expression provided by V8 does not support the expression you are providing.

> var r = new RegExp("(?i)^mih")
Thu May 30 06:59:47.516 SyntaxError: Invalid regular expression: /(?i)^mih/: Invalid group

This is a shortcoming of V8 in the version that we are using.

The bug in MongoDB is that the code assumes that an attempt to construct a RegExp value will succeed and return a valid handle. This regular expression (using the mode modifier "(?i)" for case insensitivity) does not succeed in producing a V8 object, and when the code tries to store the NULL handle V8 throws a fatal error, aborting the shell.

The code that is trying to store the NULL value in this case is in src/mongo/scripting/engine_v8.cpp in lines 1389 to 1394:

            v8::Handle<v8::Array> array = v8::Array::New();
            int i = 0;
            BSONForEach(subElem, elem.embeddedObject()) {
                array->Set(i++, mongoToV8Element(subElem, readOnly));
            }
            return array;

Tad

Comment by Scott Hernandez (Inactive) [ 29/May/13 ]

I also found that when using the regex object in javascript I did not get the error, so you can do that as well.

Comment by Mihai Lacatusu [ 29/May/13 ]

I'll run the explains from python to workaround this one - thanks Scott.

Comment by Scott Hernandez (Inactive) [ 29/May/13 ]

You will want to use the python RegexObject type: http://docs.python.org/2/library/re.html#re.RegexObject

You can also use the python shell to do the explain if you want to use the same query or code and do it in python. http://api.mongodb.org/python/current/api/pymongo/cursor.html#pymongo.cursor.Cursor.explain

Comment by Mihai Lacatusu [ 29/May/13 ]

Thanks Scott. I confirm, this does not affect the server, but only the shell client. Sorry if this bug report was placed in the wrong module.

I was running the query using the $regex wrapper because I was profiling the exact same queries executed by our Python code. It seems that the /<regex>/<options> syntax doesn't work through pymongo.

So we're using $regex wrapper and the goal of my profiling was to make sure that this query makes use of an index.

Are these 2 syntaxes 100% equivalent at MongoDB query engine level? How can I get the explain() output for the $regex syntax?

Thanks in advance!

Comment by Scott Hernandez (Inactive) [ 29/May/13 ]

The seg fault is just for the mongo process, not the server process as far as I can see. Please confirm that this is not affecting the server, but just the client.

Also, in the shell I think you want this query using the javascript regex object (/<regex>/<options>), and not the special $regex wrapper:

db.test_coll.find({"name" : /^mih/i}).explain()

Are you storing any "name" values which are regular expressions themselves? If not you def. don't want the syntax you are using.

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