]> granicus.if.org Git - php/commitdiff
Fix handling of several uinitialized intl objects
authorGustavo Lopes <glopes@nebm.ist.utl.pt>
Tue, 21 Aug 2012 21:21:59 +0000 (23:21 +0200)
committerGustavo Lopes <glopes@nebm.ist.utl.pt>
Wed, 22 Aug 2012 20:32:51 +0000 (22:32 +0200)
17 files changed:
ext/intl/collator/collator_class.h
ext/intl/collator/collator_create.c
ext/intl/dateformat/dateformat.c
ext/intl/dateformat/dateformat_attr.c
ext/intl/dateformat/dateformat_class.c
ext/intl/dateformat/dateformat_class.h
ext/intl/formatter/formatter_class.c
ext/intl/formatter/formatter_class.h
ext/intl/formatter/formatter_main.c
ext/intl/msgformat/msgformat.c
ext/intl/msgformat/msgformat_class.c
ext/intl/msgformat/msgformat_class.h
ext/intl/resourcebundle/resourcebundle_class.c
ext/intl/resourcebundle/resourcebundle_class.h
ext/intl/tests/dateformat_clone_bad_obj.phpt [new file with mode: 0644]
ext/intl/tests/formatter_clone_bad_obj.phpt [new file with mode: 0644]
ext/intl/tests/msgfmt_clone_bad_obj.phpt [new file with mode: 0644]

index 835abd66c8a166c973610a9b9027fce903150148..7a56dfce50878b9c41db4b5d2bc556c9a2fea4a8 100644 (file)
@@ -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 )                                        \
index 0f0cc193e4c34fb9f37fcd356516958bb0ee5ecc..b2a9968af49a686babb1fdf3ce646abf60cf7738 100644 (file)
@@ -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);
index b399a39fcb51156db0a86a3bd12becb34db4d979..8aded18bd64b3c02953b62866678b4934d99eb73 100644 (file)
@@ -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,
index 6131cedc956b5fd156486b7d38ad33bb1c4a35a6..b8c5f25e3aa037853c51941822a402468b256af2 100644 (file)
@@ -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"
 
index eb3f5f4e7706c7dae653e02b57df2ff331b8f92a..85a67f7f9fc6ea3d00e90d3e7e7b8089c49acd63 100644 (file)
@@ -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;
 }
index 9ad83ee3d63c94476a5e2e5b90ccb8a4a3f2aa73..d58abe42f586ed1070c1cc0b2f6a194b20d1e3a0 100644 (file)
@@ -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
index 0bb5894f096b53fae885e097ccad8857252de5a1..5790f0c2e198ff93b323560155e227ec7a7c11b6 100644 (file)
@@ -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;
 }
index cf1cb060c6d798ae533d08caef381d1b5d3f28ab..9582866664336452ba6e1ad57bcd92102432aa54 100644 (file)
@@ -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
index 8fa17560b89577ee21fe33e51117f9be46164a59..5cb648332600a9381c7231aa827ec162ef4286d2 100644 (file)
@@ -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) {
index 0a01204fae90d7ec285731ed85ee535635c78ff3..e3fb9425a9c528adfeb30909930ed2f2dc956fb7 100644 (file)
@@ -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) {
index 7ed28df3dc54caec56bbc8aa4716a44446d61f95..9cccef27093d1b9d022810bf3ec5b63a201725fc 100644 (file)
@@ -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;
 }
index b6b8e33226eabdc012c90d99e4c85c20e5b9f3c2..337e04e647da978ea1118042d743c531940d6160 100644 (file)
@@ -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
index d2a29d9b25c0ccf658b11c28b32570e2372e914e..9c0459e1a3e7b33ed0843051b8e2b0df7d1168c2 100644 (file)
@@ -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 );
 
index 4755d723b8adb21aad227eb8bb01b0bc7df4bf95..8da3ed9d474e56a7d84848081ce714090e7b0049 100644 (file)
@@ -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 (file)
index 0000000..5e12b96
--- /dev/null
@@ -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 (file)
index 0000000..ef7b28a
--- /dev/null
@@ -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 (file)
index 0000000..4832109
--- /dev/null
@@ -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"