diff options
author | Mathias Stearn <mathias@10gen.com> | 2013-05-03 15:44:54 -0400 |
---|---|---|
committer | Dan Pasette <dan@10gen.com> | 2013-05-13 01:29:19 -0400 |
commit | d6093148fceef8bf50556a2681dc6d2ff77ccb5f (patch) | |
tree | ad1ad4f24eb7abb948263f9c2a19b6fc25421eb9 | |
parent | 834f226a115f71c7f57d202efc2bf99dcc86509f (diff) | |
download | mongo-d6093148fceef8bf50556a2681dc6d2ff77ccb5f.tar.gz |
SERVER-9538 Only update BufBuilder's len if successfully grew
Otherwise BSONObj destructor will try to grow again to add EOO byte,
causing a double exception and terminate() call.
-rw-r--r-- | src/mongo/bson/util/builder.h | 11 | ||||
-rw-r--r-- | src/mongo/dbtests/jsobjtests.cpp | 22 |
2 files changed, 28 insertions, 5 deletions
diff --git a/src/mongo/bson/util/builder.h b/src/mongo/bson/util/builder.h index cfff6114980..a66a736bb5c 100644 --- a/src/mongo/bson/util/builder.h +++ b/src/mongo/bson/util/builder.h @@ -202,18 +202,19 @@ namespace mongo { /* returns the pre-grow write position */ inline char* grow(int by) { int oldlen = l; - l += by; - if ( l > size ) { - grow_reallocate(); + int newLen = l + by; + if ( newLen > size ) { + grow_reallocate(newLen); } + l = newLen; return data + oldlen; } private: /* "slow" portion of 'grow()' */ - void NOINLINE_DECL grow_reallocate() { + void NOINLINE_DECL grow_reallocate(int newLen) { int a = 64; - while( a < l ) + while( a < newLen ) a = a * 2; if ( a > BufferMaxSize ) { std::stringstream ss; diff --git a/src/mongo/dbtests/jsobjtests.cpp b/src/mongo/dbtests/jsobjtests.cpp index a2ea39bcb82..80b88831c47 100644 --- a/src/mongo/dbtests/jsobjtests.cpp +++ b/src/mongo/dbtests/jsobjtests.cpp @@ -2065,6 +2065,27 @@ namespace JsobjTests { } }; + class NestedBuilderOversize { + public: + void run() { + try { + BSONObjBuilder outer; + BSONObjBuilder inner(outer.subobjStart("inner")); + + string bigStr(1000, 'x'); + while (true) { + ASSERT_LESS_THAN_OR_EQUALS(inner.len(), BufferMaxSize); + inner.append("", bigStr); + } + + ASSERT(!"Expected Throw"); + } catch (const DBException& e) { + if (e.getCode() != 13548) // we expect the code for oversized buffer + throw; + } + } + }; + class All : public Suite { public: All() : Suite( "jsobj" ) { @@ -2166,6 +2187,7 @@ namespace JsobjTests { add< BSONForEachTest >(); add< CompareOps >(); add< HashingTest >(); + add< NestedBuilderOversize >(); } } myall; |