diff options
Diffstat (limited to 'src/mongo/base/data_type_validated.h')
-rw-r--r-- | src/mongo/base/data_type_validated.h | 195 |
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 |