diff --git a/src/mongo/db/json.cpp b/src/mongo/db/json.cpp
|
index 9e5531f..0f61960 100644
|
--- a/src/mongo/db/json.cpp
|
+++ b/src/mongo/db/json.cpp
|
@@ -911,29 +911,40 @@ namespace mongo {
|
}
|
|
Status JParse::number(const StringData& fieldName, BSONObjBuilder& builder) {
|
- char* endptrll;
|
- char* endptrd;
|
+ const char *numptr;
|
+ const char *numend;
|
long long retll;
|
double retd;
|
|
- // reset errno to make sure that we are getting it from strtod
|
- errno = 0;
|
- // SERVER-11920: We should use parseNumberFromString here, but that function requires that
|
- // we know ahead of time where the number ends, which is not currently the case.
|
- retd = strtod(_input, &endptrd);
|
- // if pointer does not move, we found no digits
|
- if (_input == endptrd) {
|
- return parseError("Bad characters in value");
|
+ // find boundry of number.
|
+
|
+ // Skip whitespace
|
+ // 'isspace()' takes an 'int' (signed), so (default signed) 'char's get sign-extended
|
+ // and therefore 'corrupted' unless we force them to be unsigned ... 0x80 becomes
|
+ // 0xffffff80 as seen by isspace when sign-extended ... we want it to be 0x00000080
|
+ numptr = _input;
|
+ while (numptr < _input_end &&
|
+ isspace(*reinterpret_cast<const unsigned char*>(numptr))) {
|
+ ++numptr;
|
}
|
- if (errno == ERANGE) {
|
- return parseError("Value cannot fit in double");
|
+
|
+ numend = numptr;
|
+ // This is not the exact production from the json standard, but should give
|
+ // the same result for all valid input.
|
+ while (numend < _input_end) {
|
+ char ch = *numend;
|
+ if ((ch >= '0' && ch <= '9')
|
+ || ch == 'e' || ch == 'E' || ch == '-' || ch == '+' || ch == '.') {
|
+ ++numend;
|
+ } else break;
|
}
|
- // reset errno to make sure that we are getting it from strtoll
|
- errno = 0;
|
- // SERVER-11920: We should use parseNumberFromString here, but that function requires that
|
- // we know ahead of time where the number ends, which is not currently the case.
|
- retll = strtoll(_input, &endptrll, 10);
|
- if (endptrll < endptrd || errno == ERANGE) {
|
+
|
+ StringData numberstr(numptr, numend - numptr);
|
+
|
+ if (Status::OK() != parseNumberFromStringWithBase(numberstr, 0, &retd)) {
|
+ return parseError("Bad characters in value");
|
+ }
|
+ if (Status::OK() != parseNumberFromStringWithBase(numberstr, 10, &retll)) {
|
// The number either had characters only meaningful for a double or
|
// could not fit in a 64 bit int
|
MONGO_JSON_DEBUG("Type: double");
|
@@ -949,7 +960,7 @@ namespace mongo {
|
MONGO_JSON_DEBUG("Type: 64 bit int");
|
builder.append(fieldName, retll);
|
}
|
- _input = endptrd;
|
+ _input = numend;
|
if (_input >= _input_end) {
|
return parseError("Trailing number at end of input");
|
}
|