]> granicus.if.org Git - php/commitdiff
Fixed bug #60785
authorGustavo André dos Santos Lopes <cataphract@php.net>
Thu, 24 May 2012 08:44:44 +0000 (10:44 +0200)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Thu, 24 May 2012 09:06:21 +0000 (11:06 +0200)
Memory leak in IntlDateFormatter constructor.

udat_setCalendar() clones the calendar before it adopts it,
so we were leaking the original calendar.

Also we now validate the calendar type.

ext/intl/dateformat/dateformat.c
ext/intl/tests/dateformat_calendars.phpt [new file with mode: 0644]

index 6c0c52257b9703776f3cfb228cd20247868159cd..b399a39fcb51156db0a86a3bd12becb34db4d979 100755 (executable)
@@ -99,6 +99,15 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
     }
 
        INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
+       
+       if (calendar != UCAL_TRADITIONAL && calendar != UCAL_GREGORIAN) {
+               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: "
+                               "invalid value for calendar type; it must be one of "
+                               "IntlDateFormatter::TRADITIONAL (locale's default calendar) "
+                               "or IntlDateFormatter::GREGORIAN", 0 TSRMLS_CC);
+               goto error;
+       }
+       
        DATE_FORMAT_METHOD_FETCH_OBJECT;
        
        if (DATE_FORMAT_OBJECT(dfo) != NULL) {
@@ -142,13 +151,13 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
                DATE_FORMAT_OBJECT(dfo) = udat_open(time_type, date_type, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo));
        }
 
-    /* Set the calendar if passed */
-    if(!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
-               if (calendar) {
+    if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
+               if (calendar != UCAL_TRADITIONAL) {
                        ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale,
                                        calendar, &INTL_DATA_ERROR_CODE(dfo));
                        if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
-                               udat_setCalendar( DATE_FORMAT_OBJECT(dfo), ucal_obj );
+                               udat_setCalendar(DATE_FORMAT_OBJECT(dfo), ucal_obj);
+                               ucal_close(ucal_obj);
                        } else {
                                intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create"
                                                ": error opening calendar", 0 TSRMLS_CC);
diff --git a/ext/intl/tests/dateformat_calendars.phpt b/ext/intl/tests/dateformat_calendars.phpt
new file mode 100644 (file)
index 0000000..27f380c
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+IntlDateFormatter, calendars and time zone
+--INI--
+date.timezone=Atlantic/Azores
+--SKIPIF--
+<?php
+if (!extension_loaded('intl'))
+       die('skip intl extension not enabled');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+
+$fmt1 = new IntlDateFormatter('en_US',
+       IntlDateFormatter::FULL,
+       IntlDateFormatter::FULL,
+       'GMT+05:12',
+       IntlDateFormatter::TRADITIONAL);
+$fmt2 = new IntlDateFormatter('en_US',
+       IntlDateFormatter::FULL,
+       IntlDateFormatter::FULL,
+       'GMT+05:12',
+       IntlDateFormatter::GREGORIAN);
+$fmt3 = new IntlDateFormatter('en_US@calendar=hebrew',
+       IntlDateFormatter::FULL,
+       IntlDateFormatter::FULL,
+       'GMT+05:12',
+       IntlDateFormatter::TRADITIONAL);
+var_dump($fmt1->format(strtotime('2012-01-01 00:00:00 +0000')));
+var_dump($fmt2->format(strtotime('2012-01-01 00:00:00 +0000')));
+var_dump($fmt3->format(strtotime('2012-01-01 00:00:00 +0000')));
+
+new IntlDateFormatter('en_US@calendar=hebrew',
+       IntlDateFormatter::FULL,
+       IntlDateFormatter::FULL,
+       'GMT+05:12',
+       -1);
+?>
+==DONE==
+--EXPECTF--
+string(44) "Sunday, January 1, 2012 5:12:00 AM GMT+05:12"
+string(44) "Sunday, January 1, 2012 5:12:00 AM GMT+05:12"
+string(42) "Sunday, Tevet 6, 5772 5:12:00 AM GMT+05:12"
+
+Warning: IntlDateFormatter::__construct(): datefmt_create: invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN in %s on line %d
+==DONE==