From 3bd41f563f973c77f7b251a067595bb040b60298 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 11 Mar 2023 11:02:03 +0000 Subject: [PATCH] ext/intl usmg_parse_helper possible mem leak fixes on failure path. introducing an utility class which calls a lambda from its destructor when going out of scope. --- ext/intl/intl_convertcpp.h | 37 ++++++++++++++++++++++++ ext/intl/msgformat/msgformat_helpers.cpp | 11 +++---- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/ext/intl/intl_convertcpp.h b/ext/intl/intl_convertcpp.h index 28948c2e01ca6..061c0c625aae1 100644 --- a/ext/intl/intl_convertcpp.h +++ b/ext/intl/intl_convertcpp.h @@ -28,4 +28,41 @@ int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCod zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status); +/** + * Utility class to act as a cleaner when an instance + * uses the expression when it goes out of its scope + * avoiding to needs handle all errors in all code paths + * + * note that template auto deduction is supported + * only from C++17, still need to be explicit + * at instantiation's time. + */ +template +class intl_cleaner { + T expr; + bool useexpr{true}; +public: + intl_cleaner(T& expr_) : + expr(std::move(expr_)) {} + intl_cleaner(const intl_cleaner& o) = delete; + intl_cleaner& operator=(const intl_cleaner& o) = delete; + // for the assignment constructors with std::move semantics + // we invalidate the original. + intl_cleaner(intl_cleaner&& o) : + expr(std::move(o.expr)), + useexpr(o.useexpr) { + o.useexpr = false; + } + intl_cleaner& operator=(const intl_cleaner&& o) { + if (&o == this) + return *this; + this->~intl_cleaner(); + new (this)intl_cleaner(std::move(o)); + return *this; + } + ~intl_cleaner() { + if (useexpr) + expr(); + } +}; #endif /* INTL_CONVERTCPP_H */ diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index fbd85b857f3bc..ccf5180ef592c 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -623,11 +623,13 @@ U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval **args, UCh UnicodeString srcString(source, source_len); Formattable *fargs = ((const MessageFormat*)fmt)->parse(srcString, *count, *status); - if(U_FAILURE(*status)) { - return; - } + if(U_FAILURE(*status)) { + return; + } - *args = (zval *)safe_emalloc(*count, sizeof(zval), 0); + *args = (zval *)safe_emalloc(*count, sizeof(zval), 0); + auto fargs_expr = [&]() { delete []fargs; }; + auto fargs_cleaner = intl_cleaner(fargs_expr); // assign formattables to varargs for(int32_t i = 0; i < *count; i++) { @@ -676,5 +678,4 @@ U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval **args, UCh break; } } - delete[] fargs; }