Skip to content

Commit

Permalink
MB-37956: makeCollectionID/makeScopeID should use gsl::narrow<>
Browse files Browse the repository at this point in the history
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 <daver@couchbase.com>
Tested-by: Build Bot <build@couchbase.com>
  • Loading branch information
rdemellow authored and daverigby committed Jun 3, 2021
1 parent c6717ea commit 77693a5
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions engines/ep/src/collections/collections_types.h
Expand Up @@ -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<CollectionID>(makeUid(uid, 8));
try {
return gsl::narrow<CollectionIDType>(makeUid(uid, 8));
} catch (const gsl::narrowing_error& e) {
throw std::invalid_argument("Cannot narrow uid:'" + std::string(uid) +
"' to a CollectionID");
}
}

/**
Expand All @@ -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<ScopeID>(makeUid(uid, 8));
try {
// ScopeId is 8 characters max and smaller than a ManifestUid
return gsl::narrow<ScopeIDType>(makeUid(uid, 8));
} catch (const gsl::narrowing_error& e) {
throw std::invalid_argument("Cannot narrow uid:'" + std::string(uid) +
"' to a ScopeID");
}
}

/**
Expand Down

0 comments on commit 77693a5

Please sign in to comment.