summaryrefslogtreecommitdiff
path: root/src/mongo/crypto
diff options
context:
space:
mode:
authorShreyas Kalyan <shreyas.kalyan@mongodb.com>2022-10-19 18:45:29 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-28 17:08:17 +0000
commit0d9455e8ee5ed764aee6a514d789ae1b5ed0af03 (patch)
treeafdf0a9b77327ee7ec3b51d699d132dbf311c453 /src/mongo/crypto
parent9e75d3b2db979335716de2b1f6b5bb6bcf0b6f3b (diff)
downloadmongo-0d9455e8ee5ed764aee6a514d789ae1b5ed0af03.tar.gz
SERVER-69671 FLE2 range float precision: update createCollection to enforce parameter constraints
Diffstat (limited to 'src/mongo/crypto')
-rw-r--r--src/mongo/crypto/encryption_fields.idl8
-rw-r--r--src/mongo/crypto/encryption_fields_validation.cpp35
-rw-r--r--src/mongo/crypto/fle_crypto_test.cpp8
-rw-r--r--src/mongo/crypto/fle_field_schema.idl8
-rw-r--r--src/mongo/crypto/fle_fields_util.cpp7
5 files changed, 51 insertions, 15 deletions
diff --git a/src/mongo/crypto/encryption_fields.idl b/src/mongo/crypto/encryption_fields.idl
index 567fb1b3237..5eb13c5d700 100644
--- a/src/mongo/crypto/encryption_fields.idl
+++ b/src/mongo/crypto/encryption_fields.idl
@@ -93,6 +93,14 @@ structs:
optional: true
stability: unstable
validator: { gte: 1, lte: 4 }
+ precision:
+ description: >-
+ Defines the number of digits after the decimal point for floating point numbers.
+ Only applicable to floating point numbers and for queryType range.
+ type: safeInt
+ optional: true
+ stability: unstable
+ validator: { gte: 0 }
EncryptedField:
description: "Information about encrypted fields"
diff --git a/src/mongo/crypto/encryption_fields_validation.cpp b/src/mongo/crypto/encryption_fields_validation.cpp
index a0debee4a89..3c370136fb3 100644
--- a/src/mongo/crypto/encryption_fields_validation.cpp
+++ b/src/mongo/crypto/encryption_fields_validation.cpp
@@ -77,7 +77,7 @@ Value coerceValueToRangeIndexTypes(Value val, BSONType fieldType) {
}
-void validateRangeIndex(BSONType fieldType, const QueryTypeConfig& query) {
+void validateRangeIndex(BSONType fieldType, QueryTypeConfig& query) {
uassert(6775201,
str::stream() << "Type '" << typeName(fieldType)
<< "' is not a supported range indexed type",
@@ -90,18 +90,31 @@ void validateRangeIndex(BSONType fieldType, const QueryTypeConfig& query) {
"The field 'sparsity' must be between 1 and 4",
query.getSparsity().value() >= 1 && query.getSparsity().value() <= 4);
+
switch (fieldType) {
case NumberDouble:
- case NumberDecimal:
- uassert(7006601,
- "The field 'min' on floating point field is invalid for range index over "
- "double/decimal fields.",
- !query.getMin().has_value());
- uassert(7006602,
- "The field 'max' on floating point field is invalid for range index over "
- "double/decimal fields.",
- !query.getMax().has_value());
- break;
+ case NumberDecimal: {
+ if (!((query.getMin().has_value() == query.getMax().has_value()) &&
+ (query.getMin().has_value() == query.getPrecision().has_value()))) {
+ uasserted(6967100,
+ str::stream() << "Precision, min, and max must all be specified "
+ << "together for floating point fields");
+ }
+
+ if (!query.getMin().has_value()) {
+ if (fieldType == NumberDouble) {
+ query.setMin(mongo::Value(std::numeric_limits<double>::min()));
+ query.setMax(mongo::Value(std::numeric_limits<double>::max()));
+ } else {
+ query.setMin(mongo::Value(Decimal128::kLargestNegative));
+ query.setMax(mongo::Value(Decimal128::kLargestPositive));
+ }
+ }
+ }
+ // We want to perform the same validation after sanitizing floating
+ // point parameters, so we call FMT_FALLTHROUGH here.
+
+ FMT_FALLTHROUGH;
case NumberInt:
case NumberLong:
case Date: {
diff --git a/src/mongo/crypto/fle_crypto_test.cpp b/src/mongo/crypto/fle_crypto_test.cpp
index e99f4c854b9..c47f6e54e21 100644
--- a/src/mongo/crypto/fle_crypto_test.cpp
+++ b/src/mongo/crypto/fle_crypto_test.cpp
@@ -731,16 +731,16 @@ std::vector<char> generatePlaceholder(
upperDoc = BSON("ub" << 1234567890123456789LL);
break;
case BSONType::NumberDouble:
- lowerDoc = BSON("lb" << std::numeric_limits<double>::min());
- upperDoc = BSON("ub" << std::numeric_limits<double>::max());
+ lowerDoc = BSON("lb" << 0.0);
+ upperDoc = BSON("ub" << 1234567890123456789.0);
break;
case BSONType::Date:
lowerDoc = BSON("lb" << Date_t::fromMillisSinceEpoch(0));
upperDoc = BSON("ub" << Date_t::fromMillisSinceEpoch(1234567890123456789LL));
break;
case BSONType::NumberDecimal:
- lowerDoc = BSON("lb" << Decimal128::kLargestNegative);
- upperDoc = BSON("ub" << Decimal128::kLargestPositive);
+ lowerDoc = BSON("lb" << Decimal128(0));
+ upperDoc = BSON("ub" << Decimal128(1234567890123456789LL));
break;
default:
LOGV2_WARNING(6775520,
diff --git a/src/mongo/crypto/fle_field_schema.idl b/src/mongo/crypto/fle_field_schema.idl
index 65b274dd3e7..918344b7e17 100644
--- a/src/mongo/crypto/fle_field_schema.idl
+++ b/src/mongo/crypto/fle_field_schema.idl
@@ -389,6 +389,10 @@ structs:
ubIncluded:
description: "Indicates if the upper bound should be included in the range."
type: bool
+ precision:
+ description: "Determines the number of digits after the decimal point for floating point values"
+ type: safeInt
+ optional: true
indexMin:
description: "Minimum value for the encrypted index that this query is using."
type: encrypted_numeric_element
@@ -436,3 +440,7 @@ structs:
type: encrypted_numeric_element
optional: true
cpp_name: maxBound
+ precision:
+ description: "Determines the number of digits after the decimal point for floating point values"
+ type: safeInt
+ optional: true
diff --git a/src/mongo/crypto/fle_fields_util.cpp b/src/mongo/crypto/fle_fields_util.cpp
index 8887645100f..02653266b8a 100644
--- a/src/mongo/crypto/fle_fields_util.cpp
+++ b/src/mongo/crypto/fle_fields_util.cpp
@@ -146,6 +146,13 @@ void validateIDLFLE2RangeFindSpec(const FLE2RangeFindSpec* placeholder) {
auto min = edgesInfo.getIndexMin().getElement();
auto max = edgesInfo.getIndexMax().getElement();
uassert(6901304, "Range min and range max must be the same type.", min.type() == max.type());
+
+ if (edgesInfo.getPrecision().has_value()) {
+ uassert(6967102,
+ "Precision can only be set if type is floating point",
+ min.type() == BSONType::NumberDecimal || min.type() == BSONType::NumberDouble);
+ }
+
auto lb = edgesInfo.getLowerBound().getElement();
auto ub = edgesInfo.getUpperBound().getElement();
validateQueryBounds(min.type(), lb, ub);