diff options
-rw-r--r-- | src/mongo/db/field_parser.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/field_parser_test.cpp | 19 | ||||
-rw-r--r-- | src/mongo/db/namespace_string-inl.h | 15 | ||||
-rw-r--r-- | src/mongo/db/namespace_string_test.cpp | 2 |
4 files changed, 36 insertions, 3 deletions
diff --git a/src/mongo/db/field_parser.cpp b/src/mongo/db/field_parser.cpp index 7a3a61b3203..3d300db2ead 100644 --- a/src/mongo/db/field_parser.cpp +++ b/src/mongo/db/field_parser.cpp @@ -150,7 +150,8 @@ namespace mongo { } if (elem.type() == String) { - *out = elem.valuestr(); + // Extract everything, including embedded null characters. + *out = string(elem.valuestr(), elem.valuestrsize() - 1); return FIELD_SET; } diff --git a/src/mongo/db/field_parser_test.cpp b/src/mongo/db/field_parser_test.cpp index 1a458c3960e..9e3f974c915 100644 --- a/src/mongo/db/field_parser_test.cpp +++ b/src/mongo/db/field_parser_test.cpp @@ -422,4 +422,23 @@ namespace { ASSERT_NOT_EQUALS(errMsg, ""); } + TEST(EdgeCases, EmbeddedNullStrings) { + + // Test extraction of string values with embedded nulls. + BSONField<string> field("testStr"); + + const char* str = "a\0c"; + const size_t strSize = 4; + BSONObjBuilder doc; + doc.append(field(), str, strSize); + BSONObj obj(doc.obj()); + + string parsed; + string errMsg; + ASSERT(FieldParser::extract(obj, field, &parsed, &errMsg)); + + ASSERT_EQUALS(0, memcmp(parsed.data(), str, strSize)); + ASSERT_EQUALS(errMsg, ""); + } + } // unnamed namespace diff --git a/src/mongo/db/namespace_string-inl.h b/src/mongo/db/namespace_string-inl.h index 5a03f6d9930..597d9a93159 100644 --- a/src/mongo/db/namespace_string-inl.h +++ b/src/mongo/db/namespace_string-inl.h @@ -99,8 +99,18 @@ namespace mongo { if (coll.empty()) return false; - return coll.find('$') == std::string::npos; + for (StringData::const_iterator iter = coll.begin(), end = coll.end(); + iter != end; ++iter) { + switch (*iter) { + case '\0': + case '$': + return false; + default: + continue; + } + } + return true; } inline NamespaceString::NamespaceString() : _ns(), _dotIndex(0) {} @@ -126,7 +136,8 @@ namespace mongo { _dotIndex = dbName.size(); dassert(it == _ns.end()); dassert(_ns[_dotIndex] == '.'); - dassert(_ns.find('\0') == std::string::npos); + uassert(17295, "namespaces cannot have embedded null characters", + _ns.find('\0') == std::string::npos); } inline int nsDBHash( const std::string& ns ) { diff --git a/src/mongo/db/namespace_string_test.cpp b/src/mongo/db/namespace_string_test.cpp index 74a65b6d70a..e3d6ebf8e36 100644 --- a/src/mongo/db/namespace_string_test.cpp +++ b/src/mongo/db/namespace_string_test.cpp @@ -59,6 +59,7 @@ namespace mongo { ASSERT( !NamespaceString::validDBName( "foo.bar" ) ); ASSERT( !NamespaceString::validDBName( "foo\\bar" ) ); ASSERT( !NamespaceString::validDBName( "foo\"bar" ) ); + ASSERT( !NamespaceString::validDBName( StringData( "a\0", 4 ) ) ); #ifdef _WIN32 ASSERT( !NamespaceString::validDBName( "foo*bar" ) ); ASSERT( !NamespaceString::validDBName( "foo<bar" ) ); @@ -88,6 +89,7 @@ namespace mongo { ASSERT( !NamespaceString::validCollectionName( "$a" ) ); ASSERT( !NamespaceString::validCollectionName( "a$b" ) ); ASSERT( !NamespaceString::validCollectionName( "" ) ); + ASSERT( !NamespaceString::validCollectionName( StringData( "a\0", 4 ) ) ); } TEST( NamespaceStringTest, DBHash ) { |