Skip to content

Commit c29eed4

Browse files
committed
ext/intl: Normalize cloning error handling behaviour
Always throw a Error exception as we cannot progress from here
1 parent 38c634e commit c29eed4

15 files changed

+115
-213
lines changed

ext/intl/breakiterator/breakiterator_class.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -96,37 +96,22 @@ static int BreakIterator_compare_objects(zval *object1,
9696
/* {{{ clone handler for BreakIterator */
9797
static zend_object *BreakIterator_clone_obj(zend_object *object)
9898
{
99-
BreakIterator_object *bio_orig,
100-
*bio_new;
101-
zend_object *ret_val;
102-
103-
bio_orig = php_intl_breakiterator_fetch_object(object);
104-
intl_errors_reset(INTL_DATA_ERROR_P(bio_orig));
105-
106-
ret_val = BreakIterator_ce_ptr->create_object(object->ce);
107-
bio_new = php_intl_breakiterator_fetch_object(ret_val);
99+
BreakIterator_object *bio_orig = php_intl_breakiterator_fetch_object(object);
100+
zend_object *ret_val = BreakIterator_ce_ptr->create_object(object->ce);
101+
BreakIterator_object *bio_new = php_intl_breakiterator_fetch_object(ret_val);
108102

109103
zend_objects_clone_members(&bio_new->zo, &bio_orig->zo);
110104

111105
if (bio_orig->biter != NULL) {
112-
BreakIterator *new_biter;
113-
114-
new_biter = bio_orig->biter->clone();
106+
BreakIterator *new_biter = bio_orig->biter->clone();
115107
if (!new_biter) {
116-
zend_string *err_msg;
117-
intl_errors_set_code(BREAKITER_ERROR_P(bio_orig),
118-
U_MEMORY_ALLOCATION_ERROR);
119-
intl_errors_set_custom_msg(BREAKITER_ERROR_P(bio_orig),
120-
"Could not clone BreakIterator", 0);
121-
err_msg = intl_error_get_message(BREAKITER_ERROR_P(bio_orig));
122-
zend_throw_exception(NULL, ZSTR_VAL(err_msg), 0);
123-
zend_string_free(err_msg);
108+
zend_throw_error(NULL, "Failed to clone BreakIterator");
124109
} else {
125110
bio_new->biter = new_biter;
126111
ZVAL_COPY(&bio_new->text, &bio_orig->text);
127112
}
128113
} else {
129-
zend_throw_exception(NULL, "Cannot clone unconstructed BreakIterator", 0);
114+
zend_throw_error(NULL, "Cannot clone uninitialized BreakIterator");
130115
}
131116

132117
return ret_val;

ext/intl/calendar/calendar_class.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,9 @@ U_CFUNC void calendar_object_construct(zval *object,
7777
/* {{{ clone handler for Calendar */
7878
static zend_object *Calendar_clone_obj(zend_object *object)
7979
{
80-
Calendar_object *co_orig,
81-
*co_new;
82-
zend_object *ret_val;
83-
intl_error_reset(NULL);
84-
85-
co_orig = php_intl_calendar_fetch_object(object);
86-
intl_error_reset(INTL_DATA_ERROR_P(co_orig));
87-
88-
ret_val = Calendar_ce_ptr->create_object(object->ce);
89-
co_new = php_intl_calendar_fetch_object(ret_val);
80+
Calendar_object *co_orig = php_intl_calendar_fetch_object(object);
81+
zend_object *ret_val = Calendar_ce_ptr->create_object(object->ce);
82+
Calendar_object *co_new = php_intl_calendar_fetch_object(ret_val);
9083

9184
zend_objects_clone_members(&co_new->zo, &co_orig->zo);
9285

@@ -95,19 +88,12 @@ static zend_object *Calendar_clone_obj(zend_object *object)
9588

9689
newCalendar = co_orig->ucal->clone();
9790
if (UNEXPECTED(!newCalendar)) {
98-
zend_string *err_msg;
99-
intl_errors_set_code(CALENDAR_ERROR_P(co_orig),
100-
U_MEMORY_ALLOCATION_ERROR);
101-
intl_errors_set_custom_msg(CALENDAR_ERROR_P(co_orig),
102-
"Could not clone IntlCalendar", 0);
103-
err_msg = intl_error_get_message(CALENDAR_ERROR_P(co_orig));
104-
zend_throw_exception(NULL, ZSTR_VAL(err_msg), 0);
105-
zend_string_free(err_msg);
91+
zend_throw_error(NULL, "Failed to clone IntlCalendar");
10692
} else {
10793
co_new->ucal = newCalendar;
10894
}
10995
} else {
110-
zend_throw_exception(NULL, "Cannot clone unconstructed IntlCalendar", 0);
96+
zend_throw_error(NULL, "Cannot clone uninitialized IntlCalendar");
11197
}
11298

11399
return ret_val;

ext/intl/converter/converter.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -929,8 +929,6 @@ static zend_object *php_converter_clone_object(zend_object *object) {
929929
zend_object *retval = php_converter_object_ctor(object->ce, &objval);
930930
UErrorCode error = U_ZERO_ERROR;
931931

932-
intl_errors_reset(&oldobj->error);
933-
934932
#if U_ICU_VERSION_MAJOR_NUM > 70
935933
objval->src = ucnv_clone(oldobj->src, &error);
936934
#else
@@ -944,14 +942,9 @@ static zend_object *php_converter_clone_object(zend_object *object) {
944942
objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error);
945943
#endif
946944
}
947-
if (U_FAILURE(error)) {
948-
zend_string *err_msg;
949-
THROW_UFAILURE(oldobj, "ucnv_safeClone", error);
950-
951-
err_msg = intl_error_get_message(&oldobj->error);
952-
zend_throw_exception(NULL, ZSTR_VAL(err_msg), 0);
953-
zend_string_release_ex(err_msg, 0);
954945

946+
if (U_FAILURE(error)) {
947+
zend_throw_error(NULL, "Failed to clone UConverter");
955948
return retval;
956949
}
957950

ext/intl/dateformat/dateformat_class.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,23 @@ zend_object *IntlDateFormatter_object_create(zend_class_entry *ce)
6464
/* {{{ IntlDateFormatter_object_clone */
6565
zend_object *IntlDateFormatter_object_clone(zend_object *object)
6666
{
67-
IntlDateFormatter_object *dfo, *new_dfo;
68-
zend_object *new_obj;
67+
IntlDateFormatter_object *dfo = php_intl_dateformatter_fetch_object(object);
68+
zend_object *new_obj = IntlDateFormatter_ce_ptr->create_object(object->ce);
69+
IntlDateFormatter_object *new_dfo = php_intl_dateformatter_fetch_object(new_obj);
6970

70-
dfo = php_intl_dateformatter_fetch_object(object);
71-
intl_error_reset(INTL_DATA_ERROR_P(dfo));
72-
73-
new_obj = IntlDateFormatter_ce_ptr->create_object(object->ce);
74-
new_dfo = php_intl_dateformatter_fetch_object(new_obj);
7571
/* clone standard parts */
7672
zend_objects_clone_members(&new_dfo->zo, &dfo->zo);
73+
7774
/* clone formatter object */
78-
if (dfo->datef_data.udatf != NULL) {
79-
DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(dfo));
80-
if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
81-
/* set up error in case error handler is interested */
82-
intl_errors_set(INTL_DATA_ERROR_P(dfo), INTL_DATA_ERROR_CODE(dfo),
83-
"Failed to clone IntlDateFormatter object", 0 );
84-
zend_throw_exception(NULL, "Failed to clone IntlDateFormatter object", 0);
75+
if (DATE_FORMAT_OBJECT(dfo) != NULL) {
76+
UErrorCode error = U_ZERO_ERROR;
77+
DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &error);
78+
79+
if (U_FAILURE(error)) {
80+
zend_throw_error(NULL, "Failed to clone IntlDateFormatter");
8581
}
8682
} else {
87-
zend_throw_exception(NULL, "Cannot clone unconstructed IntlDateFormatter", 0);
83+
zend_throw_error(NULL, "Cannot clone uninitialized IntlDateFormatter");
8884
}
8985
return new_obj;
9086
}

ext/intl/dateformat/datepatterngenerator_class.cpp

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,32 +36,21 @@ zend_object_handlers IntlDatePatternGenerator_handlers;
3636

3737
static zend_object *IntlDatePatternGenerator_object_clone(zend_object *object)
3838
{
39-
intl_error_reset(NULL);
40-
4139
IntlDatePatternGenerator_object *dtpgo_orig = php_intl_datepatterngenerator_fetch_object(object);
42-
intl_error_reset(DTPATTERNGEN_ERROR_P(dtpgo_orig));
43-
44-
zend_object *ret_val = IntlDatePatternGenerator_ce_ptr->create_object(object->ce);
45-
IntlDatePatternGenerator_object *dtpgo_new = php_intl_datepatterngenerator_fetch_object(ret_val);
40+
zend_object *ret_val = IntlDatePatternGenerator_ce_ptr->create_object(object->ce);
41+
IntlDatePatternGenerator_object *dtpgo_new = php_intl_datepatterngenerator_fetch_object(ret_val);
4642

4743
zend_objects_clone_members(&dtpgo_new->zo, &dtpgo_orig->zo);
4844

4945
if (dtpgo_orig->dtpg != NULL) {
5046
DateTimePatternGenerator *newDtpg = dtpgo_orig->dtpg->clone();
5147
if (!newDtpg) {
52-
zend_string *err_msg;
53-
intl_errors_set_code(DTPATTERNGEN_ERROR_P(dtpgo_orig),
54-
U_MEMORY_ALLOCATION_ERROR);
55-
intl_errors_set_custom_msg(DTPATTERNGEN_ERROR_P(dtpgo_orig),
56-
"Could not clone IntlDatePatternGenerator", 0);
57-
err_msg = intl_error_get_message(DTPATTERNGEN_ERROR_P(dtpgo_orig));
58-
zend_throw_exception(NULL, ZSTR_VAL(err_msg), 0);
59-
zend_string_free(err_msg);
48+
zend_throw_error(NULL, "Failed to clone IntlDatePatternGenerator");
6049
} else {
6150
dtpgo_new->dtpg = newDtpg;
6251
}
6352
} else {
64-
zend_throw_exception(NULL, "Cannot clone unconstructed IntlDatePatternGenerator", 0);
53+
zend_throw_error(NULL, "Cannot clone uninitialized IntlDatePatternGenerator");
6554
}
6655

6756
return ret_val;

ext/intl/formatter/formatter_class.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,22 @@ zend_object *NumberFormatter_object_create(zend_class_entry *ce)
5858
/* {{{ NumberFormatter_object_clone */
5959
zend_object *NumberFormatter_object_clone(zend_object *object)
6060
{
61-
NumberFormatter_object *nfo, *new_nfo;
62-
zend_object *new_obj;
61+
NumberFormatter_object *nfo = php_intl_number_format_fetch_object(object);
62+
zend_object *new_obj = NumberFormatter_ce_ptr->create_object(object->ce);
63+
NumberFormatter_object *new_nfo = php_intl_number_format_fetch_object(new_obj);
6364

64-
nfo = php_intl_number_format_fetch_object(object);
65-
intl_error_reset(INTL_DATA_ERROR_P(nfo));
66-
67-
new_obj = NumberFormatter_ce_ptr->create_object(object->ce);
68-
new_nfo = php_intl_number_format_fetch_object(new_obj);
6965
/* clone standard parts */
7066
zend_objects_clone_members(&new_nfo->zo, &nfo->zo);
67+
7168
/* clone formatter object. It may fail, the destruction code must handle this case */
7269
if (FORMATTER_OBJECT(nfo) != NULL) {
73-
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo),
74-
&INTL_DATA_ERROR_CODE(nfo));
75-
if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
76-
/* set up error in case error handler is interested */
77-
intl_errors_set(INTL_DATA_ERROR_P(nfo), INTL_DATA_ERROR_CODE(nfo),
78-
"Failed to clone NumberFormatter object", 0);
79-
zend_throw_exception(NULL, "Failed to clone NumberFormatter object", 0);
70+
UErrorCode error = U_ZERO_ERROR;
71+
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &error);
72+
if (U_FAILURE(error)) {
73+
zend_throw_error(NULL, "Failed to clone NumberFormatter");
8074
}
8175
} else {
82-
zend_throw_exception(NULL, "Cannot clone unconstructed NumberFormatter", 0);
76+
zend_throw_error(NULL, "Cannot clone uninitialized NumberFormatter");
8377
}
8478
return new_obj;
8579
}

ext/intl/msgformat/msgformat_class.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,29 +56,23 @@ zend_object *MessageFormatter_object_create(zend_class_entry *ce)
5656
/* {{{ MessageFormatter_object_clone */
5757
zend_object *MessageFormatter_object_clone(zend_object *object)
5858
{
59-
MessageFormatter_object *mfo, *new_mfo;
60-
zend_object *new_obj;
59+
MessageFormatter_object *mfo = php_intl_messageformatter_fetch_object(object);
60+
zend_object *new_obj = MessageFormatter_ce_ptr->create_object(object->ce);
61+
MessageFormatter_object *new_mfo = php_intl_messageformatter_fetch_object(new_obj);
6162

62-
mfo = php_intl_messageformatter_fetch_object(object);
63-
intl_error_reset(INTL_DATA_ERROR_P(mfo));
64-
65-
new_obj = MessageFormatter_ce_ptr->create_object(object->ce);
66-
new_mfo = php_intl_messageformatter_fetch_object(new_obj);
6763
/* clone standard parts */
6864
zend_objects_clone_members(&new_mfo->zo, &mfo->zo);
6965

7066
/* clone formatter object */
7167
if (MSG_FORMAT_OBJECT(mfo) != NULL) {
72-
MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo),
73-
&INTL_DATA_ERROR_CODE(mfo));
68+
UErrorCode error = U_ZERO_ERROR;
69+
MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &error);
7470

