summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorGustavo Lopes <glopes@nebm.ist.utl.pt>2012-08-21 23:21:59 +0200
committerGustavo Lopes <glopes@nebm.ist.utl.pt>2012-08-22 22:32:51 +0200
commita5d0c1e21b9fa166d8fe5ec7d52a24a5f7adc107 (patch)
tree2ed39a52ede3d5e9dce93ffa5e0b1aff39698b69 /ext
parente5bdd2c0eeab50dc1f863dae9a32d3857ece6a79 (diff)
downloadphp-git-a5d0c1e21b9fa166d8fe5ec7d52a24a5f7adc107.tar.gz
Fix handling of several uinitialized intl objects
Diffstat (limited to 'ext')
-rw-r--r--ext/intl/collator/collator_class.h9
-rw-r--r--ext/intl/collator/collator_create.c2
-rw-r--r--ext/intl/dateformat/dateformat.c2
-rw-r--r--ext/intl/dateformat/dateformat_attr.c5
-rw-r--r--ext/intl/dateformat/dateformat_class.c21
-rw-r--r--ext/intl/dateformat/dateformat_class.h10
-rw-r--r--ext/intl/formatter/formatter_class.c23
-rw-r--r--ext/intl/formatter/formatter_class.h15
-rw-r--r--ext/intl/formatter/formatter_main.c2
-rw-r--r--ext/intl/msgformat/msgformat.c2
-rw-r--r--ext/intl/msgformat/msgformat_class.c22
-rw-r--r--ext/intl/msgformat/msgformat_class.h10
-rw-r--r--ext/intl/resourcebundle/resourcebundle_class.c9
-rw-r--r--ext/intl/resourcebundle/resourcebundle_class.h11
-rw-r--r--ext/intl/tests/dateformat_clone_bad_obj.phpt20
-rw-r--r--ext/intl/tests/formatter_clone_bad_obj.phpt20
-rw-r--r--ext/intl/tests/msgfmt_clone_bad_obj.phpt20
17 files changed, 163 insertions, 40 deletions
diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h
index 835abd66c8..7a56dfce50 100644
--- a/ext/intl/collator/collator_class.h
+++ b/ext/intl/collator/collator_class.h
@@ -20,8 +20,9 @@
#include <php.h>
-#include "intl_common.h"
-#include "intl_error.h"
+#include "../intl_common.h"
+#include "../intl_error.h"
+#include "../intl_data.h"
#include <unicode/ucol.h>
@@ -54,9 +55,7 @@ extern zend_class_entry *Collator_ce_ptr;
Collator_object* co = NULL; \
intl_error_reset( NULL TSRMLS_CC ); \
-#define COLLATOR_METHOD_FETCH_OBJECT \
- co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); \
- intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); \
+#define COLLATOR_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(Collator, co)
// Macro to check return value of a ucol_* function call.
#define COLLATOR_CHECK_STATUS( co, msg ) \
diff --git a/ext/intl/collator/collator_create.c b/ext/intl/collator/collator_create.c
index 0f0cc193e4..b2a9968af4 100644
--- a/ext/intl/collator/collator_create.c
+++ b/ext/intl/collator/collator_create.c
@@ -45,7 +45,7 @@ static void collator_ctor(INTERNAL_FUNCTION_PARAMETERS)
}
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
- co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC );
+ COLLATOR_METHOD_FETCH_OBJECT;
if(locale_len == 0) {
locale = INTL_G(default_locale);
diff --git a/ext/intl/dateformat/dateformat.c b/ext/intl/dateformat/dateformat.c
index b399a39fcb..8aded18bd6 100644
--- a/ext/intl/dateformat/dateformat.c
+++ b/ext/intl/dateformat/dateformat.c
@@ -108,7 +108,7 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
goto error;
}
- DATE_FORMAT_METHOD_FETCH_OBJECT;
+ DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
if (DATE_FORMAT_OBJECT(dfo) != NULL) {
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,
diff --git a/ext/intl/dateformat/dateformat_attr.c b/ext/intl/dateformat/dateformat_attr.c
index 6131cedc95..b8c5f25e3a 100644
--- a/ext/intl/dateformat/dateformat_attr.c
+++ b/ext/intl/dateformat/dateformat_attr.c
@@ -17,8 +17,9 @@
#include "config.h"
#endif
-#include "php_intl.h"
-#include "intl_convert.h"
+#include "../php_intl.h"
+#include "dateformat_class.h"
+#include "../intl_convert.h"
#include "dateformat_class.h"
#include "dateformat_attr.h"
diff --git a/ext/intl/dateformat/dateformat_class.c b/ext/intl/dateformat/dateformat_class.c
index eb3f5f4e77..85a67f7f9f 100644
--- a/ext/intl/dateformat/dateformat_class.c
+++ b/ext/intl/dateformat/dateformat_class.c
@@ -23,6 +23,8 @@
#include "dateformat.h"
#include "dateformat_attr.h"
+#include <zend_exceptions.h>
+
zend_class_entry *IntlDateFormatter_ce_ptr = NULL;
static zend_object_handlers IntlDateFormatter_handlers;
@@ -87,18 +89,23 @@ zend_object_value IntlDateFormatter_object_clone(zval *object TSRMLS_DC)
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
IntlDateFormatter_object *dfo, *new_dfo;
- DATE_FORMAT_METHOD_FETCH_OBJECT;
+ DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
+
new_obj_val = IntlDateFormatter_ce_ptr->create_object(IntlDateFormatter_ce_ptr TSRMLS_CC);
new_dfo = (IntlDateFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
/* clone standard parts */
zend_objects_clone_members(&new_dfo->zo, new_obj_val, &dfo->zo, handle TSRMLS_CC);
/* clone formatter object */
- DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(new_dfo));
- if(U_FAILURE(INTL_DATA_ERROR_CODE(new_dfo))) {
- /* set up error in case error handler is interested */
- intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_dfo), "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC );
- IntlDateFormatter_object_dtor(new_dfo, new_obj_val.handle TSRMLS_CC); /* free new object */
- zend_error(E_ERROR, "Failed to clone IntlDateFormatter object");
+ if (dfo->datef_data.udatf != NULL) {
+ DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(dfo));
+ if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
+ /* set up error in case error handler is interested */
+ intl_errors_set(INTL_DATA_ERROR_P(dfo), INTL_DATA_ERROR_CODE(dfo),
+ "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC );
+ zend_throw_exception(NULL, "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC);
+ }
+ } else {
+ zend_throw_exception(NULL, "Cannot clone unconstructed IntlDateFormatter", 0 TSRMLS_CC);
}
return new_obj_val;
}
diff --git a/ext/intl/dateformat/dateformat_class.h b/ext/intl/dateformat/dateformat_class.h
index 9ad83ee3d6..d58abe42f5 100644
--- a/ext/intl/dateformat/dateformat_class.h
+++ b/ext/intl/dateformat/dateformat_class.h
@@ -38,7 +38,15 @@ extern zend_class_entry *IntlDateFormatter_ce_ptr;
/* Auxiliary macros */
#define DATE_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(IntlDateFormatter, dfo)
-#define DATE_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, dfo)
+#define DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, dfo)
+#define DATE_FORMAT_METHOD_FETCH_OBJECT \
+ DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; \
+ if (dfo->datef_data.udatf == NULL) \
+ { \
+ intl_errors_set(&dfo->datef_data.error, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed IntlDateFormatter", 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ }
+
#define DATE_FORMAT_OBJECT(dfo) (dfo)->datef_data.udatf
#endif // #ifndef DATE_FORMAT_CLASS_H
diff --git a/ext/intl/formatter/formatter_class.c b/ext/intl/formatter/formatter_class.c
index 0bb5894f09..5790f0c2e1 100644
--- a/ext/intl/formatter/formatter_class.c
+++ b/ext/intl/formatter/formatter_class.c
@@ -24,6 +24,8 @@
#include "formatter_main.h"
#include "formatter_attr.h"
+#include <zend_exceptions.h>
+
zend_class_entry *NumberFormatter_ce_ptr = NULL;
static zend_object_handlers NumberFormatter_handlers;
@@ -82,18 +84,23 @@ zend_object_value NumberFormatter_object_clone(zval *object TSRMLS_DC)
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
NumberFormatter_object *nfo, *new_nfo;
- FORMATTER_METHOD_FETCH_OBJECT;
+ FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK;
new_obj_val = NumberFormatter_ce_ptr->create_object(NumberFormatter_ce_ptr TSRMLS_CC);
new_nfo = (NumberFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
/* clone standard parts */
zend_objects_clone_members(&new_nfo->zo, new_obj_val, &nfo->zo, handle TSRMLS_CC);
- /* clone formatter object */
- FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &INTL_DATA_ERROR_CODE(new_nfo));
- if(U_FAILURE(INTL_DATA_ERROR_CODE(new_nfo))) {
- /* set up error in case error handler is interested */
- intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_nfo), "Failed to clone NumberFormatter object", 0 TSRMLS_CC );
- NumberFormatter_object_dtor(new_nfo, new_obj_val.handle TSRMLS_CC); /* free new object */
- zend_error(E_ERROR, "Failed to clone NumberFormatter object");
+ /* clone formatter object. It may fail, the destruction code must handle this case */
+ if (FORMATTER_OBJECT(nfo) != NULL) {
+ FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo),
+ &INTL_DATA_ERROR_CODE(nfo));
+ if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
+ /* set up error in case error handler is interested */
+ intl_errors_set(INTL_DATA_ERROR_P(nfo), INTL_DATA_ERROR_CODE(nfo),
+ "Failed to clone NumberFormatter object", 0 TSRMLS_CC);
+ zend_throw_exception(NULL, "Failed to clone NumberFormatter object", 0 TSRMLS_CC);
+ }
+ } else {
+ zend_throw_exception(NULL, "Cannot clone unconstructed NumberFormatter", 0 TSRMLS_CC);
}
return new_obj_val;
}
diff --git a/ext/intl/formatter/formatter_class.h b/ext/intl/formatter/formatter_class.h
index cf1cb060c6..9582866664 100644
--- a/ext/intl/formatter/formatter_class.h
+++ b/ext/intl/formatter/formatter_class.h
@@ -34,8 +34,17 @@ extern zend_class_entry *NumberFormatter_ce_ptr;
/* Auxiliary macros */
-#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo)
-#define FORMATTER_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo)
-#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum
+#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo)
+#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum
+#define FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo)
+#define FORMATTER_METHOD_FETCH_OBJECT \
+ FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; \
+ if (FORMATTER_OBJECT(nfo) == NULL) \
+ { \
+ intl_errors_set(&nfo->nf_data.error, U_ILLEGAL_ARGUMENT_ERROR, \
+ "Found unconstructed NumberFormatter", 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ }
+
#endif // #ifndef FORMATTER_CLASS_H
diff --git a/ext/intl/formatter/formatter_main.c b/ext/intl/formatter/formatter_main.c
index 8fa17560b8..5cb6483326 100644
--- a/ext/intl/formatter/formatter_main.c
+++ b/ext/intl/formatter/formatter_main.c
@@ -47,7 +47,7 @@ static void numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
object = return_value;
- FORMATTER_METHOD_FETCH_OBJECT;
+ FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK;
/* Convert pattern (if specified) to UTF-16. */
if(pattern && pattern_len) {
diff --git a/ext/intl/msgformat/msgformat.c b/ext/intl/msgformat/msgformat.c
index 0a01204fae..e3fb9425a9 100644
--- a/ext/intl/msgformat/msgformat.c
+++ b/ext/intl/msgformat/msgformat.c
@@ -49,7 +49,7 @@ static void msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
}
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
- MSG_FORMAT_METHOD_FETCH_OBJECT;
+ MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
/* Convert pattern (if specified) to UTF-16. */
if(pattern && pattern_len) {
diff --git a/ext/intl/msgformat/msgformat_class.c b/ext/intl/msgformat/msgformat_class.c
index 7ed28df3dc..9cccef2709 100644
--- a/ext/intl/msgformat/msgformat_class.c
+++ b/ext/intl/msgformat/msgformat_class.c
@@ -24,6 +24,8 @@
#include "msgformat.h"
#include "msgformat_attr.h"
+#include <zend_exceptions.h>
+
zend_class_entry *MessageFormatter_ce_ptr = NULL;
static zend_object_handlers MessageFormatter_handlers;
@@ -80,18 +82,24 @@ zend_object_value MessageFormatter_object_clone(zval *object TSRMLS_DC)
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
MessageFormatter_object *mfo, *new_mfo;
- MSG_FORMAT_METHOD_FETCH_OBJECT;
+ MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
new_obj_val = MessageFormatter_ce_ptr->create_object(MessageFormatter_ce_ptr TSRMLS_CC);
new_mfo = (MessageFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
/* clone standard parts */
zend_objects_clone_members(&new_mfo->zo, new_obj_val, &mfo->zo, handle TSRMLS_CC);
+
/* clone formatter object */
- MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &INTL_DATA_ERROR_CODE(new_mfo));
- if(U_FAILURE(INTL_DATA_ERROR_CODE(new_mfo))) {
- /* set up error in case error handler is interested */
- intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_mfo), "Failed to clone MessageFormatter object", 0 TSRMLS_CC );
- MessageFormatter_object_dtor(new_mfo, new_obj_val.handle TSRMLS_CC); /* free new object */
- zend_error(E_ERROR, "Failed to clone MessageFormatter object");
+ if (MSG_FORMAT_OBJECT(mfo) != NULL) {
+ MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo),
+ &INTL_DATA_ERROR_CODE(mfo));
+
+ if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) {
+ intl_errors_set(INTL_DATA_ERROR_P(mfo), INTL_DATA_ERROR_CODE(mfo),
+ "Failed to clone MessageFormatter object", 0 TSRMLS_CC);
+ zend_throw_exception_ex(NULL, 0, "Failed to clone MessageFormatter object");
+ }
+ } else {
+ zend_throw_exception_ex(NULL, 0, "Cannot clone unconstructed MessageFormatter");
}
return new_obj_val;
}
diff --git a/ext/intl/msgformat/msgformat_class.h b/ext/intl/msgformat/msgformat_class.h
index b6b8e33226..337e04e647 100644
--- a/ext/intl/msgformat/msgformat_class.h
+++ b/ext/intl/msgformat/msgformat_class.h
@@ -37,7 +37,15 @@ extern zend_class_entry *MessageFormatter_ce_ptr;
/* Auxiliary macros */
#define MSG_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(MessageFormatter, mfo)
-#define MSG_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(MessageFormatter, mfo)
+#define MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(MessageFormatter, mfo)
+#define MSG_FORMAT_METHOD_FETCH_OBJECT \
+ MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; \
+ if (MSG_FORMAT_OBJECT(mfo) == NULL) { \
+ intl_errors_set(&mfo->mf_data.error, U_ILLEGAL_ARGUMENT_ERROR, \
+ "Found unconstructed MessageFormatter", 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ }
+
#define MSG_FORMAT_OBJECT(mfo) (mfo)->mf_data.umsgf
#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM < 48
diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c
index d2a29d9b25..9c0459e1a3 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.c
+++ b/ext/intl/resourcebundle/resourcebundle_class.c
@@ -252,7 +252,14 @@ PHP_FUNCTION( resourcebundle_get )
/* {{{ resourcebundle_array_count */
int resourcebundle_array_count(zval *object, long *count TSRMLS_DC)
{
- ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
+ ResourceBundle_object *rb;
+ RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK;
+
+ if (rb->me == NULL) {
+ intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR,
+ "Found unconstructed ResourceBundle", 0 TSRMLS_CC);
+ return 0;
+ }
*count = ures_getSize( rb->me );
diff --git a/ext/intl/resourcebundle/resourcebundle_class.h b/ext/intl/resourcebundle/resourcebundle_class.h
index 4755d723b8..8da3ed9d47 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.h
+++ b/ext/intl/resourcebundle/resourcebundle_class.h
@@ -33,7 +33,16 @@ typedef struct {
} ResourceBundle_object;
#define RESOURCEBUNDLE_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(ResourceBundle, rb)
-#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb)
+#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb)
+#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT \
+ INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb); \
+ if (RESOURCEBUNDLE_OBJECT(rb) == NULL) { \
+ intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR, \
+ "Found unconstructed ResourceBundle", 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ }
+
+
#define RESOURCEBUNDLE_OBJECT(rb) (rb)->me
void resourcebundle_register_class( TSRMLS_D );
diff --git a/ext/intl/tests/dateformat_clone_bad_obj.phpt b/ext/intl/tests/dateformat_clone_bad_obj.phpt
new file mode 100644
index 0000000000..5e12b96ae8
--- /dev/null
+++ b/ext/intl/tests/dateformat_clone_bad_obj.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Cloning unconstructed IntlDateFormatter
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+class A extends IntlDateFormatter {
+ function __construct() {}
+}
+
+$a = new A;
+try {
+ $b = clone $a;
+} catch (Exception $e) {
+ var_dump($e->getMessage());
+}
+
+--EXPECTF--
+string(%s) "Cannot clone unconstructed IntlDateFormatter"
diff --git a/ext/intl/tests/formatter_clone_bad_obj.phpt b/ext/intl/tests/formatter_clone_bad_obj.phpt
new file mode 100644
index 0000000000..ef7b28a546
--- /dev/null
+++ b/ext/intl/tests/formatter_clone_bad_obj.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Cloning unconstructed numfmt
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+class A extends NumberFormatter {
+ function __construct() {}
+}
+
+$a = new A;
+try {
+ $b = clone $a;
+} catch (Exception $e) {
+ var_dump($e->getMessage());
+}
+
+--EXPECTF--
+string(42) "Cannot clone unconstructed NumberFormatter"
diff --git a/ext/intl/tests/msgfmt_clone_bad_obj.phpt b/ext/intl/tests/msgfmt_clone_bad_obj.phpt
new file mode 100644
index 0000000000..48321094d1
--- /dev/null
+++ b/ext/intl/tests/msgfmt_clone_bad_obj.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Cloning unconstructed MessageFormatter
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+class A extends MessageFormatter {
+ function __construct() {}
+}
+
+$a = new A;
+try {
+ $b = clone $a;
+} catch (Exception $e) {
+ var_dump($e->getMessage());
+}
+
+--EXPECTF--
+string(%d) "Cannot clone unconstructed MessageFormatter"