Skip to content

Commit a5d0c1e

Browse files
committed
Fix handling of several uinitialized intl objects
1 parent e5bdd2c commit a5d0c1e

17 files changed

+163
-40
lines changed

ext/intl/collator/collator_class.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020

2121
#include <php.h>
2222

23-
#include "intl_common.h"
24-
#include "intl_error.h"
23+
#include "../intl_common.h"
24+
#include "../intl_error.h"
25+
#include "../intl_data.h"
2526

2627
#include <unicode/ucol.h>
2728

@@ -54,9 +55,7 @@ extern zend_class_entry *Collator_ce_ptr;
5455
Collator_object* co = NULL; \
5556
intl_error_reset( NULL TSRMLS_CC ); \
5657

57-
#define COLLATOR_METHOD_FETCH_OBJECT \
58-
co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); \
59-
intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); \
58+
#define COLLATOR_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(Collator, co)
6059

6160
// Macro to check return value of a ucol_* function call.
6261
#define COLLATOR_CHECK_STATUS( co, msg ) \

ext/intl/collator/collator_create.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void collator_ctor(INTERNAL_FUNCTION_PARAMETERS)
4545
}
4646

4747
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
48-
co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC );
48+
COLLATOR_METHOD_FETCH_OBJECT;
4949

5050
if(locale_len == 0) {
5151
locale = INTL_G(default_locale);

ext/intl/dateformat/dateformat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
108108
goto error;
109109
}
110110

111-
DATE_FORMAT_METHOD_FETCH_OBJECT;
111+
DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
112112

113113
if (DATE_FORMAT_OBJECT(dfo) != NULL) {
114114
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,

ext/intl/dateformat/dateformat_attr.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
#include "config.h"
1818
#endif
1919

20-
#include "php_intl.h"
21-
#include "intl_convert.h"
20+
#include "../php_intl.h"
21+
#include "dateformat_class.h"
22+
#include "../intl_convert.h"
2223
#include "dateformat_class.h"
2324
#include "dateformat_attr.h"
2425

ext/intl/dateformat/dateformat_class.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "dateformat.h"
2424
#include "dateformat_attr.h"
2525

26+
#include <zend_exceptions.h>
27+
2628
zend_class_entry *IntlDateFormatter_ce_ptr = NULL;
2729
static zend_object_handlers IntlDateFormatter_handlers;
2830

@@ -87,18 +89,23 @@ zend_object_value IntlDateFormatter_object_clone(zval *object TSRMLS_DC)
8789
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
8890
IntlDateFormatter_object *dfo, *new_dfo;
8991

90-
DATE_FORMAT_METHOD_FETCH_OBJECT;
92+
DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
93+
9194
new_obj_val = IntlDateFormatter_ce_ptr->create_object(IntlDateFormatter_ce_ptr TSRMLS_CC);
9295
new_dfo = (IntlDateFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
9396
/* clone standard parts */
9497
zend_objects_clone_members(&new_dfo->zo, new_obj_val, &dfo->zo, handle TSRMLS_CC);
9598
/* clone formatter object */
96-
DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(new_dfo));
97-
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_dfo))) {
98-
/* set up error in case error handler is interested */
99-
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_dfo), "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC );
100-
IntlDateFormatter_object_dtor(new_dfo, new_obj_val.handle TSRMLS_CC); /* free new object */
101-
zend_error(E_ERROR, "Failed to clone IntlDateFormatter object");
99+
if (dfo->datef_data.udatf != NULL) {
100+
DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(dfo));
101+
if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
102+
/* set up error in case error handler is interested */
103+
intl_errors_set(INTL_DATA_ERROR_P(dfo), INTL_DATA_ERROR_CODE(dfo),
104+
"Failed to clone IntlDateFormatter object", 0 TSRMLS_CC );
105+
zend_throw_exception(NULL, "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC);
106+
}
107+
} else {
108+
zend_throw_exception(NULL, "Cannot clone unconstructed IntlDateFormatter", 0 TSRMLS_CC);
102109
}
103110
return new_obj_val;
104111
}

ext/intl/dateformat/dateformat_class.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ extern zend_class_entry *IntlDateFormatter_ce_ptr;
3838
/* Auxiliary macros */
3939

