1 Based on the following upstream commits:
3 https://github.com/php/php-src/commit/45a05f38410d4a67c8c83c09906e2cfb42fc6e4c
4 https://github.com/php/php-src/commit/534684d1042978f3c21caf9b665a7aca27f3f325
6 --- a/ext/intl/msgformat/msgformat_helpers.cpp
7 +++ b/ext/intl/msgformat/msgformat_helpers.cpp
9 #include <unicode/timezone.h>
10 #include <unicode/datefmt.h>
11 #include <unicode/calendar.h>
12 +#include <unicode/strenum.h>
16 @@ -45,6 +46,7 @@ extern "C" {
18 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48
19 #define HAS_MESSAGE_PATTERN 1
20 +#define HAS_MISALLOCATE_MEMORY_BUG 1
24 @@ -345,6 +347,26 @@ static void umsg_set_timezone(MessageFormatter_object *mfo,
25 return; /* already done */
28 +#ifdef HAS_MISALLOCATE_MEMORY_BUG
29 + /* There is a bug in ICU which prevents MessageFormatter::getFormats()
30 + to handle more than 10 formats correctly. The enumerator could be
31 + used to walk through the present formatters using getFormat(), which
32 + however seems to provide just a readonly access. This workaround
33 + prevents crash when there are > 10 formats but doesn't set any error.
34 + As a result, only DateFormatters with > 10 subformats are affected.
35 + This workaround should be ifdef'd out, when the bug has been fixed
37 + icu::StringEnumeration* fnames = mf->getFormatNames(err.code);
38 + if (!fnames || U_FAILURE(err.code)) {
41 + count = fnames->count(err.code);
48 formats = mf->getFormats(count);
50 if (formats == NULL) {
52 +++ b/ext/intl/tests/bug74484_MessageFormatter.phpt
55 +Bug #74484 MessageFormatter::formatMessage memory corruption with 11+ named placeholder
58 +if (!extension_loaded('intl'))
59 + die('skip intl extension not enabled');
60 +if (version_compare(INTL_ICU_VERSION, '4.8') < 0)
61 + die('skip for ICU 4.8+');
65 +$text = "{a} {b} {c} {d} {e} {f} {g} {h} {i} {j} {k} {l}";
82 +var_dump(MessageFormatter::formatMessage('en_US', $text, $vars));
87 +string(26) "1 2 3 4 5 6 7 8 9 10 11 12"