Skip to content

Commit 38257f7

Browse files
committed
CXX-559 Backport server r3.0.0-rc6..r3.0.1 changes
Server SHAs cherry-picked into this commit: 656c47b 43ea13b 5285225 ac7d4ea 77c5493 33afe7a 8f6875a 0cbcdfd
1 parent e23ec16 commit 38257f7

File tree

7 files changed

+103
-21
lines changed

7 files changed

+103
-21
lines changed

SConstruct

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,7 @@ add_option('variables-help',
246246
"Print the help text for SCons variables", 0, False)
247247

248248
if darwin:
249-
osx_version_choices = ['10.6', '10.7', '10.8', '10.9', '10.10']
250-
251-
my_version, _, _ = py_platform.mac_ver()
252-
my_version = '.'.join(my_version.split('.')[:2])
253-
254-
add_option("osx-version-min",
255-
"minimum OS X version to support, defaults to current version", 1, True,
256-
type = 'choice', default = my_version, choices = osx_version_choices)
249+
add_option("osx-version-min", "minimum OS X version to support", 1, True)
257250

258251
elif windows:
259252
win_version_min_choices = {
@@ -366,7 +359,7 @@ if buildDir[0] not in ['$', '#']:
366359

367360
cacheDir = get_option('cache-dir').rstrip('/')
368361
if cacheDir[0] not in ['$', '#']:
369-
if not os.path.isabs(cachdDIr):
362+
if not os.path.isabs(cacheDir):
370363
print("Do not use relative paths with --cache-dir")
371364
Exit(1)
372365

src/mongo/bson/bson_validate.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <cstring>
1919
#include <deque>
20+
#include <limits>
2021

2122
#include "mongo/base/data_view.h"
2223
#include "mongo/bson/bson_validate.h"
@@ -78,6 +79,11 @@ namespace mongo {
7879
if ( !readNumber<int>( &sz ) )
7980
return makeError("invalid bson", _idElem);
8081

82+
if ( sz <= 0 ) {
83+
// must have NULL at the very least
84+
return makeError("invalid bson", _idElem);
85+
}
86+
8187
if ( out ) {
8288
*out = StringData( _buffer + _position, sz );
8389
}
@@ -237,6 +243,8 @@ namespace mongo {
237243
int sz;
238244
if ( !buffer->readNumber<int>( &sz ) )
239245
return makeError("invalid bson", idElem);
246+
if ( sz < 0 || sz == std::numeric_limits<int>::max() )
247+
return makeError("invalid size in bson", idElem);
240248
if ( !buffer->skip( 1 + sz ) )
241249
return makeError("invalid bson", idElem);
242250
return Status::OK();

src/mongo/bson/bson_validate_test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,20 @@ namespace {
281281
ASSERT_NOT_OK(status);
282282
ASSERT_EQUALS(status.reason(), "not null terminated string in object with unknown _id");
283283
}
284+
285+
TEST(BSONValidateFast, StringHasSomething) {
286+
BufBuilder bb;
287+
BSONObjBuilder ob(bb);
288+
bb.appendChar(String);
289+
bb.appendStr("x", /*withNUL*/true);
290+
bb.appendNum(0);
291+
const BSONObj x = ob.done();
292+
ASSERT_EQUALS(5 // overhead
293+
+ 1 // type
294+
+ 2 // name
295+
+ 4 // size
296+
, x.objsize());
297+
ASSERT_NOT_OK(validateBSON(x.objdata(), x.objsize()));
298+
}
299+
284300
}

src/mongo/bson/bsonobjbuilder.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ namespace mongo {
6060
, _s(this)
6161
, _tracker(0)
6262
, _doneCalled(false) {
63-
// Reserve space for a holder object at the beginning of the buffer, followed by
63+
// Skip over space for a holder object at the beginning of the buffer, followed by
6464
// space for the object length. The length is filled in by _done.
6565
_b.skip(sizeof(BSONObj::Holder));
6666
_b.skip(sizeof(int));
67+
68+
// Reserve space for the EOO byte. This means _done() can't fail.
69+
_b.reserveBytes(1);
6770
}
6871

6972
/** @param baseBuilder construct a BSONObjBuilder using an existing BufBuilder
@@ -76,9 +79,13 @@ namespace mongo {
7679
, _s(this)
7780
, _tracker(0)
7881
, _doneCalled(false) {
79-
// Reserve space for the object length, which is filled in by _done. We don't need a holder
80-
// since we are a sub-builder, and some parent builder has already made the reservation.
82+
// Skip over space for the object length, which is filled in by _done. We don't need a
83+
// holder since we are a sub-builder, and some parent builder has already made the
84+
// reservation.
8185
_b.skip(sizeof(int));
86+
87+
// Reserve space for the EOO byte. This means _done() can't fail.
88+
_b.reserveBytes(1);
8289
}
8390

8491
BSONObjBuilder( const BSONSizeTracker & tracker )
@@ -91,6 +98,9 @@ namespace mongo {
9198
// See the comments in the first constructor for details.
9299
_b.skip(sizeof(BSONObj::Holder));
93100
_b.skip(sizeof(int));
101+
102+
// Reserve space for the EOO byte. This means _done() can't fail.
103+
_b.reserveBytes(1);
94104
}
95105

96106
~BSONObjBuilder() {
@@ -626,6 +636,7 @@ namespace mongo {
626636
BSONObj asTempObj() {
627637
BSONObj temp(_done());
628638
_b.setlen(_b.len()-1); //next append should overwrite the EOO
639+
_b.reserveBytes(1); // Rereserve room for the real EOO
629640
_doneCalled = false;
630641
return temp;
631642
}
@@ -707,8 +718,14 @@ namespace mongo {
707718
return _b.buf() + _offset;
708719

709720
_doneCalled = true;
721+
722+
// TODO remove this or find some way to prevent it from failing. Since this is intended
723+
// for use with BSON() literal queries, it is less likely to result in oversized BSON.
710724
_s.endField();
725+
726+
_b.claimReservedBytes(1); // Prevents adding EOO from failing.
711727
_b.appendNum((char) EOO);
728+
712729
char *data = _b.buf() + _offset;
713730
int size = _b.len() - _offset;
714731
DataView(data).writeLE(size);

src/mongo/bson/util/builder.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ namespace mongo {
102102
data = 0;
103103
}
104104
l = 0;
105+
reservedBytes = 0;
105106
}
106107
~_BufBuilder() { kill(); }
107108

@@ -114,9 +115,11 @@ namespace mongo {
114115

115116
void reset() {
116117
l = 0;
118+
reservedBytes = 0;
117119
}
118120
void reset( int maxSize ) {
119121
l = 0;
122+
reservedBytes = 0;
120123
if ( maxSize && size > maxSize ) {
121124
al.Free(data);
122125
data = (char*)al.Malloc(maxSize);
@@ -205,13 +208,36 @@ namespace mongo {
205208
inline char* grow(int by) {
206209
int oldlen = l;
207210
int newLen = l + by;
208-
if ( newLen > size ) {
209-
grow_reallocate(newLen);
211+
int minSize = newLen + reservedBytes;
212+
if ( minSize > size ) {
213+
grow_reallocate(minSize);
210214
}
211215
l = newLen;
212216
return data + oldlen;
213217
}
214218

219+
/**
220+
* Reserve room for some number of bytes to be claimed at a later time.
221+
*/
222+
void reserveBytes(int bytes) {
223+
int minSize = l + reservedBytes + bytes;
224+
if (minSize > size)
225+
grow_reallocate(minSize);
226+
227+
// This must happen *after* any attempt to grow.
228+
reservedBytes += bytes;
229+
}
230+
231+
/**
232+
* Claim an earlier reservation of some number of bytes. These bytes must already have been
233+
* reserved. Appends of up to this many bytes immediately following a claim are
234+
* guaranteed to succeed without a need to reallocate.
235+
*/
236+
void claimReservedBytes(int bytes) {
237+
invariant(reservedBytes >= bytes);
238+
reservedBytes -= bytes;
239+
}
240+
215241
private:
216242
template<typename T>
217243
void appendNumImpl(T t) {
@@ -224,10 +250,11 @@ namespace mongo {
224250

225251

226252
/* "slow" portion of 'grow()' */
227-
void NOINLINE_DECL grow_reallocate(int newLen) {
253+
void NOINLINE_DECL grow_reallocate(int minSize) {
228254
int a = 64;
229-
while( a < newLen )
255+
while (a < minSize)
230256
a = a * 2;
257+
231258
if ( a > BufferMaxSize ) {
232259
std::stringstream ss;
233260
ss << "BufBuilder attempted to grow() to " << a << " bytes, past the 64MB limit.";
@@ -242,6 +269,7 @@ namespace mongo {
242269
char *data;
243270
int l;
244271
int size;
272+
int reservedBytes; // eagerly grow_reallocate to keep this many bytes of spare room.
245273

246274
friend class StringBuilderImpl<Allocator>;
247275
};

src/mongo/util/net/sock.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,15 +487,30 @@ namespace mongo {
487487
ConnectBG(int sock, SockAddr remote) : _sock(sock), _remote(remote) { }
488488

489489
void run() {
490-
_res = ::connect(_sock, _remote.raw(), _remote.addressSize);
491-
_errnoWithDescription = errnoWithDescription();
490+
#if defined(_WIN32)
491+
if ((_res = _connect()) == SOCKET_ERROR) {
492+
_errnoWithDescription = errnoWithDescription();
493+
}
494+
#else
495+
while ((_res = _connect()) == -1) {
496+
const int error = errno;
497+
if (error != EINTR) {
498+
_errnoWithDescription = errnoWithDescription(error);
499+
break;
500+
}
501+
}
502+
#endif
492503
}
493504

494505
std::string name() const { return "ConnectBG"; }
495506
std::string getErrnoWithDescription() const { return _errnoWithDescription; }
496507
int inError() const { return _res; }
497508

498509
private:
510+
int _connect() const {
511+
return ::connect(_sock, _remote.raw(), _remote.addressSize);
512+
}
513+
499514
int _sock;
500515
int _res;
501516
SockAddr _remote;

src/mongo/util/net/ssl_manager.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,14 @@ namespace mongo {
556556
// Note: this is for blocking sockets only.
557557
SSL_CTX_set_mode(*context, SSL_MODE_AUTO_RETRY);
558558

559-
// Disable session caching (see SERVER-10261)
560-
SSL_CTX_set_session_cache_mode(*context, SSL_SESS_CACHE_OFF);
561-
559+
massert(28607,
560+
mongoutils::str::stream() << "can't store ssl session id context: " <<
561+
getSSLErrorMessage(ERR_get_error()),
562+
SSL_CTX_set_session_id_context(
563+
*context,
564+
static_cast<unsigned char*>(static_cast<void*>(context)),
565+
sizeof(*context)));
566+
562567
// Use the clusterfile for internal outgoing SSL connections if specified
563568
if (context == &_clientContext && !params.clusterfile.empty()) {
564569
EVP_set_pw_prompt("Enter cluster certificate passphrase");

0 commit comments

Comments
 (0)