75-
if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) {
76-
intl_errors_set(INTL_DATA_ERROR_P(mfo), INTL_DATA_ERROR_CODE(mfo),
77-
"Failed to clone MessageFormatter object", 0);
78-
zend_throw_exception_ex(NULL, 0, "Failed to clone MessageFormatter object");
71+
if (U_FAILURE(error)) {
72+
zend_throw_error(NULL, "Failed to clone MessageFormatter");
7973
}
8074
} else {
81-
zend_throw_exception_ex(NULL, 0, "Cannot clone unconstructed MessageFormatter");
75+
zend_throw_error(NULL, "Cannot clone uninitialized MessageFormatter");
8276
}
8377
return new_obj;
8478
}

ext/intl/spoofchecker/spoofchecker_class.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,25 @@ zend_object *Spoofchecker_object_create(zend_class_entry *ce)
6161

6262
static zend_object *spoofchecker_clone_obj(zend_object *object) /* {{{ */
6363
{
64-
zend_object *new_obj_val;
65-
Spoofchecker_object *sfo, *new_sfo;
66-
67-
sfo = php_intl_spoofchecker_fetch_object(object);
68-
intl_error_reset(SPOOFCHECKER_ERROR_P(sfo));
69-
70-
new_obj_val = Spoofchecker_ce_ptr->create_object(object->ce);
71-
new_sfo = php_intl_spoofchecker_fetch_object(new_obj_val);
72-
/* clone standard parts */
73-
zend_objects_clone_members(&new_sfo->zo, &sfo->zo);
74-
/* clone internal object */
75-
new_sfo->uspoof = uspoof_clone(sfo->uspoof, SPOOFCHECKER_ERROR_CODE_P(new_sfo));
76-
if(U_FAILURE(SPOOFCHECKER_ERROR_CODE(new_sfo))) {
77-
/* set up error in case error handler is interested */
78-
intl_error_set( NULL, SPOOFCHECKER_ERROR_CODE(new_sfo), "Failed to clone SpoofChecker object", 0 );
79-
Spoofchecker_objects_free(&new_sfo->zo); /* free new object */
80-
zend_error_noreturn(E_ERROR, "Failed to clone SpoofChecker object");
64+
Spoofchecker_object *spoofchecker_orig = php_intl_spoofchecker_fetch_object(object);
65+
zend_object *new_obj_val = Spoofchecker_ce_ptr->create_object(object->ce);
66+
Spoofchecker_object *spoofchecker_new = php_intl_spoofchecker_fetch_object(new_obj_val);
67+
68+
zend_objects_clone_members(&spoofchecker_new->zo, &spoofchecker_orig->zo);
69+
70+
if (spoofchecker_orig->uspoof != NULL) {
71+
/* guaranteed to return NULL if it fails */
72+
UErrorCode error = U_ZERO_ERROR;
73+
spoofchecker_new->uspoof = uspoof_clone(spoofchecker_orig->uspoof, &error);
74+
if (U_FAILURE(error)) {
75+
/* free new object */
76+
Spoofchecker_objects_free(&spoofchecker_new->zo);
77+
zend_throw_error(NULL, "Failed to clone SpoofChecker");
78+
}
79+
} else {
80+
zend_throw_error(NULL, "Cannot clone uninitialized SpoofChecker");
8181
}
82+
8283
return new_obj_val;
8384
}
8485
/* }}} */

ext/intl/tests/bug62915.phpt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ intl
77

88
class foo extends IntlTimeZone {
99
public $foo = 'test';
10-
11-
public function __construct() { }
10+
public function __construct() { }
1211
}
1312

1413
$x = new foo;
1514

1615
try {
17-
$z = clone $x;
18-
} catch (Exception $e) {
19-
var_dump($e->getMessage());
16+
$z = clone $x;
17+
var_dump($z);
18+
} catch (Throwable $e) {
19+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
2020
}
2121
?>
2222
--EXPECT--
23-
string(39) "Cannot clone unconstructed IntlTimeZone"
23+
Error: Cannot clone uninitialized IntlTimeZone
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Cloning unconstructed IntlDateFormatter
2+
Cloning uninitialized IntlDateFormatter
33
--EXTENSIONS--
44
intl
55
--FILE--
@@ -12,9 +12,10 @@ class A extends IntlDateFormatter {
1212
$a = new A;
1313
try {
1414
$b = clone $a;
15-
} catch (Exception $e) {
16-
var_dump($e->getMessage());
15+
var_dump($b);
16+
} catch (Throwable $e) {
17+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1718
}
1819
?>
19-
--EXPECTF--
20-
string(%s) "Cannot clone unconstructed IntlDateFormatter"
20+
--EXPECT--
21+
Error: Cannot clone uninitialized IntlDateFormatter

ext/intl/tests/formatter_clone_bad_obj.phpt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Cloning unconstructed numfmt
2+
Cloning uninitialized NumberFormatter
33
--EXTENSIONS--
44
intl
55
--FILE--
@@ -12,9 +12,10 @@ class A extends NumberFormatter {
1212
$a = new A;
1313
try {
1414
$b = clone $a;
15-
} catch (Exception $e) {
16-
var_dump($e->getMessage());
15+
var_dump($b);
16+
} catch (Throwable $e) {
17+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1718
}
1819
?>
1920
--EXPECT--
20-
string(42) "Cannot clone unconstructed NumberFormatter"
21+
Error: Cannot clone uninitialized NumberFormatter
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Cloning unconstructed MessageFormatter
2+
Cloning uninitialized MessageFormatter
33
--EXTENSIONS--
44
intl
55
--FILE--
@@ -12,9 +12,10 @@ class A extends MessageFormatter {
1212
$a = new A;
1313
try {
1414
$b = clone $a;
15-
} catch (Exception $e) {
16-
var_dump($e->getMessage());
15+
var_dump($b);
16+
} catch (Throwable $e) {
17+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1718
}
1819
?>
19-
--EXPECTF--
20-
string(%d) "Cannot clone unconstructed MessageFormatter"
20+
--EXPECT--
21+
Error: Cannot clone uninitialized MessageFormatter

0 commit comments

Comments
 (0)