diff --git a/api/include/opentelemetry/common/string_util.h b/api/include/opentelemetry/common/string_util.h index 5108f186e7..4aa7cd4f56 100644 --- a/api/include/opentelemetry/common/string_util.h +++ b/api/include/opentelemetry/common/string_util.h @@ -5,6 +5,7 @@ #include +#include "opentelemetry/common/macros.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/version.h" @@ -25,7 +26,18 @@ class StringUtil { right--; } - return str.substr(left, 1 + right - left); +#if OPENTELEMETRY_HAVE_EXCEPTIONS + try +#endif + { + return str.substr(left, 1 + right - left); + } +#if OPENTELEMETRY_HAVE_EXCEPTIONS + catch (...) + { + return nostd::string_view(); + } +#endif } static nostd::string_view Trim(nostd::string_view str) noexcept diff --git a/api/include/opentelemetry/nostd/string_view.h b/api/include/opentelemetry/nostd/string_view.h index a0c8081473..13c8cfe560 100644 --- a/api/include/opentelemetry/nostd/string_view.h +++ b/api/include/opentelemetry/nostd/string_view.h @@ -71,7 +71,7 @@ class string_view { if (pos > length_) { -# if __EXCEPTIONS +# if OPENTELEMETRY_HAVE_EXCEPTIONS throw std::out_of_range{"opentelemetry::nostd::string_view"}; # else std::terminate(); diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 3294554c58..b55ce35ce1 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -18,7 +18,7 @@ // Header-only. Without compiling the actual Abseil binary. As Abseil moves on to new // toolchains, it may drop support for Visual Studio 2015 in future versions. -# if defined(__EXCEPTIONS) +# if OPENTELEMETRY_HAVE_EXCEPTIONS # include OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd diff --git a/api/include/opentelemetry/plugin/detail/utility.h b/api/include/opentelemetry/plugin/detail/utility.h index 8e78fb4270..0bfdf4f858 100644 --- a/api/include/opentelemetry/plugin/detail/utility.h +++ b/api/include/opentelemetry/plugin/detail/utility.h @@ -3,36 +3,34 @@ #pragma once -#if __EXCEPTIONS -# include -#endif // __EXCEPTIONS +#include "opentelemetry/version.h" #include -#include "opentelemetry/version.h" - OPENTELEMETRY_BEGIN_NAMESPACE namespace plugin { namespace detail { inline void CopyErrorMessage(const char *source, std::string &destination) noexcept -#if __EXCEPTIONS -try -#endif { - if (source == nullptr) +#if OPENTELEMETRY_HAVE_EXCEPTIONS + try +#endif + { + if (source == nullptr) + { + return; + } + destination.assign(source); + } +#if OPENTELEMETRY_HAVE_EXCEPTIONS + catch (...) { return; } - destination.assign(source); -} -#if __EXCEPTIONS -catch (const std::bad_alloc &) -{ - return; -} #endif +} } // namespace detail } // namespace plugin OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/std/variant.h b/api/include/opentelemetry/std/variant.h index 58bc510c5f..e1c660eb6d 100644 --- a/api/include/opentelemetry/std/variant.h +++ b/api/include/opentelemetry/std/variant.h @@ -33,7 +33,7 @@ using monostate = std::monostate; // Apple Platforms provide std::bad_variant_access only in newer versions of OS. // To keep API compatible with any version of OS - we are providing our own // implementation of nostd::bad_variant_access exception. -# if __EXCEPTIONS +# if OPENTELEMETRY_HAVE_EXCEPTIONS // nostd::bad_variant_access class bad_variant_access : public std::exception @@ -48,7 +48,7 @@ class bad_variant_access : public std::exception } # endif -# if __EXCEPTIONS +# if OPENTELEMETRY_HAVE_EXCEPTIONS # define THROW_BAD_VARIANT_ACCESS throw_bad_variant_access() # else # define THROW_BAD_VARIANT_ACCESS std::terminate() diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index 7ed83284cb..dde8dd2f69 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -209,7 +209,7 @@ class OPENTELEMETRY_EXPORT TraceState * For multi-tenant vendor scenarios, an at sign (@) can be used to prefix the vendor name. * */ - static bool IsValidKey(nostd::string_view key) + static bool IsValidKey(nostd::string_view key) noexcept { #if OPENTELEMETRY_HAVE_WORKING_REGEX return IsValidKeyRegEx(key); @@ -222,7 +222,7 @@ class OPENTELEMETRY_EXPORT TraceState * The value is an opaque string containing up to 256 printable ASCII (RFC0020) * characters ((i.e., the range 0x20 to 0x7E) except comma , and equal =) */ - static bool IsValidValue(nostd::string_view value) + static bool IsValidValue(nostd::string_view value) noexcept { #if OPENTELEMETRY_HAVE_WORKING_REGEX return IsValidValueRegEx(value); @@ -249,29 +249,51 @@ class OPENTELEMETRY_EXPORT TraceState } #if OPENTELEMETRY_HAVE_WORKING_REGEX - static bool IsValidKeyRegEx(nostd::string_view key) + static bool IsValidKeyRegEx(nostd::string_view key) noexcept { - static std::regex reg_key("^[a-z0-9][a-z0-9*_\\-/]{0,255}$"); - static std::regex reg_key_multitenant( - "^[a-z0-9][a-z0-9*_\\-/]{0,240}(@)[a-z0-9][a-z0-9*_\\-/]{0,13}$"); - std::string key_s(key.data(), key.size()); - if (std::regex_match(key_s, reg_key) || std::regex_match(key_s, reg_key_multitenant)) +# if OPENTELEMETRY_HAVE_EXCEPTIONS + try { - return true; +# endif + static std::regex reg_key("^[a-z0-9][a-z0-9*_\\-/]{0,255}$"); + static std::regex reg_key_multitenant( + "^[a-z0-9][a-z0-9*_\\-/]{0,240}(@)[a-z0-9][a-z0-9*_\\-/]{0,13}$"); + std::string key_s(key.data(), key.size()); + if (std::regex_match(key_s, reg_key) || std::regex_match(key_s, reg_key_multitenant)) + { + return true; + } + return false; +# if OPENTELEMETRY_HAVE_EXCEPTIONS + } + catch (...) + { + return false; } - return false; +# endif } - static bool IsValidValueRegEx(nostd::string_view value) + static bool IsValidValueRegEx(nostd::string_view value) noexcept { - // Hex 0x20 to 0x2B, 0x2D to 0x3C, 0x3E to 0x7E - static std::regex reg_value( - "^[\\x20-\\x2B\\x2D-\\x3C\\x3E-\\x7E]{0,255}[\\x21-\\x2B\\x2D-\\x3C\\x3E-\\x7E]$"); - // Need to benchmark without regex, as a string object is created here. - return std::regex_match(std::string(value.data(), value.size()), reg_value); +# if OPENTELEMETRY_HAVE_EXCEPTIONS + try + { +# endif + // Hex 0x20 to 0x2B, 0x2D to 0x3C, 0x3E to 0x7E + static std::regex reg_value( + "^[\\x20-\\x2B\\x2D-\\x3C\\x3E-\\x7E]{0,255}[\\x21-\\x2B\\x2D-\\x3C\\x3E-\\x7E]$"); + // Need to benchmark without regex, as a string object is created here. + return std::regex_match(std::string(value.data(), value.size()), reg_value); +# if OPENTELEMETRY_HAVE_EXCEPTIONS + } + catch (...) + { + return false; + } +# endif } #else - static bool IsValidKeyNonRegEx(nostd::string_view key) + static bool IsValidKeyNonRegEx(nostd::string_view key) noexcept { if (key.empty() || key.size() > kKeyMaxSize || !IsLowerCaseAlphaOrDigit(key[0])) { @@ -294,7 +316,7 @@ class OPENTELEMETRY_EXPORT TraceState return true; } - static bool IsValidValueNonRegEx(nostd::string_view value) + static bool IsValidValueNonRegEx(nostd::string_view value) noexcept { if (value.empty() || value.size() > kValueMaxSize) { @@ -312,7 +334,7 @@ class OPENTELEMETRY_EXPORT TraceState } #endif - static bool IsLowerCaseAlphaOrDigit(char c) { return isdigit(c) || islower(c); } + static bool IsLowerCaseAlphaOrDigit(char c) noexcept { return isdigit(c) || islower(c); } private: // Store entries in a C-style array to avoid using std::array or std::vector. diff --git a/api/test/common/string_util_test.cc b/api/test/common/string_util_test.cc index 4da8563175..03f49d5538 100644 --- a/api/test/common/string_util_test.cc +++ b/api/test/common/string_util_test.cc @@ -4,6 +4,7 @@ #include #include +#include #include #include "opentelemetry/nostd/string_view.h" @@ -50,3 +51,12 @@ TEST(StringUtilTest, TrimString) EXPECT_EQ(StringUtil::Trim(testcase.input), testcase.expected); } } + +TEST(StringUtilTest, TrimStringOutOfRange) +{ +#if OPENTELEMETRY_HAVE_EXCEPTIONS + EXPECT_EQ(StringUtil::Trim("x", 2, 1), ""); +#else + EXPECT_DEATH(StringUtil::Trim("x", 2, 1), ""); +#endif +} diff --git a/api/test/nostd/string_view_test.cc b/api/test/nostd/string_view_test.cc index f32da62b42..14bc69b4af 100644 --- a/api/test/nostd/string_view_test.cc +++ b/api/test/nostd/string_view_test.cc @@ -8,6 +8,7 @@ #include #include +#include "opentelemetry/common/macros.h" #include "opentelemetry/nostd/string_view.h" using opentelemetry::nostd::string_view; @@ -74,7 +75,7 @@ TEST(StringViewTest, SubstrPortion) TEST(StringViewTest, SubstrOutOfRange) { string_view s = "abc123"; -#if __EXCEPTIONS || (defined(OPENTELEMETRY_STL_VERSION) && (OPENTELEMETRY_STL_VERSION >= 2017)) +#if OPENTELEMETRY_HAVE_EXCEPTIONS EXPECT_THROW((void)s.substr(10), std::out_of_range); #else EXPECT_DEATH({ s.substr(10); }, ""); diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 193bd4874a..5ebadd6eac 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -51,7 +51,7 @@ TEST(VariantTest, Get) EXPECT_EQ(nostd::get(w), 12); EXPECT_EQ(*nostd::get_if(&v), 12); EXPECT_EQ(nostd::get_if(&v), nullptr); -#if __EXCEPTIONS || (defined(OPENTELEMETRY_STL_VERSION) && (OPENTELEMETRY_STL_VERSION >= 2017)) +#if OPENTELEMETRY_HAVE_EXCEPTIONS EXPECT_THROW(nostd::get(w), nostd::bad_variant_access); #else EXPECT_DEATH({ nostd::get(w); }, ""); diff --git a/api/test/trace/trace_state_test.cc b/api/test/trace/trace_state_test.cc index 6613d9270c..d8b5aaa7e3 100644 --- a/api/test/trace/trace_state_test.cc +++ b/api/test/trace/trace_state_test.cc @@ -58,6 +58,7 @@ TEST(TraceStateTest, ValidateHeaderParsing) } testcases[] = {{"k1=v1", "k1=v1"}, {"K1=V1", ""}, {"k1=v1,k2=v2,k3=v3", "k1=v1,k2=v2,k3=v3"}, + {"k1=v1,InvalidKey=v2", ""}, {"k1=v1,k2=v2,,", "k1=v1,k2=v2"}, {"k1=v1,k2=v2,invalidmember", ""}, {"1a-2f@foo=bar1,a*/foo-_/bar=bar4", "1a-2f@foo=bar1,a*/foo-_/bar=bar4"}, @@ -73,6 +74,15 @@ TEST(TraceStateTest, ValidateHeaderParsing) } } +TEST(TraceStateTest, ExceedsMaxKeyValuePairs) +{ + std::string header = header_with_max_members(); + header += ",overflow=value"; + + auto ts = TraceState::FromHeader(header); + EXPECT_EQ(ts->ToHeader(), ""); +} + TEST(TraceStateTest, TraceStateGet) {