4040
#define DATE_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(IntlDateFormatter, dfo)
41-
#define DATE_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, dfo)
41+
#define DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, dfo)
42+
#define DATE_FORMAT_METHOD_FETCH_OBJECT \
43+
DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; \
44+
if (dfo->datef_data.udatf == NULL) \
45+
{ \
46+
intl_errors_set(&dfo->datef_data.error, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed IntlDateFormatter", 0 TSRMLS_CC); \
47+
RETURN_FALSE; \
48+
}
49+
4250
#define DATE_FORMAT_OBJECT(dfo) (dfo)->datef_data.udatf
4351

4452
#endif // #ifndef DATE_FORMAT_CLASS_H

ext/intl/formatter/formatter_class.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "formatter_main.h"
2525
#include "formatter_attr.h"
2626

27+
#include <zend_exceptions.h>
28+
2729
zend_class_entry *NumberFormatter_ce_ptr = NULL;
2830
static zend_object_handlers NumberFormatter_handlers;
2931

@@ -82,18 +84,23 @@ zend_object_value NumberFormatter_object_clone(zval *object TSRMLS_DC)
8284
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
8385
NumberFormatter_object *nfo, *new_nfo;
8486

85-
FORMATTER_METHOD_FETCH_OBJECT;
87+
FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK;
8688
new_obj_val = NumberFormatter_ce_ptr->create_object(NumberFormatter_ce_ptr TSRMLS_CC);
8789
new_nfo = (NumberFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
8890
/* clone standard parts */
8991
zend_objects_clone_members(&new_nfo->zo, new_obj_val, &nfo->zo, handle TSRMLS_CC);
90-
/* clone formatter object */
91-
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &INTL_DATA_ERROR_CODE(new_nfo));
92-
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_nfo))) {
93-
/* set up error in case error handler is interested */
94-
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_nfo), "Failed to clone NumberFormatter object", 0 TSRMLS_CC );
95-
NumberFormatter_object_dtor(new_nfo, new_obj_val.handle TSRMLS_CC); /* free new object */
96-
zend_error(E_ERROR, "Failed to clone NumberFormatter object");
92+
/* clone formatter object. It may fail, the destruction code must handle this case */
93+
if (FORMATTER_OBJECT(nfo) != NULL) {
94+
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo),
95+
&INTL_DATA_ERROR_CODE(nfo));
96+
if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
97+
/* set up error in case error handler is interested */
98+
intl_errors_set(INTL_DATA_ERROR_P(nfo), INTL_DATA_ERROR_CODE(nfo),
99+
"Failed to clone NumberFormatter object", 0 TSRMLS_CC);
100+
zend_throw_exception(NULL, "Failed to clone NumberFormatter object", 0 TSRMLS_CC);
101+
}
102+
} else {
103+
zend_throw_exception(NULL, "Cannot clone unconstructed NumberFormatter", 0 TSRMLS_CC);
97104
}
98105
return new_obj_val;
99106
}

ext/intl/formatter/formatter_class.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,17 @@ extern zend_class_entry *NumberFormatter_ce_ptr;
3434

3535
/* Auxiliary macros */
3636

37-
#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo)
38-
#define FORMATTER_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo)
39-
#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum
37+
#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo)
38+
#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum
39+
#define FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo)
40+
#define FORMATTER_METHOD_FETCH_OBJECT \
41+
FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; \
42+
if (FORMATTER_OBJECT(nfo) == NULL) \
43+
{ \
44+
intl_errors_set(&nfo->nf_data.error, U_ILLEGAL_ARGUMENT_ERROR, \
45+
"Found unconstructed NumberFormatter", 0 TSRMLS_CC); \
46+
RETURN_FALSE; \
47+
}
48+
4049

4150
#endif // #ifndef FORMATTER_CLASS_H

ext/intl/formatter/formatter_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static void numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
4747

4848
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
4949
object = return_value;
50-
FORMATTER_METHOD_FETCH_OBJECT;
50+
FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK;
5151

5252
/* Convert pattern (if specified) to UTF-16. */
5353
if(pattern && pattern_len) {

ext/intl/msgformat/msgformat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static void msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
4949
}
5050

5151
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
52-
MSG_FORMAT_METHOD_FETCH_OBJECT;
52+
MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
5353

5454
/* Convert pattern (if specified) to UTF-16. */
5555
if(pattern && pattern_len) {

ext/intl/msgformat/msgformat_class.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "msgformat.h"
2525
#include "msgformat_attr.h"
2626

27+
#include <zend_exceptions.h>
28+
2729
zend_class_entry *MessageFormatter_ce_ptr = NULL;
2830
static zend_object_handlers MessageFormatter_handlers;
2931

@@ -80,18 +82,24 @@ zend_object_value MessageFormatter_object_clone(zval *object TSRMLS_DC)
8082
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
8183
MessageFormatter_object *mfo, *new_mfo;
8284

83-
MSG_FORMAT_METHOD_FETCH_OBJECT;
85+
MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
8486
new_obj_val = MessageFormatter_ce_ptr->create_object(MessageFormatter_ce_ptr TSRMLS_CC);
8587
new_mfo = (MessageFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
8688
/* clone standard parts */
8789
zend_objects_clone_members(&new_mfo->zo, new_obj_val, &mfo->zo, handle TSRMLS_CC);
90+
8891
/* clone formatter object */
89-
MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &INTL_DATA_ERROR_CODE(new_mfo));
90-
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_mfo))) {
91-
/* set up error in case error handler is interested */
92-
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_mfo), "Failed to clone MessageFormatter object", 0 TSRMLS_CC );
93-
MessageFormatter_object_dtor(new_mfo, new_obj_val.handle TSRMLS_CC); /* free new object */
94-
zend_error(E_ERROR, "Failed to clone MessageFormatter object");
92+
if (MSG_FORMAT_OBJECT(mfo) != NULL) {
93+
MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo),
94+
&INTL_DATA_ERROR_CODE(mfo));
95+
96+
if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) {
97+
intl_errors_set(INTL_DATA_ERROR_P(mfo), INTL_DATA_ERROR_CODE(mfo),
98+
"Failed to clone MessageFormatter object", 0 TSRMLS_CC);
99+
zend_throw_exception_ex(NULL, 0, "Failed to clone MessageFormatter object");
100+
}
101+
} else {
102+
zend_throw_exception_ex(NULL, 0, "Cannot clone unconstructed MessageFormatter");
95103
}
96104
return new_obj_val;
97105
}

