summaryrefslogtreecommitdiff
path: root/src/mongo/bson/bsonobjbuilder.h
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-02-17 12:40:39 -0500
committerMathias Stearn <mathias@10gen.com>2015-03-05 13:22:19 -0500
commita0db9321139e8da657638ddbe7e86d8bac9ea3cc (patch)
tree07f2d51bcbf4985771463f697664525a55ab8b1e /src/mongo/bson/bsonobjbuilder.h
parentb2944efee1cf3b70da1dff3de14f09ea329da728 (diff)
downloadmongo-a0db9321139e8da657638ddbe7e86d8bac9ea3cc.tar.gz
SERVER-17224 Reserve room for EOO byte when starting BSONObj building
Since _done() is called from ~BSONObjBuilder we need to ensure that it cannot fail. This prevents a double exception leading to a std::terminate call. This also resolves SERVER-17226.
Diffstat (limited to 'src/mongo/bson/bsonobjbuilder.h')
-rw-r--r--src/mongo/bson/bsonobjbuilder.h23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/mongo/bson/bsonobjbuilder.h b/src/mongo/bson/bsonobjbuilder.h
index 5cd27a5a198..3c3cd7de363 100644
--- a/src/mongo/bson/bsonobjbuilder.h
+++ b/src/mongo/bson/bsonobjbuilder.h
@@ -68,10 +68,13 @@ namespace mongo {
, _s(this)
, _tracker(0)
, _doneCalled(false) {
- // Reserve space for a holder object at the beginning of the buffer, followed by
+ // Skip over space for a holder object at the beginning of the buffer, followed by
// space for the object length. The length is filled in by _done.
_b.skip(sizeof(BSONObj::Holder));
_b.skip(sizeof(int));
+
+ // Reserve space for the EOO byte. This means _done() can't fail.
+ _b.reserveBytes(1);
}
/** @param baseBuilder construct a BSONObjBuilder using an existing BufBuilder
@@ -84,9 +87,13 @@ namespace mongo {
, _s(this)
, _tracker(0)
, _doneCalled(false) {
- // Reserve space for the object length, which is filled in by _done. We don't need a holder
- // since we are a sub-builder, and some parent builder has already made the reservation.
+ // Skip over space for the object length, which is filled in by _done. We don't need a
+ // holder since we are a sub-builder, and some parent builder has already made the
+ // reservation.
_b.skip(sizeof(int));
+
+ // Reserve space for the EOO byte. This means _done() can't fail.
+ _b.reserveBytes(1);
}
BSONObjBuilder( const BSONSizeTracker & tracker )
@@ -99,6 +106,9 @@ namespace mongo {
// See the comments in the first constructor for details.
_b.skip(sizeof(BSONObj::Holder));
_b.skip(sizeof(int));
+
+ // Reserve space for the EOO byte. This means _done() can't fail.
+ _b.reserveBytes(1);
}
~BSONObjBuilder() {
@@ -622,6 +632,7 @@ namespace mongo {
BSONObj asTempObj() {
BSONObj temp(_done());
_b.setlen(_b.len()-1); //next append should overwrite the EOO
+ _b.reserveBytes(1); // Rereserve room for the real EOO
_doneCalled = false;
return temp;
}
@@ -703,8 +714,14 @@ namespace mongo {
return _b.buf() + _offset;
_doneCalled = true;
+
+ // TODO remove this or find some way to prevent it from failing. Since this is intended
+ // for use with BSON() literal queries, it is less likely to result in oversized BSON.
_s.endField();
+
+ _b.claimReservedBytes(1); // Prevents adding EOO from failing.
_b.appendNum((char) EOO);
+
char *data = _b.buf() + _offset;
int size = _b.len() - _offset;
DataView(data).writeLE(size);