summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2013-05-03 15:44:54 -0400
committerDan Pasette <dan@10gen.com>2013-05-13 01:29:19 -0400
commitd6093148fceef8bf50556a2681dc6d2ff77ccb5f (patch)
treead1ad4f24eb7abb948263f9c2a19b6fc25421eb9
parent834f226a115f71c7f57d202efc2bf99dcc86509f (diff)
downloadmongo-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.h11
-rw-r--r--src/mongo/dbtests/jsobjtests.cpp22
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;