summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 cce567d04da..aba90c8ae02 100644
--- a/src/mongo/dbtests/jsobjtests.cpp
+++ b/src/mongo/dbtests/jsobjtests.cpp
@@ -2064,6 +2064,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" ) {
@@ -2165,6 +2186,7 @@ namespace JsobjTests {
add< BSONForEachTest >();
add< CompareOps >();
add< HashingTest >();
+ add< NestedBuilderOversize >();
}
} myall;