diff options
author | Mathias Stearn <mathias@10gen.com> | 2015-02-17 12:40:39 -0500 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2015-03-05 13:22:19 -0500 |
commit | a0db9321139e8da657638ddbe7e86d8bac9ea3cc (patch) | |
tree | 07f2d51bcbf4985771463f697664525a55ab8b1e /src/mongo/bson/bsonobjbuilder.h | |
parent | b2944efee1cf3b70da1dff3de14f09ea329da728 (diff) | |
download | mongo-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.h | 23 |
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); |