summaryrefslogtreecommitdiff
path: root/src/mongo/base/data_type_validated.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/base/data_type_validated.h')
-rw-r--r--src/mongo/base/data_type_validated.h195
1 files changed, 98 insertions, 97 deletions
diff --git a/src/mongo/base/data_type_validated.h b/src/mongo/base/data_type_validated.h
index e13bb03ea60..92b56c14f5f 100644
--- a/src/mongo/base/data_type_validated.h
+++ b/src/mongo/base/data_type_validated.h
@@ -33,118 +33,119 @@
namespace mongo {
+/**
+ * Allows for specializations of load/store that run validation logic.
+ *
+ * To add validation for your T:
+ * 1) ensure that there are DataType::Handler<T> specializations for your type
+ * 2) implement a specialization of Validator<T> for your type. The two methods
+ * you must implement are:
+ * - Status validateLoad(const char* ptr, size_t length);
+ * - Status validateStore(const T& toStore);
+ *
+ * See bson_validate.h for an example.
+ *
+ * Then you can use Validated<T> in a DataRange (and associated types)
+ *
+ * Example:
+ *
+ * DataRangeCursor drc(buf, buf_end);
+ * Validated<MyObj> vobj;
+ * auto status = drc.readAndAdvance(&vobj);
+ * if (status.isOK()) {
+ * // use vobj.val
+ * // ....
+ * }
+ */
+template <typename T>
+struct Validator {
+ // These methods are intentionally unimplemented so that if the default validator
+ // is instantiated, the resulting binary will not link.
+
/**
- * Allows for specializations of load/store that run validation logic.
- *
- * To add validation for your T:
- * 1) ensure that there are DataType::Handler<T> specializations for your type
- * 2) implement a specialization of Validator<T> for your type. The two methods
- * you must implement are:
- * - Status validateLoad(const char* ptr, size_t length);
- * - Status validateStore(const T& toStore);
- *
- * See bson_validate.h for an example.
- *
- * Then you can use Validated<T> in a DataRange (and associated types)
- *
- * Example:
- *
- * DataRangeCursor drc(buf, buf_end);
- * Validated<MyObj> vobj;
- * auto status = drc.readAndAdvance(&vobj);
- * if (status.isOK()) {
- * // use vobj.val
- * // ....
- * }
+ * Checks that the provided buffer contains at least 1 valid object of type T.
+ * The length parameter is the size of the buffer, not the size of the object.
+ * Specializations of this function should be hardened to malicious input from untrusted
+ * sources.
*/
- template <typename T>
- struct Validator {
-
- // These methods are intentionally unimplemented so that if the default validator
- // is instantiated, the resulting binary will not link.
-
- /**
- * Checks that the provided buffer contains at least 1 valid object of type T.
- * The length parameter is the size of the buffer, not the size of the object.
- * Specializations of this function should be hardened to malicious input from untrusted
- * sources.
- */
- static Status validateLoad(const char* ptr, size_t length);
-
- /**
- * Checks that the provided object is valid to store in a buffer.
- */
- static Status validateStore(const T& toStore);
- };
-
- template <typename T>
- struct Validated {
-
- Validated() = default;
- Validated(T value) : val(std::move(value)) {}
-
- operator T&() {
- return val;
- }
-
- T val = DataType::defaultConstruct<T>();
- };
-
- template <typename T>
- struct DataType::Handler<Validated<T>> {
-
- static Status load(Validated<T>* vt, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
-
- size_t local_advanced = 0;
+ static Status validateLoad(const char* ptr, size_t length);
- auto valid = Validator<T>::validateLoad(ptr, length);
-
- if (!valid.isOK()) {
- return valid;
- }
-
- auto loadStatus = DataType::load(vt ? &vt->val : nullptr, ptr, length, &local_advanced,
- debug_offset);
-
- if (!loadStatus.isOK()) {
- return loadStatus;
- }
+ /**
+ * Checks that the provided object is valid to store in a buffer.
+ */
+ static Status validateStore(const T& toStore);
+};
+
+template <typename T>
+struct Validated {
+ Validated() = default;
+ Validated(T value) : val(std::move(value)) {}
+
+ operator T&() {
+ return val;
+ }
+
+ T val = DataType::defaultConstruct<T>();
+};
+
+template <typename T>
+struct DataType::Handler<Validated<T>> {
+ static Status load(Validated<T>* vt,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
+
+ auto valid = Validator<T>::validateLoad(ptr, length);
+
+ if (!valid.isOK()) {
+ return valid;
+ }
- if (advanced) {
- *advanced = local_advanced;
- }
+ auto loadStatus =
+ DataType::load(vt ? &vt->val : nullptr, ptr, length, &local_advanced, debug_offset);
- return Status::OK();
+ if (!loadStatus.isOK()) {
+ return loadStatus;
}
- static Status store(const Validated<T>& vt, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
-
- size_t local_advanced = 0;
+ if (advanced) {
+ *advanced = local_advanced;
+ }
- auto valid = Validator<T>::validateStore(vt.val);
+ return Status::OK();
+ }
- if (!valid.isOK()) {
- return valid;
- }
+ static Status store(const Validated<T>& vt,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
- auto storeStatus = DataType::store(vt.val, ptr, length, &local_advanced, debug_offset);
+ auto valid = Validator<T>::validateStore(vt.val);
- if (!storeStatus.isOK()) {
- return storeStatus;
- }
+ if (!valid.isOK()) {
+ return valid;
+ }
- if (advanced) {
- *advanced = local_advanced;
- }
+ auto storeStatus = DataType::store(vt.val, ptr, length, &local_advanced, debug_offset);
- return Status::OK();
+ if (!storeStatus.isOK()) {
+ return storeStatus;
}
- static Validated<T> defaultConstruct() {
- return Validated<T>();
+ if (advanced) {
+ *advanced = local_advanced;
}
- };
+
+ return Status::OK();
+ }
+
+ static Validated<T> defaultConstruct() {
+ return Validated<T>();
+ }
+};
} // namespace mongo