From 77693a5e04ba81d75c6a710bb436ed9c142afb76 Mon Sep 17 00:00:00 2001 From: Richard de Mellow Date: Tue, 1 Jun 2021 09:24:43 +0100 Subject: [PATCH] MB-37956: makeCollectionID/makeScopeID should use gsl::narrow<> We currently use narrow_cast<> to cast a ManifestUid to a ScopeID or CollectionID. But this doesn't throw if the value can't be fitted into narrower value. So we should use gsl::narrow<> which will throw if the value can't be fitted into the narrow value. gsl::narrow will cast to ScopeIDType and CollectionIDType first as this gives us the benefit of also throwing if the conversion can't be done. Then creating a ScopeID and CollectionID object (We perform the gsl::narrow<> to the underlying type first so that we don't need to implement extra operators that gsl::narrow requires). Any narrowing exceptions throw will be caught and re-thrown as an std::invalid_argument() exception. This issue was found as gsl::narrow_cast<> is marked noexcept in gsl-lite 0.38.1. Which caused us to crash due to ScopeID and CollectionID throwing in the constructor. Change-Id: Ie220f3d80c851d1b78d39916898f2c5e8aef7e87 Reviewed-on: http://review.couchbase.org/c/kv_engine/+/154775 Reviewed-by: Dave Rigby Tested-by: Build Bot --- engines/ep/src/collections/collections_types.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/engines/ep/src/collections/collections_types.h b/engines/ep/src/collections/collections_types.h index 9eead63e4b..cb99794754 100644 --- a/engines/ep/src/collections/collections_types.h +++ b/engines/ep/src/collections/collections_types.h @@ -107,7 +107,12 @@ static inline ManifestUid makeUid(const std::string& uid) { */ static inline CollectionID makeCollectionID(const char* uid) { // CollectionID is 8 characters max and smaller than a ManifestUid - return gsl::narrow_cast(makeUid(uid, 8)); + try { + return gsl::narrow(makeUid(uid, 8)); + } catch (const gsl::narrowing_error& e) { + throw std::invalid_argument("Cannot narrow uid:'" + std::string(uid) + + "' to a CollectionID"); + } } /** @@ -127,11 +132,16 @@ static inline CollectionID makeCollectionID(const std::string& uid) { * A valid CollectionID is a std::string where each character satisfies * std::isxdigit and can be converted to a CollectionID by std::strtoul * @param uid C-string uid - * @return std::invalid_argument if uid is invalid + * @throws std::invalid_argument if uid is invalid */ static inline ScopeID makeScopeID(const char* uid) { - // ScopeId is 8 characters max and smaller than a ManifestUid - return gsl::narrow_cast(makeUid(uid, 8)); + try { + // ScopeId is 8 characters max and smaller than a ManifestUid + return gsl::narrow(makeUid(uid, 8)); + } catch (const gsl::narrowing_error& e) { + throw std::invalid_argument("Cannot narrow uid:'" + std::string(uid) + + "' to a ScopeID"); + } } /**