Skip to content

Commit 3bd41f5

Browse files
committed
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.
1 parent 5c058d7 commit 3bd41f5

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

ext/intl/intl_convertcpp.h

+37
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,41 @@ int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCod
2828

2929
zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status);
3030

31+
/**
32+
* Utility class to act as a cleaner when an instance
33+
* uses the expression when it goes out of its scope
34+
* avoiding to needs handle all errors in all code paths
35+
*
36+
* note that template auto deduction is supported
37+
* only from C++17, still need to be explicit
38+
* at instantiation's time.
39+
*/
40+
template<typename T>
41+
class intl_cleaner {
42+
T expr;
43+
bool useexpr{true};
44+
public:
45+
intl_cleaner(T& expr_) :
46+
expr(std::move(expr_)) {}
47+
intl_cleaner(const intl_cleaner& o) = delete;
48+
intl_cleaner& operator=(const intl_cleaner& o) = delete;
49+
// for the assignment constructors with std::move semantics
50+
// we invalidate the original.
51+
intl_cleaner(intl_cleaner&& o) :
52+
expr(std::move(o.expr)),
53+
useexpr(o.useexpr) {
54+
o.useexpr = false;
55+
}
56+
intl_cleaner& operator=(const intl_cleaner&& o) {
57+
if (&o == this)
58+
return *this;
59+
this->~intl_cleaner();
60+
new (this)intl_cleaner(std::move(o));
61+
return *this;
62+
}
63+
~intl_cleaner() {
64+
if (useexpr)
65+
expr();
66+
}
67+
};
3168
#endif /* INTL_CONVERTCPP_H */

ext/intl/msgformat/msgformat_helpers.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,13 @@ U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval **args, UCh
623623
UnicodeString srcString(source, source_len);
624624
Formattable *fargs = ((const MessageFormat*)fmt)->parse(srcString, *count, *status);
625625

626-
if(U_FAILURE(*status)) {
627-
return;
628-
}
626+
if(U_FAILURE(*status)) {
627+
return;
628+
}
629629

630-
*args = (zval *)safe_emalloc(*count, sizeof(zval), 0);
630+
*args = (zval *)safe_emalloc(*count, sizeof(zval), 0);
631+
auto fargs_expr = [&]() { delete []fargs; };
632+
auto fargs_cleaner = intl_cleaner<decltype(fargs_expr)>(fargs_expr);
631633

632634
// assign formattables to varargs
633635
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
676678
break;
677679
}
678680
}
679-
delete[] fargs;
680681
}

0 commit comments

Comments
 (0)