From: Kefu Chai Date: Sun, 1 Mar 2026 04:16:40 +0000 (+0800) Subject: librbd: use try_lexical_convert instead of throwing lexical_cast X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3ce085076a10de6c5f74ba4d9d66ff28fc95b26d;p=ceph.git librbd: use try_lexical_convert instead of throwing lexical_cast rbd_features_from_string() uses boost::lexical_cast which throws bad_lexical_cast when the input is not numeric. The exception is caught and handled as "parse as feature name list instead". This is normal control flow, but when ASAN's __cxa_throw interceptor is misconfigured (e.g. with intercept_cxx_exceptions=0 leaving real___cxa_throw NULL), any exception causes a CHECK failure. Even with a correctly configured ASAN, throwing exceptions during config initialization adds overhead. Replace the try/catch pattern with boost::conversion::try_lexical_convert, which returns false on parse failure instead of throwing. This eliminates the exception entirely, making the code more efficient and avoiding any interaction with ASAN's exception interceptor. The ASan report: ``` AddressSanitizer: CHECK failed: asan_interceptors.cpp:320 "((__interception::real___cxa_throw)) != (0)" (0x0, 0x0) (tid=30529) #0 0x7d668fac9a09 in CheckUnwind ../../../../src/libsanitizer/asan/asan_rtl.cpp:67 #1 0x7d668faec105 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cpp:86 #2 0x7d668fa4b194 in __interceptor___cxa_throw ../../../../src/libsanitizer/asan/asan_interceptors.cpp:320 #3 0x7d668ae4ec0f in void boost::throw_exception(boost::bad_lexical_cast const&) /opt/ceph/include/boost/throw_exception.hpp:165 #4 0x7d668c1e1e0b in void boost::conversion::detail::throw_bad_cast, std::allocator >, unsigned long>() /opt/ceph/include/boost/lexical_cast/bad_lexical_cast.hpp:93 #5 0x7d668c1e0e05 in unsigned long boost::lexical_cast, std::allocator > >(std::__cxx11::basic_string, std::allocator > const&) /opt/ceph/include/boost/lexical_cast.hpp:43 #6 0x7d668c1df609 in librbd::rbd_features_from_string(std::__cxx11::basic_string, std::allocator > const&, std::ostream*) /ceph/src/librbd/Features.cc:67 #7 0x7d668b255a35 in get_rbd_options()::$_2::operator()(std::__cxx11::basic_string, std::allocator >*, std::__cxx11::basic_string, std::allocator >*) const src/common/options/rbd_options.cc:44 #8 0x7d668b255806 in int std::__invoke_impl, std::allocator >*, std::__cxx11::basic_string, std::allocator >*>(std::__invoke_other, get_rbd_options()::$_2&, std::__cxx11::basic_string, std::allocator >*&&, std::__cxx11::basic_string, std::allocator >*&&) /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/invoke.h:61 #9 0x7d668b255754 in std::enable_if, std::allocator >*, std::__cxx11::basic_string, std::allocator >*>, int>::type std::__invoke_r, std::allocator >*, std::__cxx11::basic_string, std::allocator >*>(get_rbd_options()::$_2&, std::__cxx11::basic_string, std::allocator >*&&, std::__cxx11::basic_string, std::allocator >*&&) /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/invoke.h:114 #10 0x7d668b25563c in std::_Function_handler, std::allocator >*, std::__cxx11::basic_string, std::allocator >*), get_rbd_options()::$_2>::_M_invoke(std::_Any_data const&, std::__cxx11::basic_string, std::allocator >*&&, std::__cxx11::basic_string, std::allocator >*&&) /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:290 #11 0x7d668af924f1 in std::function, std::allocator >*, std::__cxx11::basic_string, std::allocator >*)>::operator()(std::__cxx11::basic_string, std::allocator >*, std::__cxx11::basic_string, std::allocator >*) const /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_function.h:591 #12 0x7d668af8c495 in Option::pre_validate(std::__cxx11::basic_string, std::allocator >*, std::__cxx11::basic_string, std::allocator >*) const /ceph/src/common/options.cc:94 #13 0x7d668aef9ec3 in md_config_t::md_config_t(ConfigValues&, ConfigTracker const&, bool) /ceph/src/common/config.cc:208 #14 0x7d668ae0040d in ceph::common::ConfigProxy::ConfigProxy(bool) /ceph/src/common/config_proxy.h:70 #15 0x7d668adf3f5d in ceph::common::CephContext::CephContext(unsigned int, ceph::common::CephContext::create_options const&) /ceph/src/common/ceph_context.cc:730 #16 0x7d668adf3785 in ceph::common::CephContext::CephContext(unsigned int, code_environment_t, int) /ceph/src/common/ceph_context.cc:724 #17 0x7d668aef5ee6 in common_preinit(CephInitParameters const&, code_environment_t, int) /ceph/src/common/common_init.cc:40 #18 0x7d668d4a47af in rados_create_cct(char const*, CephInitParameters*) /ceph/src/librados/librados_c.cc:120 #19 0x7d668d4a49db in _rados_create2 /ceph/src/librados/librados_c.cc:168 #20 0x7d668d94dc4b in __pyx_pf_5rados_5Rados_2__setup /ceph/build/src/pybind/rados/rados_processed.c:13219 #21 0x7d668d94dc4b in __pyx_pw_5rados_5Rados_3__setup /ceph/build/src/pybind/rados/rados_processed.c:12703 #22 0x7d668d94a347 in __Pyx_CyFunction_CallAsMethod /ceph/build/src/pybind/rados/rados_processed.c:93157 #23 0x58ac5086d0ba in _PyObject_MakeTpCall (/usr/bin/python3.10+0x1810ba) #24 0x58ac508843da (/usr/bin/python3.10+0x1983da) #25 0x58ac50885076 in PyVectorcall_Call (/usr/bin/python3.10+0x199076) #26 0x7d668d94cdd7 in __Pyx_PyObject_Call /ceph/build/src/pybind/rados/rados_processed.c:90994 #27 0x7d668d94cdd7 in __pyx_pf_5rados_5Rados___init__ /ceph/build/src/pybind/rados/rados_processed.c:12474 #28 0x7d668d94cdd7 in __pyx_pw_5rados_5Rados_1__init__ /ceph/build/src/pybind/rados/rados_processed.c:12443 #29 0x58ac5086d43a (/usr/bin/python3.10+0x18143a) #30 0x58ac50884d3a in PyObject_Call (/usr/bin/python3.10+0x198d3a) #31 0x58ac508637de in _PyEval_EvalFrameDefault (/usr/bin/python3.10+0x1777de) #32 0x58ac5087702b in _PyFunction_Vectorcall (/usr/bin/python3.10+0x18b02b) #33 0x58ac508615fe in _PyEval_EvalFrameDefault (/usr/bin/python3.10+0x1755fe) #34 0x58ac5087702b in _PyFunction_Vectorcall (/usr/bin/python3.10+0x18b02b) #35 0x58ac508615fe in _PyEval_EvalFrameDefault (/usr/bin/python3.10+0x1755fe) ``` Signed-off-by: Kefu Chai --- diff --git a/src/librbd/Features.cc b/src/librbd/Features.cc index 71cc8b374e04..005c9bc397cc 100644 --- a/src/librbd/Features.cc +++ b/src/librbd/Features.cc @@ -1,8 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- // vim: ts=8 sw=2 sts=2 expandtab -#include #include +#include #include "librbd/Features.h" #include "include/rbd/features.h" @@ -62,10 +62,8 @@ uint64_t rbd_features_from_string(const std::string& orig_value, return RBD_FEATURES_DEFAULT; } - try { - // numeric? - features = boost::lexical_cast(value); - + // Try to parse as numeric value first + if (boost::conversion::try_lexical_convert(value, features)) { // drop unrecognized bits uint64_t unsupported_features = (features & ~RBD_FEATURES_ALL); if (unsupported_features != 0ull) { @@ -85,7 +83,7 @@ uint64_t rbd_features_from_string(const std::string& orig_value, *err << "ignoring feature mask 0x" << std::hex << ignored_features; } } - } catch (boost::bad_lexical_cast&) { + } else { // feature name list? bool errors = false; std::vector feature_names; diff --git a/src/librbd/io/IoOperations.cc b/src/librbd/io/IoOperations.cc index 855f9875d7aa..b2006ab9fa47 100644 --- a/src/librbd/io/IoOperations.cc +++ b/src/librbd/io/IoOperations.cc @@ -1,8 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- // vim: ts=8 sw=2 sts=2 expandtab -#include #include +#include #include "librbd/io/Types.h" #include "librbd/io/IoOperations.h" @@ -61,10 +61,8 @@ uint64_t rbd_io_operations_from_string(const std::string& orig_value, return RBD_IO_OPERATIONS_DEFAULT; } - try { - // numeric? - operations = boost::lexical_cast(value); - + // Try to parse as numeric value first + if (boost::conversion::try_lexical_convert(value, operations)) { // drop unrecognized bits uint64_t unsupported_operations = (operations & ~RBD_IO_OPERATIONS_ALL); if (unsupported_operations != 0ull) { @@ -74,7 +72,7 @@ uint64_t rbd_io_operations_from_string(const std::string& orig_value, << std::hex << unsupported_operations << std::dec; } } - } catch (boost::bad_lexical_cast&) { + } else { // operation name list? bool errors = false; std::vector operation_names;