summaryrefslogtreecommitdiff
path: root/src/mongo/db/geo/hash.cpp
diff options
context:
space:
mode:
authorSvilen Mihaylov <svilen.mihaylov@mongodb.com>2020-05-05 10:18:39 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-18 15:38:37 +0000
commitcbd23d40077b148f94ba74fef49198b287e51747 (patch)
tree5f9c43938f58e5cebce0ba07fb405ec5dbdc7c96 /src/mongo/db/geo/hash.cpp
parentdf291c458193f3bf51c314fc9219efc36dfbd067 (diff)
downloadmongo-cbd23d40077b148f94ba74fef49198b287e51747.tar.gz
SERVER-47994 Fix for numerical overflow in GeoHash (part 2)
Diffstat (limited to 'src/mongo/db/geo/hash.cpp')
-rw-r--r--src/mongo/db/geo/hash.cpp45
1 files changed, 30 insertions, 15 deletions
diff --git a/src/mongo/db/geo/hash.cpp b/src/mongo/db/geo/hash.cpp
index c1170efd57e..25437d51769 100644
--- a/src/mongo/db/geo/hash.cpp
+++ b/src/mongo/db/geo/hash.cpp
@@ -662,49 +662,64 @@ static BSONField<double> minField("min", -180.0);
// (about 1.11e-16) times the magnitude of the result.
double const GeoHashConverter::kMachinePrecision = 0.5 * std::numeric_limits<double>::epsilon();
-Status GeoHashConverter::parseParameters(const BSONObj& paramDoc,
- GeoHashConverter::Parameters* params) {
+StatusWith<std::unique_ptr<GeoHashConverter>> GeoHashConverter::createFromDoc(
+ const BSONObj& paramDoc) {
string errMsg;
+ Parameters params{};
if (FieldParser::FIELD_INVALID ==
- FieldParser::extractNumber(paramDoc, bitsField, &params->bits, &errMsg)) {
+ FieldParser::extractNumber(paramDoc, bitsField, &params.bits, &errMsg)) {
return Status(ErrorCodes::InvalidOptions, errMsg);
}
if (FieldParser::FIELD_INVALID ==
- FieldParser::extractNumber(paramDoc, maxField, &params->max, &errMsg)) {
+ FieldParser::extractNumber(paramDoc, maxField, &params.max, &errMsg)) {
return Status(ErrorCodes::InvalidOptions, errMsg);
}
if (FieldParser::FIELD_INVALID ==
- FieldParser::extractNumber(paramDoc, minField, &params->min, &errMsg)) {
+ FieldParser::extractNumber(paramDoc, minField, &params.min, &errMsg)) {
return Status(ErrorCodes::InvalidOptions, errMsg);
}
- if (params->bits < 1 || params->bits > 32) {
+ if (params.bits < 1 || params.bits > 32) {
return Status(ErrorCodes::InvalidOptions,
str::stream() << "bits for hash must be > 0 and <= 32, "
- << "but " << params->bits << " bits were specified");
+ << "but " << params.bits << " bits were specified");
}
- const bool rangeValid = params->min < params->max;
- if (!rangeValid || std::isinf(params->min) || std::isinf(params->max)) {
+ const bool rangeValid = params.min < params.max;
+ if (!rangeValid || std::isinf(params.min) || std::isinf(params.max)) {
return Status(ErrorCodes::InvalidOptions,
str::stream() << "region for hash must be valid and have positive area, "
- << "but [" << params->min << ", " << params->max << "] "
+ << "but [" << params.min << ", " << params.max << "] "
<< "was specified");
}
constexpr double numBuckets = 4.0 * 1024 * 1024 * 1024;
- params->scaling = numBuckets / (params->max - params->min);
- const bool scalingValid = params->scaling > 0;
- if (!scalingValid || std::isinf(params->scaling)) {
+ params.scaling = numBuckets / (params.max - params.min);
+ const bool scalingValid = params.scaling > 0;
+ if (!scalingValid || std::isinf(params.scaling)) {
return Status(ErrorCodes::InvalidOptions,
str::stream()
- << "range [" << params->min << ", " << params->max << "] is too small.");
+ << "range [" << params.min << ", " << params.max << "] is too small.");
}
- return Status::OK();
+ return createFromParams(params);
+}
+
+StatusWith<std::unique_ptr<GeoHashConverter>> GeoHashConverter::createFromParams(
+ const Parameters& params) {
+ std::unique_ptr<GeoHashConverter> converter(new GeoHashConverter(params));
+
+ const bool errorValid = params.max - params.min >= converter->_error / 2;
+ if (!errorValid) {
+ return Status(ErrorCodes::InvalidOptions,
+ str::stream() << "invalid computed error: " << converter->_error
+ << " on range [" << params.min << ", " << params.max << "].");
+ }
+
+ return {std::move(converter)};
}
GeoHashConverter::GeoHashConverter(const Parameters& params) : _params(params) {