ext/intl/msgformat/msgformat_class.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,15 @@ extern zend_class_entry *MessageFormatter_ce_ptr;
3737
/* Auxiliary macros */
3838

3939
#define MSG_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(MessageFormatter, mfo)
40-
#define MSG_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(MessageFormatter, mfo)
40+
#define MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(MessageFormatter, mfo)
41+
#define MSG_FORMAT_METHOD_FETCH_OBJECT \
42+
MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; \
43+
if (MSG_FORMAT_OBJECT(mfo) == NULL) { \
44+
intl_errors_set(&mfo->mf_data.error, U_ILLEGAL_ARGUMENT_ERROR, \
45+
"Found unconstructed MessageFormatter", 0 TSRMLS_CC); \
46+
RETURN_FALSE; \
47+
}
48+
4149
#define MSG_FORMAT_OBJECT(mfo) (mfo)->mf_data.umsgf
4250

4351
#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM < 48

ext/intl/resourcebundle/resourcebundle_class.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,14 @@ PHP_FUNCTION( resourcebundle_get )
252252
/* {{{ resourcebundle_array_count */
253253
int resourcebundle_array_count(zval *object, long *count TSRMLS_DC)
254254
{
255-
ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
255+
ResourceBundle_object *rb;
256+
RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK;
257+
258+
if (rb->me == NULL) {
259+
intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR,
260+
"Found unconstructed ResourceBundle", 0 TSRMLS_CC);
261+
return 0;
262+
}
256263

257264
*count = ures_getSize( rb->me );
258265

ext/intl/resourcebundle/resourcebundle_class.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,16 @@ typedef struct {
3333
} ResourceBundle_object;
3434

3535
#define RESOURCEBUNDLE_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(ResourceBundle, rb)
36-
#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb)
36+
#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb)
37+
#define RESOURCEBUNDLE_METHOD_FETCH_OBJECT \
38+
INTL_METHOD_FETCH_OBJECT(ResourceBundle, rb); \
39+
if (RESOURCEBUNDLE_OBJECT(rb) == NULL) { \
40+
intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR, \
41+
"Found unconstructed ResourceBundle", 0 TSRMLS_CC); \
42+
RETURN_FALSE; \
43+
}
44+
45+
3746
#define RESOURCEBUNDLE_OBJECT(rb) (rb)->me
3847

3948
void resourcebundle_register_class( TSRMLS_D );
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Cloning unconstructed IntlDateFormatter
3+
--SKIPIF--
4+
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5+
--FILE--
6+
<?php
7+
8+
class A extends IntlDateFormatter {
9+
function __construct() {}
10+
}
11+
12+
$a = new A;
13+
try {
14+
$b = clone $a;
15+
} catch (Exception $e) {
16+
var_dump($e->getMessage());
17+
}
18+
19+
--EXPECTF--
20+
string(%s) "Cannot clone unconstructed IntlDateFormatter"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Cloning unconstructed numfmt
3+
--SKIPIF--
4+
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5+
--FILE--
6+
<?php
7+
8+
class A extends NumberFormatter {
9+
function __construct() {}
10+
}
11+
12+
$a = new A;
13+
try {
14+
$b = clone $a;
15+
} catch (Exception $e) {
16+
var_dump($e->getMessage());
17+
}
18+
19+
--EXPECTF--
20+
string(42) "Cannot clone unconstructed NumberFormatter"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Cloning unconstructed MessageFormatter
3+
--SKIPIF--
4+
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5+
--FILE--
6+
<?php
7+
8+
class A extends MessageFormatter {
9+
function __construct() {}
10+
}
11+
12+
$a = new A;
13+
try {
14+
$b = clone $a;
15+
} catch (Exception $e) {
16+
var_dump($e->getMessage());
17+
}
18+
19+
--EXPECTF--
20+
string(%d) "Cannot clone unconstructed MessageFormatter"

0 commit comments

Comments
 (0)