Skip to content

Commit d3927eb

Browse files
committed
PYCBC-1852: Raise on invalid int-enum values instead of default
Changes -------- * In cpp_core_enum_conversion_macros.hxx, check PyErr_Occurred() after PyLong_AsUnsignedLong() in both PYCBC_DEFINE_INT_ENUM_CONVERSION and PYCBC_DEFINE_INT16_ENUM_CONVERSION * On a negative or out-of-range Python int, clear the pending OverflowError and throw std::invalid_argument instead of casting the -1 error sentinel and silently falling through to the enum's default value Change-Id: I6079b6f7d401ee58d738bccc2acda925ae9c3406 Reviewed-on: https://review.couchbase.org/c/couchbase-python-client/+/250617 Reviewed-by: Dimitris Christodoulou <dimitris.christodoulou@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent 03e5424 commit d3927eb

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

src/cpp_core_enum_conversion_macros.hxx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "Python.h"
2121
#include "pytocbpp_defs.hxx"
2222

23+
#include <stdexcept>
24+
2325
// ======================================================================
2426
// Generic Enum Conversion Machinery using X-Macros
2527
// ======================================================================
@@ -98,7 +100,12 @@
98100
if (pyObj == nullptr || !PyLong_Check(pyObj)) { \
99101
return enum_type::default_val; \
100102
} \
101-
auto int_val = static_cast<std::uint8_t>(PyLong_AsUnsignedLong(pyObj)); \
103+
auto raw_val = PyLong_AsUnsignedLong(pyObj); \
104+
if (raw_val == static_cast<unsigned long>(-1) && PyErr_Occurred()) { \
105+
PyErr_Clear(); \
106+
throw std::invalid_argument("value out of range for " #enum_type); \
107+
} \
108+
auto int_val = static_cast<std::uint8_t>(raw_val); \
102109
mappings(PYCBC_FROM_PY_INT_CASE, enum_type) return enum_type::default_val; \
103110
} \
104111
static inline PyObject* to_py(const enum_type& val) \
@@ -130,7 +137,12 @@
130137
if (pyObj == nullptr || !PyLong_Check(pyObj)) { \
131138
return enum_type::default_val; \
132139
} \
133-
auto int_val = static_cast<std::uint16_t>(PyLong_AsUnsignedLong(pyObj)); \
140+
auto raw_val = PyLong_AsUnsignedLong(pyObj); \
141+
if (raw_val == static_cast<unsigned long>(-1) && PyErr_Occurred()) { \
142+
PyErr_Clear(); \
143+
throw std::invalid_argument("value out of range for " #enum_type); \
144+
} \
145+
auto int_val = static_cast<std::uint16_t>(raw_val); \
134146
mappings(PYCBC_FROM_PY_INT16_CASE, enum_type) return enum_type::default_val; \
135147
} \
136148
static inline PyObject* to_py(const enum_type& val) \

0 commit comments

Comments
 (0)