Skip to content

Commit 74cf2eb

Browse files
pilifnikic
authored andcommitted
intl: report more information about message pattern parse errors
The message patterns can be pretty complex, so reporting a generic U_PARSE_ERROR without any additional information makes it needlessly hard to fix erroneous patterns. This commit makes use of the additional UParseError* parameter to umsg_open to retrieve more details about the parse error to report that to the user via intl_get_error_message() Additional improve error reporting from the IntlMessage constructor. Previously, all possible failures when calling IntlMessage::__construct() would be masked away with a generic "Constructor failed" message. This would include invalid patterns. This commit makes sure that the underlying error that caused the constructor failure is reported as part of the IntlException error message. Closes GH-6325.
1 parent 216d6a0 commit 74cf2eb

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

ext/intl/msgformat/msgformat.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor)
3636
int spattern_len = 0;
3737
zval* object;
3838
MessageFormatter_object* mfo;
39+
UParseError parse_error;
3940
int zpp_flags = is_constructor ? ZEND_PARSE_PARAMS_THROW : 0;
4041
intl_error_reset( NULL );
4142

@@ -79,12 +80,26 @@ static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor)
7980
(mfo)->mf_data.orig_format_len = pattern_len;
8081

8182
/* Create an ICU message formatter. */
82-
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(mfo));
83+
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, &parse_error, &INTL_DATA_ERROR_CODE(mfo));
8384

8485
if(spattern) {
8586
efree(spattern);
8687
}
8788

89+
if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) {
90+
char *msg = NULL;
91+
smart_str parse_error_str;
92+
parse_error_str = intl_parse_error_to_string( &parse_error );
93+
spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser error" );
94+
smart_str_free( &parse_error_str );
95+
96+
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( mfo ) );
97+
intl_errors_set_custom_msg( INTL_DATA_ERROR_P( mfo ), msg, 1 );
98+
99+
efree( msg );
100+
return FAILURE;
101+
}
102+
88103
INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: message formatter creation failed");
89104
return SUCCESS;
90105
}
@@ -116,7 +131,9 @@ PHP_METHOD( MessageFormatter, __construct )
116131
return_value = ZEND_THIS;
117132
if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1) == FAILURE) {
118133
if (!EG(exception)) {
119-
zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0);
134+
zend_string *err = intl_error_get_message(NULL);
135+
zend_throw_exception(IntlException_ce_ptr, ZSTR_VAL(err), intl_error_get_code(NULL));
136+
zend_string_release_ex(err, 0);
120137
}
121138
}
122139
zend_restore_error_handling(&error_handling);

ext/intl/msgformat/msgformat_format.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ PHP_FUNCTION( msgfmt_format_message )
9494
size_t slocale_len = 0;
9595
MessageFormatter_object mf;
9696
MessageFormatter_object *mfo = &mf;
97+
UParseError parse_error;
9798

9899
/* Parse parameters. */
99100
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "ssa",
@@ -136,10 +137,25 @@ PHP_FUNCTION( msgfmt_format_message )
136137
#endif
137138

138139
/* Create an ICU message formatter. */
139-
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, NULL, &INTL_DATA_ERROR_CODE(mfo));
140+
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, &parse_error, &INTL_DATA_ERROR_CODE(mfo));
140141
if(spattern && spattern_len) {
141142
efree(spattern);
142143
}
144+
145+
if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) {
146+
char *msg = NULL;
147+
smart_str parse_error_str;
148+
parse_error_str = intl_parse_error_to_string( &parse_error );
149+
spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser error" );
150+
smart_str_free( &parse_error_str );
151+
152+
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( mfo ) );
153+
intl_errors_set_custom_msg( INTL_DATA_ERROR_P( mfo ), msg, 1 );
154+
155+
efree( msg );
156+
RETURN_FALSE;
157+
}
158+
143159
INTL_METHOD_CHECK_STATUS(mfo, "Creating message formatter failed");
144160

145161
msgfmt_do_format(mfo, args, return_value);

ext/intl/tests/msgfmt_fail2.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ Warning: msgfmt_create() expects exactly 2 parameters, 1 given in %s on line %d
9696
Warning: MessageFormatter::create() expects exactly 2 parameters, 1 given in %s on line %d
9797
'msgfmt_create: unable to parse input parameters: U_ILLEGAL_ARGUMENT_ERROR'
9898

99-
IntlException: Constructor failed in %smsgfmt_fail2.php on line %d
99+
IntlException: msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR in %s on line %d
100100
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
101101
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
102102
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
103103

104-
IntlException: Constructor failed in %smsgfmt_fail2.php on line %d
104+
IntlException: msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR in %s on line %d
105105
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
106106
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
107107
'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
@@ -115,17 +115,17 @@ Warning: MessageFormatter::create() expects parameter 1 to be string, array give
115115
Warning: msgfmt_create() expects parameter 1 to be string, array given in %s on line %d
116116
'msgfmt_create: unable to parse input parameters: U_ILLEGAL_ARGUMENT_ERROR'
117117

118-
IntlException: Constructor failed in %smsgfmt_fail2.php on line %d
119-
'msgfmt_create: message formatter creation failed: U_PATTERN_SYNTAX_ERROR'
120-
'msgfmt_create: message formatter creation failed: U_PATTERN_SYNTAX_ERROR'
121-
'msgfmt_create: message formatter creation failed: U_PATTERN_SYNTAX_ERROR'
118+
IntlException: pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR in %s on line %d
119+
'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR'
120+
'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR'
121+
'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR'
122122

123-
IntlException: Constructor failed in %smsgfmt_fail2.php on line %d
123+
IntlException: msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES in %s on line %d
124124
'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES'
125125
'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES'
126126
'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES'
127127

128-
IntlException: Constructor failed in %smsgfmt_fail2.php on line %d
128+
IntlException: msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND in %s on line %d
129129
'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND'
130130
'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND'
131131
'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND'

0 commit comments

Comments
 (0)