Skip to content

Commit

Permalink
SERVER-7769 - turn objcheck on by default and use new fast bson validate
Browse files Browse the repository at this point in the history
  • Loading branch information
erh committed Dec 20, 2012
1 parent 4be4883 commit f9817a6
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 40 deletions.
1 change: 1 addition & 0 deletions src/SConscript.client
Expand Up @@ -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",
Expand Down
10 changes: 9 additions & 1 deletion src/mongo/db/cmdline.cpp
Expand Up @@ -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)")
Expand Down Expand Up @@ -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.")
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/mongo/db/cmdline.h
Expand Up @@ -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)
Expand Down
22 changes: 15 additions & 7 deletions src/mongo/db/dbmessage.h
Expand Up @@ -23,6 +23,7 @@
#include "../util/net/message.h"
#include "../client/constants.h"
#include "instance.h"
#include "mongo/bson/bson_validate.h"

namespace mongo {

Expand Down Expand Up @@ -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;
Expand Down
36 changes: 7 additions & 29 deletions src/mongo/db/jsobj.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 5 additions & 1 deletion src/mongo/tools/tool.cpp
Expand Up @@ -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" ) ) ) );
Expand Down
2 changes: 1 addition & 1 deletion src/mongo/tools/tool.h
Expand Up @@ -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;
Expand Down

0 comments on commit f9817a6

Please sign in to comment.