Skip to content

Commit 1f541e7

Browse files
committed
CXX-479 Backport server r2.6.7..r2.6.9 changes
Server SHAs picked into this commit: 2d45919 1b64aa8 78d52ff 1dd33f4 224067d 8f1c734 91ab64a a5408ed 738e366 5b0ff61 3abc04d a34e139 77fb852 b6a66a0 9af0d09 a5a4852 e9e813d e3a7692 3133d04 2dee1ad df313bc
1 parent f904e33 commit 1f541e7

12 files changed

+222
-38
lines changed

SConstruct

+18-17
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def add_option( name, help, nargs, contributesToVariantDir,
9696
if type == 'choice' and not metavar:
9797
metavar = '[' + '|'.join(choices) + ']'
9898

99-
AddOption( "--" + name ,
99+
AddOption( "--" + name ,
100100
dest=dest,
101101
type=type,
102102
nargs=nargs,
@@ -133,7 +133,7 @@ def use_system_version_of_library(name):
133133

134134
def get_variant_dir():
135135
if has_option('variant-dir'):
136-
return "#build/" + get_option('variant-dir')
136+
return "#build/" + get_option('variant-dir')
137137

138138
substitute = lambda x: re.sub( "[:,\\\\/]" , "_" , x )
139139

@@ -346,7 +346,7 @@ boostLibs = [ "thread" , "filesystem" , "program_options", "system" ]
346346
onlyServer = len( COMMAND_LINE_TARGETS ) == 0 or ( len( COMMAND_LINE_TARGETS ) == 1 and str( COMMAND_LINE_TARGETS[0] ) in [ "mongod" , "mongos" , "test" ] )
347347

348348
linux64 = False
349-
force32 = has_option( "force32" )
349+
force32 = has_option( "force32" )
350350
force64 = has_option( "force64" )
351351
if not force64 and not force32 and os.getcwd().endswith( "mongo-64" ):
352352
force64 = True
@@ -436,9 +436,9 @@ else:
436436

437437
static = has_option( "static" )
438438

439-
noshell = has_option( "noshell" )
439+
noshell = has_option( "noshell" )
440440

441-
usev8 = has_option( "usev8" )
441+
usev8 = has_option( "usev8" )
442442

443443
asio = has_option( "asio" )
444444

@@ -582,7 +582,7 @@ if has_option( "libpath" ):
582582
if has_option( "cpppath" ):
583583
env["CPPPATH"] = [get_option( "cpppath" )]
584584

585-
env.Prepend( CPPDEFINES=[ "_SCONS" ,
585+
env.Prepend( CPPDEFINES=[ "_SCONS" ,
586586
"MONGO_EXPOSE_MACROS" ,
587587
"SUPPORT_UTF8" ], # for pcre
588588

@@ -688,8 +688,6 @@ elif linux:
688688

689689
if static:
690690
env.Append( LINKFLAGS=" -static " )
691-
if has_option( "static-libstdc++" ):
692-
env.Append( LINKFLAGS=["-static-libstdc++", "-static-libgcc"] )
693691

694692
elif solaris:
695693
env.Append( CPPDEFINES=[ "__sunos__" ] )
@@ -739,7 +737,7 @@ elif windows:
739737
# The this pointer is valid only within nonstatic member functions. It cannot be used in the initializer list for a base class.
740738
# c4800
741739
# 'type' : forcing value to bool 'true' or 'false' (performance warning)
742-
# This warning is generated when a value that is not bool is assigned or coerced into type bool.
740+
# This warning is generated when a value that is not bool is assigned or coerced into type bool.
743741
# c4267
744742
# 'var' : conversion from 'size_t' to 'type', possible loss of data
745743
# When compiling with /Wp64, or when compiling on a 64-bit operating system, type is 32 bits but size_t is 64 bits when compiling for 64-bit targets. To fix this warning, use size_t instead of a type.
@@ -761,12 +759,12 @@ elif windows:
761759

762760
env.Append( CPPDEFINES=["_CONSOLE","_CRT_SECURE_NO_WARNINGS"] )
763761

764-
# this would be for pre-compiled headers, could play with it later
762+
# this would be for pre-compiled headers, could play with it later
765763
#env.Append( CCFLAGS=['/Yu"pch.h"'] )
766764

767765
# docs say don't use /FD from command line (minimal rebuild)
768766
# /Gy function level linking (implicit when using /Z7)
769-
# /Z7 debug info goes into each individual .obj file -- no .pdb created
767+
# /Z7 debug info goes into each individual .obj file -- no .pdb created
770768
env.Append( CCFLAGS= ["/Z7", "/errorReport:none"] )
771769

772770
# /DEBUG will tell the linker to create a .pdb file
@@ -822,6 +820,9 @@ elif windows:
822820

823821
if nix:
824822

823+
if has_option( "static-libstdc++" ):
824+
env.Append( LINKFLAGS=["-static-libstdc++", "-static-libgcc"] )
825+
825826
if has_option( "distcc" ):
826827
env["CXX"] = "distcc " + env["CXX"]
827828

@@ -1378,7 +1379,7 @@ def doConfigure(myenv):
13781379

13791380
conf.env.Append(CPPDEFINES=[("BOOST_THREAD_VERSION", "2")])
13801381

1381-
# Note that on Windows with using-system-boost builds, the following
1382+
# Note that on Windows with using-system-boost builds, the following
13821383
# FindSysLibDep calls do nothing useful (but nothing problematic either)
13831384
for b in boostLibs:
13841385
boostlib = "boost_" + b
@@ -1415,10 +1416,10 @@ def doConfigure(myenv):
14151416
env.Append( CPPDEFINES=["MONGO_SASL"] )
14161417

14171418
if conf.env['MONGO_BUILD_SASL_CLIENT'] and not conf.CheckLibWithHeader(
1418-
"sasl2",
1419-
["stddef.h","sasl/sasl.h"],
1420-
"C",
1421-
"sasl_version_info(0, 0, 0, 0, 0, 0);",
1419+
"sasl2",
1420+
["stddef.h","sasl/sasl.h"],
1421+
"C",
1422+
"sasl_version_info(0, 0, 0, 0, 0, 0);",
14221423
autoadd=False ):
14231424
Exit(1)
14241425

@@ -1482,7 +1483,7 @@ def doStyling( env , target , source ):
14821483
print( "astyle 2.x needed, found:" + res )
14831484
Exit(-1)
14841485

1485-
files = utils.getAllSourceFiles()
1486+
files = utils.getAllSourceFiles()
14861487
files = filter( lambda x: not x.endswith( ".c" ) , files )
14871488

14881489
cmd = "astyle --options=mongo_astyle " + " ".join( files )

src/mongo/bson/bson-inl.h

+7
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,13 @@ namespace mongo {
10031003
return true;
10041004
}
10051005

1006+
template<> inline bool BSONElement::coerce<long long>( long long* out ) const {
1007+
if ( !isNumber() )
1008+
return false;
1009+
*out = numberLong();
1010+
return true;
1011+
}
1012+
10061013
template<> inline bool BSONElement::coerce<double>( double* out ) const {
10071014
if ( !isNumber() )
10081015
return false;

src/mongo/bson/bson_validate.cpp

+8
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/bson/bson_validate.h"
2223
#include "mongo/bson/oid.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

+16
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,20 @@ namespace {
273273
ASSERT_NOT_OK(status);
274274
ASSERT_EQUALS(status.reason(), "not null terminated string in object with unknown _id");
275275
}
276+
277+
TEST(BSONValidateFast, StringHasSomething) {
278+
BufBuilder bb;
279+
BSONObjBuilder ob(bb);
280+
bb.appendChar(String);
281+
bb.appendStr("x", /*withNUL*/true);
282+
bb.appendNum(0);
283+
const BSONObj x = ob.done();
284+
ASSERT_EQUALS(5 // overhead
285+
+ 1 // type
286+
+ 2 // name
287+
+ 4 // size
288+
, x.objsize());
289+
ASSERT_NOT_OK(validateBSON(x.objdata(), x.objsize()));
290+
}
291+
276292
}

src/mongo/bson/bsonobjbuilder.h

+16
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,27 @@ namespace mongo {
5555
BSONObjBuilder(int initsize=512) : _b(_buf), _buf(initsize + sizeof(unsigned)), _offset( sizeof(unsigned) ), _s( this ) , _tracker(0) , _doneCalled(false) {
5656
_b.appendNum((unsigned)0); // ref-count
5757
_b.skip(4); /*leave room for size field and ref-count*/
58+
59+
// Reserve space for the EOO byte. This means _done() can't fail.
60+
_b.reserveBytes(1);
5861
}
5962

6063
/** @param baseBuilder construct a BSONObjBuilder using an existing BufBuilder
6164
* This is for more efficient adding of subobjects/arrays. See docs for subobjStart for example.
6265
*/
6366
BSONObjBuilder( BufBuilder &baseBuilder ) : _b( baseBuilder ), _buf( 0 ), _offset( baseBuilder.len() ), _s( this ) , _tracker(0) , _doneCalled(false) {
6467
_b.skip( 4 );
68+
69+
// Reserve space for the EOO byte. This means _done() can't fail.
70+
_b.reserveBytes(1);
6571
}
6672

6773
BSONObjBuilder( const BSONSizeTracker & tracker ) : _b(_buf) , _buf(tracker.getSize() + sizeof(unsigned) ), _offset( sizeof(unsigned) ), _s( this ) , _tracker( (BSONSizeTracker*)(&tracker) ) , _doneCalled(false) {
6874
_b.appendNum((unsigned)0); // ref-count
6975
_b.skip(4);
76+
77+
// Reserve space for the EOO byte. This means _done() can't fail.
78+
_b.reserveBytes(1);
7079
}
7180

7281
~BSONObjBuilder() {
@@ -600,6 +609,7 @@ namespace mongo {
600609
BSONObj asTempObj() {
601610
BSONObj temp(_done());
602611
_b.setlen(_b.len()-1); //next append should overwrite the EOO
612+
_b.reserveBytes(1); // Rereserve room for the real EOO
603613
_doneCalled = false;
604614
return temp;
605615
}
@@ -681,8 +691,14 @@ namespace mongo {
681691
return _b.buf() + _offset;
682692

683693
_doneCalled = true;
694+
695+
// TODO remove this or find some way to prevent it from failing. Since this is intended
696+
// for use with BSON() literal queries, it is less likely to result in oversized BSON.
684697
_s.endField();
698+
699+
_b.claimReservedBytes(1); // Prevents adding EOO from failing.
685700
_b.appendNum((char) EOO);
701+
686702
char *data = _b.buf() + _offset;
687703
int size = _b.len() - _offset;
688704
*((int*)data) = size;

src/mongo/bson/util/builder.h

+32-4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ namespace mongo {
110110
data = 0;
111111
}
112112
l = 0;
113+
reservedBytes = 0;
113114
}
114115
~_BufBuilder() { kill(); }
115116

@@ -122,9 +123,11 @@ namespace mongo {
122123

123124
void reset() {
124125
l = 0;
126+
reservedBytes = 0;
125127
}
126128
void reset( int maxSize ) {
127129
l = 0;
130+
reservedBytes = 0;
128131
if ( maxSize && size > maxSize ) {
129132
al.Free(data);
130133
data = (char*)al.Malloc(maxSize);
@@ -201,19 +204,43 @@ namespace mongo {
201204
inline char* grow(int by) {
202205
int oldlen = l;
203206
int newLen = l + by;
204-
if ( newLen > size ) {
205-
grow_reallocate(newLen);
207+
int minSize = newLen + reservedBytes;
208+
if ( minSize > size ) {
209+
grow_reallocate(minSize);
206210
}
207211
l = newLen;
208212
return data + oldlen;
209213
}
210214

215+
/**
216+
* Reserve room for some number of bytes to be claimed at a later time.
217+
*/
218+
void reserveBytes(int bytes) {
219+
int minSize = l + reservedBytes + bytes;
220+
if (minSize > size)
221+
grow_reallocate(minSize);
222+
223+
// This must happen *after* any attempt to grow.
224+
reservedBytes += bytes;
225+
}
226+
227+
/**
228+
* Claim an earlier reservation of some number of bytes. These bytes must already have been
229+
* reserved. Appends of up to this many bytes immediately following a claim are
230+
* guaranteed to succeed without a need to reallocate.
231+
*/
232+
void claimReservedBytes(int bytes) {
233+
invariant(reservedBytes >= bytes);
234+
reservedBytes -= bytes;
235+
}
236+
211237
private:
212238
/* "slow" portion of 'grow()' */
213-
void NOINLINE_DECL grow_reallocate(int newLen) {
239+
void NOINLINE_DECL grow_reallocate(int minSize) {
214240
int a = 64;
215-
while( a < newLen )
241+
while (a < minSize)
216242
a = a * 2;
243+
217244
if ( a > BufferMaxSize ) {
218245
std::stringstream ss;
219246
ss << "BufBuilder attempted to grow() to " << a << " bytes, past the 64MB limit.";
@@ -228,6 +255,7 @@ namespace mongo {
228255
char *data;
229256
int l;
230257
int size;
258+
int reservedBytes; // eagerly grow_reallocate to keep this many bytes of spare room.
231259

232260
friend class StringBuilderImpl<Allocator>;
233261
};

0 commit comments

Comments
 (0)