diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SConscript.client | 1 | ||||
-rw-r--r-- | src/mongo/db/cmdline.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/cmdline.h | 2 | ||||
-rw-r--r-- | src/mongo/db/dbmessage.h | 22 | ||||
-rw-r--r-- | src/mongo/db/jsobj.cpp | 36 | ||||
-rw-r--r-- | src/mongo/tools/tool.cpp | 6 | ||||
-rw-r--r-- | src/mongo/tools/tool.h | 2 |
7 files changed, 39 insertions, 40 deletions
diff --git a/src/SConscript.client b/src/SConscript.client index 05a4bb85d7b..14403223d28 100644 --- a/src/SConscript.client +++ b/src/SConscript.client @@ -26,6 +26,7 @@ clientSource = [ 'mongo/base/parse_number.cpp', 'mongo/base/status.cpp', 'mongo/base/string_data.cpp', + 'mongo/bson/bson_validate.cpp', 'mongo/bson/oid.cpp', 'mongo/buildinfo.cpp', "mongo/client/authentication_table_common.cpp", diff --git a/src/mongo/db/cmdline.cpp b/src/mongo/db/cmdline.cpp index 56b92d82638..40c57e7daf7 100644 --- a/src/mongo/db/cmdline.cpp +++ b/src/mongo/db/cmdline.cpp @@ -79,7 +79,6 @@ namespace { ("port", po::value<int>(&cmdLine.port), portInfoBuilder.str().c_str()) ("bind_ip", po::value<string>(&cmdLine.bind_ip), "comma separated list of ip addresses to listen on - all local ips by default") ("maxConns",po::value<int>(), maxConnInfoBuilder.str().c_str()) - ("objcheck", "inspect client data for validity on receipt") ("logpath", po::value<string>() , "log file to send write to instead of stdout - has to be a file, not directory" ) ("logappend" , "append to logpath instead of over-writing" ) ("pidfilepath", po::value<string>(), "full path to pidfile (if not set, no pidfile is created)") @@ -110,6 +109,8 @@ namespace { // Extra hidden options hidden.add_options() + ("objcheck", "inspect client data for validity on receipt (DEFAULT)") + ("noobjcheck", "do NOT inspect client data for validity on receipt") ("traceExceptions", "log stack traces for every exception") ("enableExperimentalIndexStatsCmd", po::bool_switch(&cmdLine.experimental.indexStatsCmdEnabled), "EXPERIMENTAL (UNSUPPORTED). Enable command computing aggregate statistics on indexes.") @@ -319,6 +320,13 @@ namespace { if (params.count("objcheck")) { cmdLine.objcheck = true; } + if (params.count("noobjcheck")) { + if (params.count("objcheck")) { + out() << "can't have both --objcheck and --noobjcheck" << endl; + return false; + } + cmdLine.objcheck = false; + } if (params.count("bind_ip")) { // passing in wildcard is the same as default behavior; remove and warn diff --git a/src/mongo/db/cmdline.h b/src/mongo/db/cmdline.h index dbb54299e28..bf576fae708 100644 --- a/src/mongo/db/cmdline.h +++ b/src/mongo/db/cmdline.h @@ -189,7 +189,7 @@ namespace mongo { port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(true), quiet(false), noTableScan(false), prealloc(true), preallocj(true), smallfiles(sizeof(int*) == 4), configsvr(false), quota(false), quotaFiles(8), cpu(false), - durOptions(0), objcheck(false), oplogSize(0), defaultProfile(0), + durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0), slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), moveParanoia( true ), syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxConns(DEFAULT_MAX_CONN), logAppend(false), logWithSyslog(false) diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h index 7b0a802a27f..a582ec1e018 100644 --- a/src/mongo/db/dbmessage.h +++ b/src/mongo/db/dbmessage.h @@ -23,6 +23,7 @@ #include "../util/net/message.h" #include "../client/constants.h" #include "instance.h" +#include "mongo/bson/bson_validate.h" namespace mongo { @@ -196,14 +197,21 @@ namespace mongo { nextjsobj += strlen(data) + 1; // skip namespace massert( 13066 , "Message contains no documents", theEnd > nextjsobj ); } - massert( 10304 , "Client Error: Remaining data too small for BSON object", theEnd - nextjsobj > 3 ); - BSONObj js(nextjsobj); - massert( 10305 , "Client Error: Invalid object size", js.objsize() > 3 ); - massert( 10306 , "Client Error: Next object larger than space left in message", - js.objsize() < ( theEnd - data ) ); - if ( cmdLine.objcheck && !js.valid() ) { - massert( 10307 , "Client Error: bad object in message", false); + massert( 10304, + "Client Error: Remaining data too small for BSON object", + theEnd - nextjsobj >= 5 ); + + if ( cmdLine.objcheck ) { + Status status = validateBSON( nextjsobj, theEnd - nextjsobj, NULL ); + massert( 10307, + str::stream() << "Client Error: bad object in message: " << status.reason(), + status.isOK() ); } + + BSONObj js(nextjsobj); + verify( js.objsize() >= 5 ); + verify( js.objsize() < ( theEnd - data ) ); + nextjsobj += js.objsize(); if ( nextjsobj >= theEnd ) nextjsobj = 0; diff --git a/src/mongo/db/jsobj.cpp b/src/mongo/db/jsobj.cpp index cd4598cb5bf..a143cc2df1e 100644 --- a/src/mongo/db/jsobj.cpp +++ b/src/mongo/db/jsobj.cpp @@ -26,6 +26,7 @@ #include <boost/lexical_cast.hpp> #include <boost/static_assert.hpp> +#include "mongo/bson/bson_validate.h" #include "mongo/bson/oid.h" #include "mongo/bson/util/atomic_int.h" #include "mongo/db/jsobjmanipulator.h" @@ -462,35 +463,12 @@ namespace mongo { bool BSONObj::valid() const { int mySize = objsize(); - - try { - BSONObjIterator it(*this); - while( it.moreWithEOO() ) { - // both throw exception on failure - BSONElement e = it.next(true); - if ( e.size() >= mySize ) - return false; - - e.validate(); - - if (e.eoo()) { - if (it.moreWithEOO()) - return false; - return true; - } - else if (e.isABSONObj()) { - if(!e.embeddedObject().valid()) - return false; - } - else if (e.type() == CodeWScope) { - if(!e.codeWScopeObject().valid()) - return false; - } - } - } - catch (...) { - } - return false; + int otherSize; + Status status = validateBSON( objdata(), mySize, &otherSize ); + if ( ! status.isOK() ) + return false; + verify( mySize == otherSize ); // should be impossible + return true; } int BSONObj::woCompare(const BSONObj& r, const Ordering &o, bool considerFieldName) const { diff --git a/src/mongo/tools/tool.cpp b/src/mongo/tools/tool.cpp index 23f4ccf88c1..90206e8669e 100644 --- a/src/mongo/tools/tool.cpp +++ b/src/mongo/tools/tool.cpp @@ -441,13 +441,17 @@ namespace mongo { add_options() ("objcheck" , "validate object before inserting" ) + ("noobjcheck" , "validate object before inserting" ) ("filter" , po::value<string>() , "filter to apply before inserting" ) ; } int BSONTool::run() { - _objcheck = hasParam( "objcheck" ); + if ( hasParam( "objcheck" ) ) + _objcheck = true; + else if ( hasParam( "noobjcheck" ) ) + _objcheck = false; if ( hasParam( "filter" ) ) _matcher.reset( new Matcher( fromjson( getParam( "filter" ) ) ) ); diff --git a/src/mongo/tools/tool.h b/src/mongo/tools/tool.h index 65765eba940..b91485656f8 100644 --- a/src/mongo/tools/tool.h +++ b/src/mongo/tools/tool.h @@ -146,7 +146,7 @@ namespace mongo { auto_ptr<Matcher> _matcher; public: - BSONTool( const char * name , DBAccess access=ALL, bool objcheck = false ); + BSONTool( const char * name , DBAccess access=ALL, bool objcheck = true ); virtual int doRun() = 0; virtual void gotObject( const BSONObj& obj ) = 0; |