Skip to content

Commit 1bbe9d8

Browse files
author
lexeyo
committed
fix postgres, utils: changed narrowing overflow exception type
Add a new template parameter `Exception` to `utils::numeric_cast` to allow explicit specification of a thrown exception type. Adds a new exception type `NarrowingOverflow` to indicate overflows during narrowing numeric conversions. Changes the exception type thrown on narrowing overflow in `IntegralBinaryParser` from `std::runtime_error` to `NarrowingOverflow` to provide additional exception information and simplify exception handling. commit_hash:24e08d7610b16da62c432ecc09e40d0ad5d2773c
1 parent b042777 commit 1bbe9d8

File tree

4 files changed

+19
-10
lines changed

4 files changed

+19
-10
lines changed

postgresql/include/userver/storages/postgres/exceptions.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ std::string OidPrettyPrint(Oid oid);
120120
* - InvalidInputBufferSize
121121
* - InvalidParserCategory
122122
* - InvalidTupleSizeRequested
123+
* - NarrowingOverflow
123124
* - NonSingleColumnResultSet
124125
* - NonSingleRowResultSet
125126
* - NoBinaryParser
@@ -738,6 +739,13 @@ class FieldTupleMismatch : public ResultSetError {
738739
FieldTupleMismatch(std::size_t field_count, std::size_t tuple_size);
739740
};
740741

742+
/// @brief A binary buffer contains a numeric value that does not fit
743+
/// into a given C++ value type.
744+
class NarrowingOverflow : public ResultSetError {
745+
public:
746+
using ResultSetError::ResultSetError;
747+
};
748+
741749
//@}
742750

743751
//@{

postgresql/include/userver/storages/postgres/io/integral_types.hpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ struct IntegralBySizeParser {
5050
}
5151
};
5252

53+
template <typename To, typename From>
54+
To NumericCast(From value) {
55+
return USERVER_NAMESPACE::utils::numeric_cast<To, NarrowingOverflow>(value);
56+
}
57+
5358
template <typename T>
5459
struct IntegralBinaryParser : BufferParserBase<T> {
5560
using BaseType = BufferParserBase<T>;
@@ -59,16 +64,13 @@ struct IntegralBinaryParser : BufferParserBase<T> {
5964
void operator()(const FieldBuffer& buf) {
6065
switch (buf.length) {
6166
case 2:
62-
this->value = USERVER_NAMESPACE::utils::numeric_cast<ValueType>(IntegralBySizeParser<2>::ParseBuffer(buf
63-
));
67+
this->value = NumericCast<ValueType>(IntegralBySizeParser<2>::ParseBuffer(buf));
6468
break;
6569
case 4:
66-
this->value = USERVER_NAMESPACE::utils::numeric_cast<ValueType>(IntegralBySizeParser<4>::ParseBuffer(buf
67-
));
70+
this->value = NumericCast<ValueType>(IntegralBySizeParser<4>::ParseBuffer(buf));
6871
break;
6972
case 8:
70-
this->value = USERVER_NAMESPACE::utils::numeric_cast<ValueType>(IntegralBySizeParser<8>::ParseBuffer(buf
71-
));
73+
this->value = NumericCast<ValueType>(IntegralBySizeParser<8>::ParseBuffer(buf));
7274
break;
7375
default:
7476
throw InvalidInputBufferSize{fmt::format(

postgresql/src/storages/postgres/tests/integral_test.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <gtest/gtest.h>
22

33
#include <limits>
4-
#include <stdexcept>
54

65
#include <storages/postgres/detail/connection.hpp>
76
#include <storages/postgres/tests/test_buffers.hpp>
@@ -111,7 +110,7 @@ TYPED_TEST(PostgreIOIntegralNarrowing, Fail) {
111110
UEXPECT_NO_THROW(io::WriteBuffer(types, buffer, src));
112111
auto fb = pg::test::MakeFieldBuffer(buffer, io::BufferCategory::kPlainBuffer);
113112
ValueType tgt{0};
114-
UEXPECT_THROW(io::ReadBuffer(fb, tgt), std::runtime_error);
113+
UEXPECT_THROW(io::ReadBuffer(fb, tgt), storages::postgres::NarrowingOverflow);
115114
}
116115
}
117116

universal/include/userver/utils/numeric_cast.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ using PrintableValue = std::conditional_t<(sizeof(T) > 1), T, int>;
2727
/// ## Example usage:
2828
///
2929
/// @snippet utils/numeric_cast_test.cpp Sample utils::numeric_cast usage
30-
template <typename To, typename From>
30+
template <typename To, typename Exception = std::runtime_error, typename From>
3131
constexpr To numeric_cast(From input) { // NOLINT(readability-identifier-naming)
3232
static_assert(std::is_integral_v<From>);
3333
static_assert(std::is_integral_v<To>);
@@ -51,7 +51,7 @@ constexpr To numeric_cast(From input) { // NOLINT(readability-identifier-naming
5151
}
5252

5353
if (!overflow_type.empty()) {
54-
throw std::runtime_error(fmt::format(
54+
throw Exception(fmt::format(
5555
"Failed to convert {} {} into {} due to {} integer overflow",
5656
compiler::GetTypeName<From>(),
5757
static_cast<impl::PrintableValue<From>>(input),

0 commit comments

Comments
 (0)