From 1ac152938cfe40e98b7b3c8cf403abb113266cfa Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 3 Mar 2016 16:46:04 +0100 Subject: Move semicolon into TSRMLS_CACHE_EXTERN/DEFINE Also re bug #71575. --- ext/intl/php_intl.c | 2 +- ext/intl/php_intl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 12bd9fdc74..fd35e57120 100644 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -892,7 +892,7 @@ zend_module_entry intl_module_entry = { #ifdef COMPILE_DL_INTL #ifdef ZTS -ZEND_TSRMLS_CACHE_DEFINE(); +ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE( intl ) #endif diff --git a/ext/intl/php_intl.h b/ext/intl/php_intl.h index b8d1600edb..e672e54087 100644 --- a/ext/intl/php_intl.h +++ b/ext/intl/php_intl.h @@ -56,7 +56,7 @@ ZEND_BEGIN_MODULE_GLOBALS(intl) ZEND_END_MODULE_GLOBALS(intl) #if defined(ZTS) && defined(COMPILE_DL_INTL) -ZEND_TSRMLS_CACHE_EXTERN(); +ZEND_TSRMLS_CACHE_EXTERN() #endif ZEND_EXTERN_MODULE_GLOBALS(intl) -- cgit v1.2.1 From 4a8c51c7d7f28653203ed6e5d6c89e5e829c57a3 Mon Sep 17 00:00:00 2001 From: Francois Laupretre Date: Sat, 12 Sep 2015 01:27:05 +0200 Subject: Add negative offset support to grapheme_strpos/stripos/extract() --- ext/intl/grapheme/grapheme_string.c | 33 +++++++++++++++++++-------------- ext/intl/tests/grapheme.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index f42ba7e69e..9fb4e35405 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -134,20 +134,21 @@ PHP_FUNCTION(grapheme_strpos) RETURN_FALSE; } + if (offset >= 0) { + /* quick check to see if the string might be there + * I realize that 'offset' is 'grapheme count offset' but will work in spite of that + */ + found = php_memnstr(haystack + offset, needle, needle_len, haystack + haystack_len); - /* quick check to see if the string might be there - * I realize that 'offset' is 'grapheme count offset' but will work in spite of that - */ - found = php_memnstr(haystack + offset, needle, needle_len, haystack + haystack_len); - - /* if it isn't there the we are done */ - if (!found) { - RETURN_FALSE; - } + /* if it isn't there the we are done */ + if (!found) { + RETURN_FALSE; + } - /* if it is there, and if the haystack is ascii, we are all done */ - if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { - RETURN_LONG(found - haystack); + /* if it is there, and if the haystack is ascii, we are all done */ + if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { + RETURN_LONG(found - haystack); + } } /* do utf16 part of the strpos */ @@ -195,7 +196,6 @@ PHP_FUNCTION(grapheme_stripos) RETURN_FALSE; } - is_ascii = ( grapheme_ascii_check((unsigned char*)haystack, haystack_len) >= 0 ); if ( is_ascii ) { @@ -204,7 +204,8 @@ PHP_FUNCTION(grapheme_stripos) haystack_dup = estrndup(haystack, haystack_len); php_strtolower(haystack_dup, haystack_len); - found = php_memnstr(haystack_dup + offset, needle_dup, needle_len, haystack_dup + haystack_len); + found = php_memnstr(haystack_dup + offset + ((offset < 0) ? haystack_len : 0) + , needle_dup, needle_len, haystack_dup + haystack_len); efree(haystack_dup); efree(needle_dup); @@ -802,6 +803,10 @@ PHP_FUNCTION(grapheme_extract) RETURN_FALSE; } + if (lstart < 0) { + lstart += str_len; + } + if ( NULL != next ) { if ( !Z_ISREF_P(next) ) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, diff --git a/ext/intl/tests/grapheme.phpt b/ext/intl/tests/grapheme.phpt index def9110d0d..251b1d142f 100644 --- a/ext/intl/tests/grapheme.phpt +++ b/ext/intl/tests/grapheme.phpt @@ -68,9 +68,13 @@ function ut_main() array( "abc", "a", 0 ), array( "abc", "a", 0, 0 ), array( "abc", "a", 1, "false" ), + array( "abc", "a", -1, "false" ), array( "ababc", "a", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -1, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -5, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ), + array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, -4, 3 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "op", 5 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "opq", 5 ), @@ -91,6 +95,7 @@ function ut_main() array( "ababc", "ab", 1, 2 ), array( "ababc", "abc", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", -8, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "bc" . $char_a_ring_nfd, 2, 3 ), ); @@ -120,10 +125,12 @@ function ut_main() $tests = array( array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Oo", "o", -6, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 5 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "O", "false" ), array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ), + array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, -1, 4 ), array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, 2 ), array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 1 ), array( "Abc", $char_a_ring_nfd, "false" ), @@ -153,6 +160,7 @@ function ut_main() array( "aBc", "abC", 0, 0 ), array( "abc", "aBc", 1, "false" ), array( "ABabc", "AB", 1, 2 ), + array( "ABabc", "AB", -4, 2 ), array( "abaBc", "aBc", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_A_ring_nfd . "bC", "O" . $char_a_ring_nfd . "bC", 2, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bC" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "Bc" . $char_a_ring_nfd, 2, 3 ), @@ -559,6 +567,7 @@ function ut_main() array( "abc", 1, 0, 1, "a" ), array( "abc", 1, 1, 2, "b" ), array( "abc", 1, 2, 3, "c" ), + array( "abc", 1, -2, 2, "b" ), array( "abc", 0, 2, 2, "" ), array( "http://news.bbc.co.uk/2/hi/middle_east/7831588.stm", 48, 48 , 50 , "tm" ), @@ -569,8 +578,11 @@ function ut_main() array( $char_a_ring_nfd . "bc", 2, 0, 4, $char_a_ring_nfd . "b" ), array( $char_a_ring_nfd . "bc", 1, 0, 3, $char_a_ring_nfd . "" ), array( $char_a_ring_nfd . "bcde", 2, 3, 5, "bc" ), + array( $char_a_ring_nfd . "bcde", 2, -4, 5, "bc" ), array( $char_a_ring_nfd . "bcde", 2, 4, 6, "cd" ), + array( $char_a_ring_nfd . "bcde", 2, -7, 4, $char_a_ring_nfd . "b" ), array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, 5, 11, "de" . $char_a_ring_nfd . "f" ), + array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, -6, 11, "de" . $char_a_ring_nfd . "f" ), array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ), array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, $char_a_ring_nfd . $char_o_diaeresis_nfd ), @@ -794,9 +806,13 @@ find "b" in "abc" - grapheme_strpos = 1 == 1 find "a" in "abc" - grapheme_strpos = 0 == 0 find "a" in "abc" - grapheme_strpos from 0 = 0 == 0 find "a" in "abc" - grapheme_strpos from 1 = false == false +find "a" in "abc" - grapheme_strpos from -1 = false == false find "a" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from 2 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -1 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -5 = 6 == 6 find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from 2 = 3 == 3 +find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from -4 = 3 == 3 find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5 find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5 find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false @@ -816,15 +832,18 @@ find "abc" in "abc" - grapheme_strpos from 1 = false == false find "ab" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "abc" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from 2 = 6 == 6 +find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from -8 = 6 == 6 find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strpos from 2 = 3 == 3 function grapheme_stripos($haystack, $needle, $offset = 0) {} find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_stripos from 2 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88Oo" - grapheme_stripos from -6 = 6 == 6 find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_stripos from 2 = 3 == 3 find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stripos = 5 == 5 find "O" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos = 4 == 4 +find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos from -1 = 4 == 4 find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stripos = 2 == 2 find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stripos = 1 == 1 find "a%CC%8A" in "Abc" - grapheme_stripos = false == false @@ -853,6 +872,7 @@ find "ab" in "ABc" - grapheme_stripos from 0 = 0 == 0 find "abC" in "aBc" - grapheme_stripos from 0 = 0 == 0 find "aBc" in "abc" - grapheme_stripos from 1 = false == false find "AB" in "ABabc" - grapheme_stripos from 1 = 2 == 2 +find "AB" in "ABabc" - grapheme_stripos from -4 = 2 == 2 find "aBc" in "abaBc" - grapheme_stripos from 1 = 2 == 2 find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_stripos from 2 = 6 == 6 find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_stripos from 2 = 3 == 3 @@ -1094,6 +1114,7 @@ extract from "abc" "0" graphemes - grapheme_extract starting at byte position 0 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 with $next = b == b $next=2 == 2 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 with $next = c == c $next=3 == 3 +extract from "abc" "1" graphemes - grapheme_extract starting at byte position -2 with $next = b == b $next=2 == 2 extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 with $next = == $next=2 == 2 extract from "http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Fmiddle_east%2F7831588.stm" "48" graphemes - grapheme_extract starting at byte position 48 with $next = tm == tm $next=50 == 50 extract from "a%CC%8Abc" "3" graphemes - grapheme_extract = a%CC%8Abc == a%CC%8Abc @@ -1103,8 +1124,11 @@ extract from "a%CC%8Abc" "3" graphemes - grapheme_extract starting at byte posit extract from "a%CC%8Abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4 extract from "a%CC%8Abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8A == a%CC%8A $next=3 == 3 extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 3 with $next = bc == bc $next=5 == 5 +extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -4 with $next = bc == bc $next=5 == 5 extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 4 with $next = cd == cd $next=6 == 6 +extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -7 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4 extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position 5 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11 +extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position -6 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11 extract from "a%CC%8Ao%CC%88o%CC%88" "3" graphemes - grapheme_extract = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88 extract from "a%CC%8Ao%CC%88o%CC%88" "2" graphemes - grapheme_extract = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88 extract from "a%CC%8Ao%CC%88c" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A -- cgit v1.2.1 From 64dae1ea76c2c226fc375bf93858f9b2f5dae27f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 13 Mar 2016 18:01:51 +0100 Subject: Statically bind static method call arguments If we know what method will be called, use ct-bound send opcodes. The intl test is changed because a runtime error changed to a compile-time error. --- ext/intl/tests/timezone_getCanonicalID_error.phpt | 6 ------ 1 file changed, 6 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/tests/timezone_getCanonicalID_error.phpt b/ext/intl/tests/timezone_getCanonicalID_error.phpt index e268e216a8..b29ca67701 100644 --- a/ext/intl/tests/timezone_getCanonicalID_error.phpt +++ b/ext/intl/tests/timezone_getCanonicalID_error.phpt @@ -11,7 +11,6 @@ ini_set("intl.error_level", E_WARNING); var_dump(IntlTimeZone::getCanonicalID()); var_dump(IntlTimeZone::getCanonicalID(array())); var_dump(IntlTimeZone::getCanonicalID("foo\x81")); -var_dump(IntlTimeZone::getCanonicalID('foobar', null)); --EXPECTF-- @@ -28,8 +27,3 @@ bool(false) Warning: IntlTimeZone::getCanonicalID(): intltz_get_canonical_id: could not convert time zone id to UTF-16 in %s on line %d bool(false) - -Fatal error: Uncaught Error: Cannot pass parameter 2 by reference in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d -- cgit v1.2.1 From 49d31fa01d1cfe4515bd6f1cdb256374701a4489 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 8 Apr 2016 08:59:06 +0200 Subject: Fixed bug #71516 IntlDateFormatter losts locale if pattern is set via constructor --- ext/intl/dateformat/dateformat_create.cpp | 17 ++++++++++------- ext/intl/tests/dateformat_bug71516.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 ext/intl/tests/dateformat_bug71516.phpt (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 1999b6a8c1..e90ad74466 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -36,6 +36,7 @@ extern "C" { #include "dateformat_helpers.h" #include "zend_exceptions.h" + /* {{{ */ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) { @@ -117,14 +118,16 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) } } + DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type, + (UDateFormatStyle)date_type, locale_str, NULL, 0, svalue, + slength, &INTL_DATA_ERROR_CODE(dfo)); + if (pattern_str && pattern_str_len > 0) { - DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE, - locale_str, NULL, 0, svalue, slength, - &INTL_DATA_ERROR_CODE(dfo)); - } else { - DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type, - (UDateFormatStyle)date_type, locale_str, NULL, 0, svalue, - slength, &INTL_DATA_ERROR_CODE(dfo)); + udat_applyPattern(DATE_FORMAT_OBJECT(dfo), true, svalue, slength); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: error applying pattern", 0); + goto error; + } } if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { diff --git a/ext/intl/tests/dateformat_bug71516.phpt b/ext/intl/tests/dateformat_bug71516.phpt new file mode 100644 index 0000000000..88ba9bf840 --- /dev/null +++ b/ext/intl/tests/dateformat_bug71516.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #71516 IntlDateFormatter losts locale if pattern is set via constructor +--SKIPIF-- + +--FILE-- +setPattern("d MMM"); + +echo "Formatter without pattern: " . $goodFormatter->getLocale() . PHP_EOL; +echo "Formatter with pattern: " . $badFormatter->getLocale() . PHP_EOL; +echo "Formatter with pattern set later: " . $badFormatter2->getLocale() . PHP_EOL; + +?> +==DONE== +--EXPECT-- +Formatter without pattern: ru +Formatter with pattern: ru +Formatter with pattern set later: ru +==DONE== -- cgit v1.2.1 From 93f8eaf3b8c9400f230dc904d52508882f83ee5f Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 8 Apr 2016 09:55:57 +0200 Subject: Fixed bug #70455 Missing constant: IntlChar::NO_NUMERIC_VALUE --- ext/intl/uchar/tests/bug70455.phpt | 13 +++++++++++++ ext/intl/uchar/uchar.c | 1 + 2 files changed, 14 insertions(+) create mode 100644 ext/intl/uchar/tests/bug70455.phpt (limited to 'ext/intl') diff --git a/ext/intl/uchar/tests/bug70455.phpt b/ext/intl/uchar/tests/bug70455.phpt new file mode 100644 index 0000000000..00ee8984a0 --- /dev/null +++ b/ext/intl/uchar/tests/bug70455.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #70455 Missing constant: IntlChar::NO_NUMERIC_VALUE +--SKIPIF-- + +--FILE-- + +--EXPECT-- +float(-123456789) +bool(true) diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c index 8fb09f9f82..755a6c9acb 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.c @@ -737,6 +737,7 @@ int php_uchar_minit(INIT_FUNC_ARGS) { IC_CONSTL("CODEPOINT_MAX", UCHAR_MAX_VALUE) IC_CONSTL("FOLD_CASE_DEFAULT", U_FOLD_CASE_DEFAULT) IC_CONSTL("FOLD_CASE_EXCLUDE_SPECIAL_I", U_FOLD_CASE_EXCLUDE_SPECIAL_I) + zend_declare_class_constant_double(ce, "NO_NUMERIC_VALUE", sizeof("NO_NUMERIC_VALUE")-1, U_NO_NUMERIC_VALUE); /* All enums used by the uchar APIs. There are a LOT of them, * so they're separated out into include files, -- cgit v1.2.1 From ff2af8951986c1192b82b0fe492528d3b758e11c Mon Sep 17 00:00:00 2001 From: Daniel Persson Date: Mon, 7 Sep 2015 22:14:36 +0200 Subject: Added tests for bug 70451 and 70452 --- ext/intl/tests/bug70451.phpt | 12 ++++++++++++ ext/intl/tests/bug70452.phpt | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 ext/intl/tests/bug70451.phpt create mode 100644 ext/intl/tests/bug70452.phpt (limited to 'ext/intl') diff --git a/ext/intl/tests/bug70451.phpt b/ext/intl/tests/bug70451.phpt new file mode 100644 index 0000000000..75392c8dad --- /dev/null +++ b/ext/intl/tests/bug70451.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #70451 IntlChar::charFromName() not consistent with C library or HHVM +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(9843) +NULL diff --git a/ext/intl/tests/bug70452.phpt b/ext/intl/tests/bug70452.phpt new file mode 100644 index 0000000000..f544c03ce3 --- /dev/null +++ b/ext/intl/tests/bug70452.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #70452 string IntlChar::charName() can sometimes return bool(false) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(22) "LATIN CAPITAL LETTER A" +string(22) "LATIN CAPITAL LETTER A" +string(0) "" +NULL \ No newline at end of file -- cgit v1.2.1 From e3b160bf864fa3b6b2bf938e62f18768032980ab Mon Sep 17 00:00:00 2001 From: Daniel Persson Date: Mon, 7 Sep 2015 22:15:23 +0200 Subject: Added function to check error and return null if error is set. --- ext/intl/intl_data.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/intl_data.h b/ext/intl/intl_data.h index 12e0a9924e..74b7092fbb 100644 --- a/ext/intl/intl_data.h +++ b/ext/intl/intl_data.h @@ -45,7 +45,7 @@ typedef struct _intl_data { obj = Z_##oclass##_P( object ); \ intl_error_reset( INTL_DATA_ERROR_P(obj) ); \ -/* Check status by error code, if error - exit */ +/* Check status by error code, if error return false */ #define INTL_CHECK_STATUS(err, msg) \ intl_error_set_code( NULL, (err) ); \ if( U_FAILURE((err)) ) \ @@ -54,6 +54,16 @@ typedef struct _intl_data { RETURN_FALSE; \ } +/* Check status by error code, if error return null */ +#define INTL_CHECK_STATUS_OR_NULL(err, msg) \ + intl_error_set_code( NULL, (err) ); \ + if( U_FAILURE((err)) ) \ + { \ + intl_error_set_custom_msg( NULL, msg, 0 ); \ + RETURN_NULL(); \ + } + + /* Check status in object, if error return false */ #define INTL_METHOD_CHECK_STATUS(obj, msg) \ intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ -- cgit v1.2.1 From 0030fa322fd987da3a0b210837fd5d41e7559368 Mon Sep 17 00:00:00 2001 From: Daniel Persson Date: Mon, 7 Sep 2015 22:15:52 +0200 Subject: Changed to check for error with the new function that returns null if error is set --- ext/intl/uchar/uchar.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c index 755a6c9acb..266c62821b 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.c @@ -241,7 +241,7 @@ IC_METHOD(charName) { if ((zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &zcp, &nameChoice) == FAILURE) || (convert_cp(&cp, zcp) == FAILURE)) { - return; + RETURN_NULL(); } buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error); @@ -250,7 +250,7 @@ IC_METHOD(charName) { buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error); if (U_FAILURE(error)) { zend_string_free(buffer); - INTL_CHECK_STATUS(error, "Failure getting character name"); + INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name"); } RETURN_NEW_STR(buffer); } @@ -269,11 +269,11 @@ IC_METHOD(charFromName) { UErrorCode error = U_ZERO_ERROR; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &name, &name_len, &nameChoice) == FAILURE) { - return; + RETURN_NULL(); } ret = u_charFromName((UCharNameChoice)nameChoice, name, &error); - INTL_CHECK_STATUS(error, NULL); + INTL_CHECK_STATUS_OR_NULL(error, NULL); RETURN_LONG(ret); } /* }}} */ -- cgit v1.2.1 From f7600e17cb8eb6c5dad8709ac1f4c76f0f28f207 Mon Sep 17 00:00:00 2001 From: Daniel Persson Date: Mon, 7 Sep 2015 22:23:26 +0200 Subject: Added missing newline. --- ext/intl/tests/bug70452.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/tests/bug70452.phpt b/ext/intl/tests/bug70452.phpt index f544c03ce3..ee1cd7053a 100644 --- a/ext/intl/tests/bug70452.phpt +++ b/ext/intl/tests/bug70452.phpt @@ -18,4 +18,4 @@ var_dump(IntlChar::charName("A", 12345)); string(22) "LATIN CAPITAL LETTER A" string(22) "LATIN CAPITAL LETTER A" string(0) "" -NULL \ No newline at end of file +NULL -- cgit v1.2.1 From 1541a55a4f9207c346a805c2b8d090f16d07f841 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 8 Apr 2016 12:29:40 +0200 Subject: Fixed bug #68893 Stackoverflow in datefmt_create --- ext/intl/dateformat/dateformat_create.cpp | 28 ++++++++++++++++++++++------ ext/intl/tests/dateformat_bug68893.phpt | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 ext/intl/tests/dateformat_bug68893.phpt (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index e90ad74466..8705d4bc0b 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -36,6 +36,13 @@ extern "C" { #include "dateformat_helpers.h" #include "zend_exceptions.h" +#define INTL_UDATE_FMT_OK(i) \ + (UDAT_FULL == (i) || UDAT_LONG == (i) || \ + UDAT_MEDIUM == (i) || UDAT_SHORT == (i) || \ + UDAT_RELATIVE == (i) || UDAT_FULL_RELATIVE == (i) || \ + UDAT_LONG_RELATIVE == (i) || UDAT_MEDIUM_RELATIVE == (i) || \ + UDAT_SHORT_RELATIVE == (i) || UDAT_NONE == (i) || \ + UDAT_PATTERN == (i)) /* {{{ */ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) @@ -72,12 +79,6 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) return FAILURE; } - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); - if (locale_len == 0) { - locale_str = intl_locale_get_default(); - } - locale = Locale::createFromName(locale_str); - DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; if (DATE_FORMAT_OBJECT(dfo) != NULL) { @@ -86,6 +87,21 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) return FAILURE; } + if (!INTL_UDATE_FMT_OK(date_type)) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid date format style", 0); + return FAILURE; + } + if (!INTL_UDATE_FMT_OK(time_type)) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid time format style", 0); + return FAILURE; + } + + INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); + if (locale_len == 0) { + locale_str = intl_locale_get_default(); + } + locale = Locale::createFromName(locale_str); + /* process calendar */ if (datefmt_process_calendar_arg(calendar_zv, locale, "datefmt_create", INTL_DATA_ERROR_P(dfo), calendar, calendar_type, diff --git a/ext/intl/tests/dateformat_bug68893.phpt b/ext/intl/tests/dateformat_bug68893.phpt new file mode 100644 index 0000000000..b3faf54342 --- /dev/null +++ b/ext/intl/tests/dateformat_bug68893.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #68893 Stackoverflow in datefmt_create +--SKIPIF-- + +--FILE-- + +--EXPECT-- +NULL +string(67) "datefmt_create: invalid date format style: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(67) "datefmt_create: invalid time format style: U_ILLEGAL_ARGUMENT_ERROR" -- cgit v1.2.1 From 45d9efaac3ff4f861f86093d801aefd1b4fde9e5 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 8 Apr 2016 12:48:26 +0200 Subject: fix compat for ICU < 50 --- ext/intl/dateformat/dateformat_create.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 8705d4bc0b..0e73fda01c 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -36,6 +36,10 @@ extern "C" { #include "dateformat_helpers.h" #include "zend_exceptions.h" +#if U_ICU_VERSION_MINOR_NUM < 50 +#define UDAT_PATTERN 0 +#endif + #define INTL_UDATE_FMT_OK(i) \ (UDAT_FULL == (i) || UDAT_LONG == (i) || \ UDAT_MEDIUM == (i) || UDAT_SHORT == (i) || \ -- cgit v1.2.1 From 73815573e0e483cc0f81145d53ae6308508bbd27 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 8 Apr 2016 14:17:57 +0200 Subject: fix indent --- ext/intl/dateformat/dateformat_create.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 0e73fda01c..51ec063270 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -52,36 +52,35 @@ extern "C" { static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) { zval *object; - const char *locale_str; - size_t locale_len = 0; + size_t locale_len = 0; Locale locale; - zend_long date_type = 0; - zend_long time_type = 0; + zend_long date_type = 0; + zend_long time_type = 0; zval *calendar_zv = NULL; - Calendar *calendar = NULL; + Calendar *calendar = NULL; zend_long calendar_type; bool calendar_owned; zval *timezone_zv = NULL; - TimeZone *timezone = NULL; + TimeZone *timezone = NULL; bool explicit_tz; - char* pattern_str = NULL; - size_t pattern_str_len = 0; - UChar* svalue = NULL; /* UTF-16 pattern_str */ - int32_t slength = 0; + char* pattern_str = NULL; + size_t pattern_str_len = 0; + UChar* svalue = NULL; /* UTF-16 pattern_str */ + int32_t slength = 0; IntlDateFormatter_object* dfo; int zpp_flags = is_constructor ? ZEND_PARSE_PARAMS_THROW : 0; intl_error_reset(NULL); object = return_value; /* Parse parameters. */ - if (zend_parse_parameters_ex(zpp_flags, ZEND_NUM_ARGS(), "sll|zzs", + if (zend_parse_parameters_ex(zpp_flags, ZEND_NUM_ARGS(), "sll|zzs", &locale_str, &locale_len, &date_type, &time_type, &timezone_zv, &calendar_zv, &pattern_str, &pattern_str_len) == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: " "unable to parse input parameters", 0); return FAILURE; - } + } DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; @@ -150,7 +149,7 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) } } - if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { DateFormat *df = (DateFormat*)DATE_FORMAT_OBJECT(dfo); if (calendar_owned) { df->adoptCalendar(calendar); @@ -162,7 +161,7 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) if (timezone != NULL) { df->adoptTimeZone(timezone); } - } else { + } else { intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " "formatter creation failed", 0); goto error; -- cgit v1.2.1 From ef17343b3cb9195437d760ec21dcdf6004a85b67 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 9 Apr 2016 18:22:57 +0200 Subject: Fixed bug #66289 Locale::lookup incorrectly returns en or en_US if locale is empty --- ext/intl/locale/locale_methods.c | 6 +++++- ext/intl/tests/locale_bug66289.phpt | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/locale_bug66289.phpt (limited to 'ext/intl') diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index c47f283201..3471ba4053 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1548,7 +1548,11 @@ PHP_FUNCTION(locale_lookup) } if(loc_range_len == 0) { - loc_range = intl_locale_get_default(); + if(fallback_loc_str) { + loc_range = ZSTR_VAL(fallback_loc_str); + } else { + loc_range = intl_locale_get_default(); + } } hash_arr = Z_ARRVAL_P(arr); diff --git a/ext/intl/tests/locale_bug66289.phpt b/ext/intl/tests/locale_bug66289.phpt new file mode 100644 index 0000000000..6afd821b5a --- /dev/null +++ b/ext/intl/tests/locale_bug66289.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #66289 Locale::lookup incorrectly returns en or en_US if locale is empty +--SKIPIF-- + +--FILE-- + +==DONE== +--EXPECT-- +string(5) "fr_fr" +string(5) "en_us" +string(5) "fr_fr" +string(5) "de_de" +==DONE== -- cgit v1.2.1 From 58ea2ad4897b74b0a11d3da8a64c557ff18b0021 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 9 Apr 2016 19:10:53 +0200 Subject: Fixed bug #65480 No declaration for msgformat_fix_quotes() in msgformat.c or msgformat_attr.c --- ext/intl/msgformat/msgformat.c | 1 + ext/intl/msgformat/msgformat_attr.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/msgformat/msgformat.c b/ext/intl/msgformat/msgformat.c index e0919ec42b..d3f8416c03 100644 --- a/ext/intl/msgformat/msgformat.c +++ b/ext/intl/msgformat/msgformat.c @@ -23,6 +23,7 @@ #include "php_intl.h" #include "msgformat_class.h" +#include "msgformat_data.h" #include "intl_convert.h" /* {{{ */ diff --git a/ext/intl/msgformat/msgformat_attr.c b/ext/intl/msgformat/msgformat_attr.c index a20a7e411d..78eb727c61 100644 --- a/ext/intl/msgformat/msgformat_attr.c +++ b/ext/intl/msgformat/msgformat_attr.c @@ -21,11 +21,11 @@ #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_attr.h" +#include "msgformat_data.h" #include "intl_convert.h" #include - /* {{{ proto string MessageFormatter::getPattern( ) * Get formatter pattern. }}} */ /* {{{ proto string msgfmt_get_pattern( MessageFormatter $mf ) -- cgit v1.2.1 From 028485ae696625e713f795582d4628796d9df996 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 11 Apr 2016 08:03:15 +0100 Subject: fix calendar segfault --- ext/intl/calendar/calendar_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index 6b6feef8d9..72cd7e1dd0 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -177,7 +177,7 @@ static HashTable *Calendar_get_debug_info(zval *object, int *is_temp) HashTable *debug_info_tz; timezone_object_construct(&cal->getTimeZone(), &ztz , 0); - debug_info = Z_OBJ_HANDLER(ztz, get_debug_info)(&ztz, &is_tmp); + debug_info_tz = Z_OBJ_HANDLER(ztz, get_debug_info)(&ztz, &is_tmp); assert(is_tmp == 1); array_init(&ztz_debug); -- cgit v1.2.1 From f62943edc8f9803b900cc44585beff18cf1361eb Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 11 Apr 2016 14:54:58 +0200 Subject: fix version macro to check --- ext/intl/dateformat/dateformat_create.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 51ec063270..00a5cc593c 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -36,7 +36,7 @@ extern "C" { #include "dateformat_helpers.h" #include "zend_exceptions.h" -#if U_ICU_VERSION_MINOR_NUM < 50 +#if U_ICU_VERSION_MAJOR_NUM < 50 #define UDAT_PATTERN 0 #endif -- cgit v1.2.1 From 28b6f66a77d660412766b6da88d01377cbdd04a1 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 11 Apr 2016 15:00:58 +0200 Subject: Fixed bug #70484 selectordinal doesn't work with named parameters --- ext/intl/msgformat/msgformat_helpers.cpp | 4 ++ ext/intl/tests/msgfmt_bug70484.phpt | 97 ++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 ext/intl/tests/msgfmt_bug70484.phpt (limited to 'ext/intl') diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index ed63105fa7..ce7899edd9 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -264,6 +264,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { type = Formattable::kString; +#if U_ICU_VERSION_MAJOR_NUM >= 50 + } else if (argType == UMSGPAT_ARG_TYPE_SELECTORDINAL) { + type = Formattable::kDouble; +#endif } else { type = Formattable::kString; } diff --git a/ext/intl/tests/msgfmt_bug70484.phpt b/ext/intl/tests/msgfmt_bug70484.phpt new file mode 100644 index 0000000000..9d0bdc4ee8 --- /dev/null +++ b/ext/intl/tests/msgfmt_bug70484.phpt @@ -0,0 +1,97 @@ +--TEST-- +Bug #70484 selectordinal doesn't work with named parameters +--SKIPIF-- +format(array("n" => $i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; + + echo "$lc numeric key\n"; + $m = new MessageFormatter($lc, "{0, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}"); + foreach ($data as $i) { + var_dump($m->format(array($i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; +} + +?> +==DONE== +--EXPECT-- +de string key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +de numeric key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +fr string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +fr numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +en string key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +en numeric key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +ru string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +ru numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +==DONE== -- cgit v1.2.1 From a9568d54858912cd741df183f8eee2493361de7f Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Wed, 16 Mar 2016 00:32:36 +0000 Subject: Update IntlTimeZone methods for ICU 52 Adds: string IntlTimeZone::getWindowsID(string id) string IntlTimeZone::getIDForWindowsID(string winID[, string region]) And matching procedural functions --- ext/intl/tests/timezone_IDforWindowsID_basic.phpt | 44 +++++++++++++ ext/intl/tests/timezone_windowsID_basic.phpt | 41 ++++++++++++ ext/intl/timezone/timezone_class.cpp | 15 +++++ ext/intl/timezone/timezone_methods.cpp | 78 +++++++++++++++++++++++ ext/intl/timezone/timezone_methods.h | 5 ++ 5 files changed, 183 insertions(+) create mode 100644 ext/intl/tests/timezone_IDforWindowsID_basic.phpt create mode 100644 ext/intl/tests/timezone_windowsID_basic.phpt (limited to 'ext/intl') diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt new file mode 100644 index 0000000000..2fab10fdd7 --- /dev/null +++ b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt @@ -0,0 +1,44 @@ +--TEST-- +IntlTimeZone::getIDForWindowsID basic test +--SKIPIF-- + array(NULL), + 'India Standard Time' => array(NULL), + 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), + 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), +); + +foreach ($tzs as $tz => $regions) { + echo "** $tz\n"; + foreach ($regions as $region) { + var_dump(IntlTimeZone::getIDForWindowsID($tz, $region)); + if (intl_get_error_code() != U_ZERO_ERROR) { + echo "Error: ", intl_get_error_message(), "\n"; + } + } +} + +--EXPECT-- +** Gnomeregan +bool(false) +Error: intltz_get_windows_id: Unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR +** India Standard Time +string(13) "Asia/Calcutta" +** Pacific Standard Time +string(19) "America/Los_Angeles" +string(17) "America/Vancouver" +string(15) "America/Tijuana" +string(19) "America/Los_Angeles" +string(7) "PST8PDT" +** Romance Standard Time +string(12) "Europe/Paris" +string(15) "Europe/Brussels" +string(17) "Europe/Copenhagen" +string(13) "Europe/Madrid" +string(12) "Europe/Paris" diff --git a/ext/intl/tests/timezone_windowsID_basic.phpt b/ext/intl/tests/timezone_windowsID_basic.phpt new file mode 100644 index 0000000000..8a9fcfe95f --- /dev/null +++ b/ext/intl/tests/timezone_windowsID_basic.phpt @@ -0,0 +1,41 @@ +--TEST-- +IntlTimeZone::getWindowsID basic test +--SKIPIF-- += 52 +ZEND_BEGIN_ARG_INFO_EX(ainfo_tz_getWindowsID, 0, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, timezone) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_tz_getIDForWindowsID, 0, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, timezone) + ZEND_ARG_INFO(0, region) +ZEND_END_ARG_INFO() +#endif + /* }}} */ /* {{{ TimeZone_class_functions @@ -475,6 +486,10 @@ static zend_function_entry TimeZone_class_functions[] = { PHP_ME_MAPPING(toDateTimeZone, intltz_to_date_time_zone, ainfo_tz_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorCode, intltz_get_error_code, ainfo_tz_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorMessage, intltz_get_error_message, ainfo_tz_void, ZEND_ACC_PUBLIC) +#if U_ICU_VERSION_MAJOR_NUM >= 52 + PHP_ME_MAPPING(getWindowsID, intltz_get_windows_id, ainfo_tz_getWindowsID, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME_MAPPING(getIDForWindowsID, intltz_get_id_for_windows_id, ainfo_tz_getIDForWindowsID, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) +#endif PHP_FE_END }; /* }}} */ diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index a35174d3da..20c0e02480 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -647,3 +647,81 @@ U_CFUNC PHP_FUNCTION(intltz_get_error_message) message = intl_error_get_message(TIMEZONE_ERROR_P(to)); RETURN_STR(message); } + +#if U_ICU_VERSION_MAJOR_NUM >= 52 +/* {{{ proto string IntlTimeZone::getWindowsID(string $timezone) + proto string intltz_get_windows_id(string $timezone) +Translate a system timezone (e.g. "America/Los_Angeles" into a +Windows Timezone (e.g. "Pacific Standard Time") + */ +U_CFUNC PHP_FUNCTION(intltz_get_windows_id) +{ + zend_string *id, *winID; + UnicodeString uID, uWinID; + UErrorCode error; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &id) == FAILURE) { + return; + } + + error = U_ZERO_ERROR; + if (intl_stringFromChar(uID, id->val, id->len, &error) == FAILURE) { + intl_error_set(NULL, error, + "intltz_get_windows_id: could not convert time zone id to UTF-16", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + TimeZone::getWindowsID(uID, uWinID, error); + INTL_CHECK_STATUS(error, "intltz_get_windows_id: Unable to get timezone from windows ID"); + if (uWinID.length() == 0) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intltz_get_windows_id: Unknown system timezone", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + winID = intl_convert_utf16_to_utf8(uWinID.getBuffer(), uWinID.length(), &error); + INTL_CHECK_STATUS(error, "intltz_get_windows_id: could not convert time zone id to UTF-8"); + RETURN_STR(winID); +} +/* }}} */ + +/* {{{ proto string IntlTimeZone::getIDForWindowsID(string $timezone[, string $region = NULL]) + proto string intltz_get_id_for_windows_id(string $timezone[, string $region = NULL]) +Translate a windows timezone (e.g. "Pacific Time Zone" into a +System Timezone (e.g. "America/Los_Angeles") + */ +U_CFUNC PHP_FUNCTION(intltz_get_id_for_windows_id) +{ + zend_string *winID, *region = NULL, *id; + UnicodeString uWinID, uID; + UErrorCode error; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &winID, ®ion) == FAILURE) { + return; + } + + error = U_ZERO_ERROR; + if (intl_stringFromChar(uWinID, winID->val, winID->len, &error) == FAILURE) { + intl_error_set(NULL, error, + "intltz_get_id_for_windows_id: could not convert time zone id to UTF-16", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + TimeZone::getIDForWindowsID(uWinID, region ? region->val : NULL, uID, error); + INTL_CHECK_STATUS(error, "intltz_get_id_for_windows_id: Unable to get windows ID for timezone"); + if (uID.length() == 0) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intltz_get_windows_id: Unknown windows timezone", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + id = intl_convert_utf16_to_utf8(uID.getBuffer(), uID.length(), &error); + INTL_CHECK_STATUS(error, "intltz_get_id_for_windows_id: could not convert time zone id to UTF-8"); + RETURN_STR(id); +} +/* }}} */ +#endif diff --git a/ext/intl/timezone/timezone_methods.h b/ext/intl/timezone/timezone_methods.h index 29d72913fd..6e6fa3f472 100644 --- a/ext/intl/timezone/timezone_methods.h +++ b/ext/intl/timezone/timezone_methods.h @@ -65,4 +65,9 @@ PHP_FUNCTION(intltz_get_error_code); PHP_FUNCTION(intltz_get_error_message); +#if U_ICU_VERSION_MAJOR_NUM >= 52 +PHP_FUNCTION(intltz_get_windows_id); +PHP_FUNCTION(intltz_get_id_for_windows_id); +#endif + #endif /* #ifndef TIMEZONE_METHODS_H */ -- cgit v1.2.1 From dc3ab58c14cb58e33b8a0c5c7a181846eb8b4ff3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 20 Apr 2016 19:43:15 +0200 Subject: Fix intl tests for ICU < 52 --- ext/intl/tests/timezone_IDforWindowsID_basic.phpt | 2 ++ ext/intl/tests/timezone_windowsID_basic.phpt | 2 ++ 2 files changed, 4 insertions(+) (limited to 'ext/intl') diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt index 2fab10fdd7..4127d8e31c 100644 --- a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt +++ b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt @@ -4,6 +4,8 @@ IntlTimeZone::getIDForWindowsID basic test = 52'); --FILE-- = 52'); --FILE-- Date: Sun, 24 Apr 2016 12:49:01 -0700 Subject: Fix bug #72061 - Out-of-bounds reads in zif_grapheme_stripos with negative offset --- ext/intl/grapheme/grapheme_string.c | 12 +++++++----- ext/intl/tests/bug72061.phpt | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 ext/intl/tests/bug72061.phpt (limited to 'ext/intl') diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 8a094e015e..3ba9b51524 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -112,7 +112,7 @@ PHP_FUNCTION(grapheme_strpos) int haystack_len, needle_len; unsigned char *found; long loffset = 0; - int32_t offset = 0; + int32_t offset = 0, noffset = 0; int ret_pos; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) { @@ -132,6 +132,7 @@ PHP_FUNCTION(grapheme_strpos) /* we checked that it will fit: */ offset = (int32_t) loffset; + noffset = offset >= 0 ? offset : haystack_len + offset; /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ @@ -146,7 +147,7 @@ PHP_FUNCTION(grapheme_strpos) /* quick check to see if the string might be there * I realize that 'offset' is 'grapheme count offset' but will work in spite of that */ - found = (unsigned char *)php_memnstr((char *)haystack + offset, (char *)needle, needle_len, (char *)haystack + haystack_len); + found = (unsigned char *)php_memnstr((char *)haystack + noffset, (char *)needle, needle_len, (char *)haystack + haystack_len); /* if it isn't there the we are done */ if (!found) { @@ -214,12 +215,13 @@ PHP_FUNCTION(grapheme_stripos) is_ascii = ( grapheme_ascii_check(haystack, haystack_len) >= 0 ); if ( is_ascii ) { + int32_t noffset = offset >= 0 ? offset : haystack_len + offset; needle_dup = (unsigned char *)estrndup((char *)needle, needle_len); php_strtolower((char *)needle_dup, needle_len); haystack_dup = (unsigned char *)estrndup((char *)haystack, haystack_len); php_strtolower((char *)haystack_dup, haystack_len); - found = (unsigned char*) php_memnstr((char *)haystack_dup + offset, (char *)needle_dup, needle_len, (char *)haystack_dup + haystack_len); + found = (unsigned char*) php_memnstr((char *)haystack_dup + noffset, (char *)needle_dup, needle_len, (char *)haystack_dup + haystack_len); efree(haystack_dup); efree(needle_dup); @@ -537,7 +539,7 @@ PHP_FUNCTION(grapheme_substr) efree(ustr); } ubrk_close(bi); - RETURN_EMPTY_STRING(); + RETURN_EMPTY_STRING(); } /* find the end point of the string to return */ @@ -576,7 +578,7 @@ PHP_FUNCTION(grapheme_substr) sub_str_end_pos = ustr_len; } } - + if(sub_str_start_pos > sub_str_end_pos) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: length is beyond start", 1 TSRMLS_CC ); diff --git a/ext/intl/tests/bug72061.phpt b/ext/intl/tests/bug72061.phpt new file mode 100644 index 0000000000..782c32c11c --- /dev/null +++ b/ext/intl/tests/bug72061.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #72061: Out-of-bounds reads in zif_grapheme_stripos with negative offset +--SKIPIF-- + +--FILE-- + +DONE +--EXPECT-- +int(65336) +int(65336) +DONE \ No newline at end of file -- cgit v1.2.1 From 6499162ff0d8aa6e862d3e3cdd2288b87636b8a1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 28 Apr 2016 04:13:34 +0300 Subject: - get rid of EG(scope). zend_get_executed_scope() should be used instead. - ichanged zval_update_constant_ex(). Use IS_TYPE_IMMUTABLE flag on shared constants and AST, instead of "inline_change" parameter. --- ext/intl/transliterator/transliterator_class.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'ext/intl') diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c index ce8c7e6291..5c80b25af8 100644 --- a/ext/intl/transliterator/transliterator_class.c +++ b/ext/intl/transliterator/transliterator_class.c @@ -269,9 +269,15 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type, static void Transliterator_write_property( zval *object, zval *member, zval *value, void **cache_slot ) { + zend_class_entry *scope; TRANSLITERATOR_PROPERTY_HANDLER_PROLOG; - if( ( EG( scope ) != Transliterator_ce_ptr ) && + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + if( ( scope != Transliterator_ce_ptr ) && ( zend_binary_strcmp( "id", sizeof( "id" ) - 1, Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) ) { -- cgit v1.2.1 From 97eff7eb57fc2320c267a949cffd622c38712484 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 22 May 2016 17:49:02 -0700 Subject: Fix bug #72241: get_icu_value_internal out-of-bounds read --- ext/intl/locale/locale_methods.c | 235 ++++++++++++++++++++------------------- ext/intl/tests/bug72241.phpt | 14 +++ 2 files changed, 132 insertions(+), 117 deletions(-) create mode 100644 ext/intl/tests/bug72241.phpt (limited to 'ext/intl') diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index c8159bcd5a..31f60b39a4 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -65,26 +65,26 @@ ZEND_EXTERN_MODULE_GLOBALS( intl ) */ static const char * const LOC_GRANDFATHERED[] = { "art-lojban", "i-klingon", "i-lux", "i-navajo", "no-bok", "no-nyn", - "cel-gaulish", "en-GB-oed", "i-ami", - "i-bnn", "i-default", "i-enochian", - "i-mingo", "i-pwn", "i-tao", + "cel-gaulish", "en-GB-oed", "i-ami", + "i-bnn", "i-default", "i-enochian", + "i-mingo", "i-pwn", "i-tao", "i-tay", "i-tsu", "sgn-BE-fr", "sgn-BE-nl", "sgn-CH-de", "zh-cmn", "zh-cmn-Hans", "zh-cmn-Hant", "zh-gan" , "zh-guoyu", "zh-hakka", "zh-min", - "zh-min-nan", "zh-wuu", "zh-xiang", + "zh-min-nan", "zh-wuu", "zh-xiang", "zh-yue", NULL }; /* Based on IANA registry at the time of writing this code * This array lists the preferred values for the grandfathered tags if applicable -* This is in sync with the array LOC_GRANDFATHERED +* This is in sync with the array LOC_GRANDFATHERED * e.g. the offsets of the grandfathered tags match the offset of the preferred value */ static const int LOC_PREFERRED_GRANDFATHERED_LEN = 6; static const char * const LOC_PREFERRED_GRANDFATHERED[] = { "jbo", "tlh", "lb", - "nv", "nb", "nn", + "nv", "nb", "nn", NULL }; @@ -122,7 +122,7 @@ static int16_t findOffset(const char* const* list, const char* key) /*}}}*/ static char* getPreferredTag(const char* gf_tag) -{ +{ char* result = NULL; int grOffset = 0; @@ -141,15 +141,15 @@ static char* getPreferredTag(const char* gf_tag) } /* {{{ -* returns the position of next token for lookup +* returns the position of next token for lookup * or -1 if no token -* strtokr equivalent search for token in reverse direction +* strtokr equivalent search for token in reverse direction */ static int getStrrtokenPos(char* str, int savedPos) { int result =-1; int i; - + for(i=savedPos-1; i>=0; i--) { if(isIDSeparator(*(str+i)) ){ /* delimiter found; check for singleton */ @@ -171,7 +171,7 @@ static int getStrrtokenPos(char* str, int savedPos) /* }}} */ /* {{{ -* returns the position of a singleton if present +* returns the position of a singleton if present * returns -1 if no singleton * strtok equivalent search for singleton */ @@ -180,7 +180,7 @@ static int getSingletonPos(const char* str) int result =-1; int i=0; int len = 0; - + if( str && ((len=strlen(str))>0) ){ for( i=0; ic, (s)->len, 0) -/* {{{ proto static string Locale::composeLocale($array) -* Creates a locale by combining the parts of locale-ID passed +/* {{{ proto static string Locale::composeLocale($array) +* Creates a locale by combining the parts of locale-ID passed * }}} */ -/* {{{ proto static string compose_locale($array) -* Creates a locale by combining the parts of locale-ID passed +/* {{{ proto static string compose_locale($array) +* Creates a locale by combining the parts of locale-ID passed * }}} */ PHP_FUNCTION(locale_compose) { @@ -920,7 +921,7 @@ PHP_FUNCTION(locale_compose) RETURN_FALSE; /* Check for grandfathered first */ - result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG); + result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG); if( result == SUCCESS){ RETURN_SMART_STR(loc_name); } @@ -929,7 +930,7 @@ PHP_FUNCTION(locale_compose) } /* Not grandfathered */ - result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG); + result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG); if( result == LOC_NOT_FOUND ){ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "locale_compose: parameter array does not contain 'language' tag.", 0 TSRMLS_CC ); @@ -947,11 +948,11 @@ PHP_FUNCTION(locale_compose) } /* Script */ - result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); + result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); if( !handleAppendResult( result, loc_name TSRMLS_CC)){ RETURN_FALSE; } - + /* Region */ result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG); if( !handleAppendResult( result, loc_name TSRMLS_CC)){ @@ -959,7 +960,7 @@ PHP_FUNCTION(locale_compose) } /* Variant */ - result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC); + result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC); if( !handleAppendResult( result, loc_name TSRMLS_CC)){ RETURN_FALSE; } @@ -985,16 +986,16 @@ static char* get_private_subtags(const char* loc_name) { char* result =NULL; int singletonPos = 0; - int len =0; + int len =0; const char* mod_loc_name =NULL; if( loc_name && (len = strlen(loc_name)>0 ) ){ - mod_loc_name = loc_name ; + mod_loc_name = loc_name ; len = strlen(mod_loc_name); while( (singletonPos = getSingletonPos(mod_loc_name))!= -1){ - if( singletonPos!=-1){ - if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){ + if( singletonPos!=-1){ + if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){ /* private subtag start found */ if( singletonPos + 2 == len){ /* loc_name ends with '-x-' ; return NULL */ @@ -1019,7 +1020,7 @@ static char* get_private_subtags(const char* loc_name) } /* end of while */ } - + return result; } /* }}} */ @@ -1044,20 +1045,20 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name } else { key_value = get_icu_value_internal( loc_name , key_name , &result,1 ); } - if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || + if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){ if( result > 0 && key_value){ /* Tokenize on the "_" or "-" */ - token = php_strtok_r( key_value , DELIMITER ,&last_ptr); + token = php_strtok_r( key_value , DELIMITER ,&last_ptr); if( cur_key_name ){ efree( cur_key_name); } cur_key_name = (char*)ecalloc( 25, 25); - sprintf( cur_key_name , "%s%d", key_name , cnt++); + sprintf( cur_key_name , "%s%d", key_name , cnt++); add_assoc_string( hash_arr, cur_key_name , token ,TRUE ); /* tokenize on the "_" or "-" and stop at singleton if any */ while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){ - sprintf( cur_key_name , "%s%d", key_name , cnt++); + sprintf( cur_key_name , "%s%d", key_name , cnt++); add_assoc_string( hash_arr, cur_key_name , token , TRUE ); } /* @@ -1077,16 +1078,16 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name } /*if( key_name != LOC_PRIVATE_TAG && key_value){*/ if( key_value){ - efree(key_value); + efree(key_value); } return cur_result; } /* }}} */ -/* {{{ proto static array Locale::parseLocale($locale) +/* {{{ proto static array Locale::parseLocale($locale) * parses a locale-id into an array the different parts of it }}} */ -/* {{{ proto static array parse_locale($locale) +/* {{{ proto static array parse_locale($locale) * parses a locale-id into an array the different parts of it */ PHP_FUNCTION(locale_parse) @@ -1144,7 +1145,7 @@ PHP_FUNCTION(locale_get_all_variants) char* saved_ptr = NULL; intl_error_reset( NULL TSRMLS_CC ); - + if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &loc_name, &loc_name_len ) == FAILURE) { @@ -1162,15 +1163,15 @@ PHP_FUNCTION(locale_get_all_variants) array_init( return_value ); /* If the locale is grandfathered, stop, no variants */ - if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){ + if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){ /* ("Grandfathered Tag. No variants."); */ } - else { + else { /* Call ICU variant */ variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0); if( result > 0 && variant){ /* Tokenize on the "_" or "-" */ - token = php_strtok_r( variant , DELIMITER , &saved_ptr); + token = php_strtok_r( variant , DELIMITER , &saved_ptr); add_next_index_stringl( return_value, token , strlen(token) ,TRUE ); /* tokenize on the "_" or "-" and stop at singleton if any */ while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){ @@ -1181,7 +1182,7 @@ PHP_FUNCTION(locale_get_all_variants) efree( variant ); } } - + } /* }}} */ @@ -1220,11 +1221,11 @@ static int strToMatch(const char* str ,char *retstr) /* }}} */ /* {{{ proto static boolean Locale::filterMatches(string $langtag, string $locale[, bool $canonicalize]) -* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm +* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ /* }}} */ /* {{{ proto boolean locale_filter_matches(string $langtag, string $locale[, bool $canonicalize]) -* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm +* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ PHP_FUNCTION(locale_filter_matches) { @@ -1243,13 +1244,13 @@ PHP_FUNCTION(locale_filter_matches) char* cur_lang_tag = NULL; char* cur_loc_range = NULL; - zend_bool boolCanonical = 0; + zend_bool boolCanonical = 0; UErrorCode status = U_ZERO_ERROR; intl_error_reset( NULL TSRMLS_CC ); - + if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", - &lang_tag, &lang_tag_len , &loc_range , &loc_range_len , + &lang_tag, &lang_tag_len , &loc_range , &loc_range_len , &boolCanonical) == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, @@ -1270,7 +1271,7 @@ PHP_FUNCTION(locale_filter_matches) /* canonicalize loc_range */ can_loc_range=get_icu_value_internal( loc_range , LOC_CANONICALIZE_TAG , &result , 0); if( result ==0) { - intl_error_set( NULL, status, + intl_error_set( NULL, status, "locale_filter_matches : unable to canonicalize loc_range" , 0 TSRMLS_CC ); RETURN_FALSE; } @@ -1278,7 +1279,7 @@ PHP_FUNCTION(locale_filter_matches) /* canonicalize lang_tag */ can_lang_tag = get_icu_value_internal( lang_tag , LOC_CANONICALIZE_TAG , &result , 0); if( result ==0) { - intl_error_set( NULL, status, + intl_error_set( NULL, status, "locale_filter_matches : unable to canonicalize lang_tag" , 0 TSRMLS_CC ); RETURN_FALSE; } @@ -1306,11 +1307,11 @@ PHP_FUNCTION(locale_filter_matches) /* check if prefix */ token = strstr( cur_lang_tag , cur_loc_range ); - + if( token && (token==cur_lang_tag) ){ /* check if the char. after match is SEPARATOR */ chrcheck = token + (strlen(cur_loc_range)); - if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ + if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ if( cur_lang_tag){ efree( cur_lang_tag ); } @@ -1346,7 +1347,7 @@ PHP_FUNCTION(locale_filter_matches) else{ /* Convert to lower case for case-insensitive comparison */ cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1); - + result = strToMatch( lang_tag , cur_lang_tag); if( result == 0) { efree( cur_lang_tag ); @@ -1362,11 +1363,11 @@ PHP_FUNCTION(locale_filter_matches) /* check if prefix */ token = strstr( cur_lang_tag , cur_loc_range ); - + if( token && (token==cur_lang_tag) ){ /* check if the char. after match is SEPARATOR */ chrcheck = token + (strlen(cur_loc_range)); - if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ + if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ if( cur_lang_tag){ efree( cur_lang_tag ); } @@ -1393,7 +1394,7 @@ PHP_FUNCTION(locale_filter_matches) static void array_cleanup( char* arr[] , int arr_size) { int i=0; - for( i=0; i< arr_size; i++ ){ + for( i=0; i< arr_size; i++ ){ if( arr[i*2] ){ efree( arr[i*2]); } @@ -1403,7 +1404,7 @@ static void array_cleanup( char* arr[] , int arr_size) #define LOOKUP_CLEAN_RETURN(value) array_cleanup(cur_arr, cur_arr_len); return (value) /* {{{ -* returns the lookup result to lookup_loc_range_src_php +* returns the lookup result to lookup_loc_range_src_php * internal function */ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int canonicalize TSRMLS_DC) @@ -1427,7 +1428,7 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca for(zend_hash_internal_pointer_reset(hash_arr); zend_hash_has_more_elements(hash_arr) == SUCCESS; zend_hash_move_forward(hash_arr)) { - + if (zend_hash_get_current_data(hash_arr, (void**)&ele_value) == FAILURE) { /* Should never actually fail since the key is known to exist.*/ continue; @@ -1436,7 +1437,7 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca /* element value is not a string */ intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: locale array element is not a string", 0 TSRMLS_CC); LOOKUP_CLEAN_RETURN(NULL); - } + } cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_PP(ele_value), Z_STRLEN_PP(ele_value)); result = strToMatch(Z_STRVAL_PP(ele_value), cur_arr[cur_arr_len*2]); if(result == 0) { @@ -1444,12 +1445,12 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca LOOKUP_CLEAN_RETURN(NULL); } cur_arr[cur_arr_len*2+1] = Z_STRVAL_PP(ele_value); - cur_arr_len++ ; + cur_arr_len++ ; } /* end of for */ /* Canonicalize array elements */ if(canonicalize) { - for(i=0; i 0) { - for(i=0; i< cur_arr_len; i++){ - if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { + for(i=0; i< cur_arr_len; i++){ + if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { /* Match found */ return_value = estrdup(canonicalize?cur_arr[i*2]:cur_arr[i*2+1]); efree(cur_loc_range); @@ -1515,14 +1516,14 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca } /* }}} */ -/* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]]) +/* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]]) * Searchs the items in $langtag for the best match to the language -* range +* range */ /* }}} */ /* {{{ proto string locale_lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]]) * Searchs the items in $langtag for the best match to the language -* range +* range */ PHP_FUNCTION(locale_lookup) { @@ -1552,8 +1553,8 @@ PHP_FUNCTION(locale_lookup) if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) { RETURN_EMPTY_STRING(); - } - + } + result = lookup_loc_range(loc_range, hash_arr, boolCanonical TSRMLS_CC); if(result == NULL || result[0] == '\0') { if( fallback_loc ) { @@ -1590,10 +1591,10 @@ PHP_FUNCTION(locale_accept_from_http) "locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC ); RETURN_FALSE; } - + available = ures_openAvailableLocales(NULL, &status); INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list"); - len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN, + len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN, &outResult, http_accept, available, &status); uenum_close(available); INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale"); diff --git a/ext/intl/tests/bug72241.phpt b/ext/intl/tests/bug72241.phpt new file mode 100644 index 0000000000..397e1e7834 --- /dev/null +++ b/ext/intl/tests/bug72241.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #72241: get_icu_value_internal out-of-bounds read +--SKIPIF-- + +--FILE-- + Date: Mon, 11 Apr 2016 15:00:58 +0200 Subject: Fixed bug #70484 selectordinal doesn't work with named parameters --- ext/intl/msgformat/msgformat_helpers.cpp | 4 ++ ext/intl/tests/msgfmt_bug70484.phpt | 97 ++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 ext/intl/tests/msgfmt_bug70484.phpt (limited to 'ext/intl') diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index f75fd91dce..cc38cf0dc9 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -264,6 +264,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { type = Formattable::kString; +#if U_ICU_VERSION_MAJOR_NUM >= 50 + } else if (argType == UMSGPAT_ARG_TYPE_SELECTORDINAL) { + type = Formattable::kDouble; +#endif } else { type = Formattable::kString; } diff --git a/ext/intl/tests/msgfmt_bug70484.phpt b/ext/intl/tests/msgfmt_bug70484.phpt new file mode 100644 index 0000000000..9d0bdc4ee8 --- /dev/null +++ b/ext/intl/tests/msgfmt_bug70484.phpt @@ -0,0 +1,97 @@ +--TEST-- +Bug #70484 selectordinal doesn't work with named parameters +--SKIPIF-- +format(array("n" => $i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; + + echo "$lc numeric key\n"; + $m = new MessageFormatter($lc, "{0, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}"); + foreach ($data as $i) { + var_dump($m->format(array($i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; +} + +?> +==DONE== +--EXPECT-- +de string key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +de numeric key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +fr string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +fr numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +en string key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +en numeric key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +ru string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +ru numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +==DONE== -- cgit v1.2.1 From 527ddacd2084d5112ba849d55ed8532d133cbd97 Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 2 Jun 2016 22:27:48 +0200 Subject: Fixed bug #69374 IntlDateFormatter formatObject returns wrong utf8 value Relying on invariant strings is a mistake. Not only UTF-8, but also many charsets are not single byte. Actual date formats can be mixed with arbitrary strings, and this can bring erroneous results in the out. Thus, instead it is more convenient to say, that a format string can consist either on UTF-8 or on pure ASCII as its subset. This is what is currently being done in other classes like Formatter, etc. as well. --- ext/intl/dateformat/dateformat_format_object.cpp | 10 +++++----- ext/intl/tests/bug69374.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 ext/intl/tests/bug69374.phpt (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index 3be76332a8..accb27e63d 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -188,11 +188,11 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } if (pattern) { - df = new SimpleDateFormat( - UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format), - UnicodeString::kInvariant), - Locale::createFromName(locale_str), - status); + StringPiece sp(Z_STRVAL_P(format)); + df = new SimpleDateFormat( + UnicodeString::fromUTF8(sp), + Locale::createFromName(locale_str), + status); if (U_FAILURE(status)) { intl_error_set(NULL, status, diff --git a/ext/intl/tests/bug69374.phpt b/ext/intl/tests/bug69374.phpt new file mode 100644 index 0000000000..4d9fffab7a --- /dev/null +++ b/ext/intl/tests/bug69374.phpt @@ -0,0 +1,24 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong utf8 value when $format param is utf8 string pattern. +--SKIPIF-- + += 51.1.2'); ?> +--FILE-- +setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, $pattern1, 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, $pattern2, 'ko_KR'), "\n"; +?> +==DONE== + +--EXPECTF-- +tháng 04, 2015 +2015년 4월 +==DONE== + + -- cgit v1.2.1 From 0112b64a346ef1c4b8b21b1cef712a587eee9aa7 Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 2 Jun 2016 22:37:44 +0200 Subject: Fixed bug #69398 IntlDateFormatter formatObject returns wrong value when time style is NONE --- ext/intl/dateformat/dateformat_format_object.cpp | 4 +++- ext/intl/tests/bug69398.phpt | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/bug69398.phpt (limited to 'ext/intl') diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index accb27e63d..e96ebe8243 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -146,7 +146,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } //there's no support for relative time in ICU yet - timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); + if (timeStyle != DateFormat::NONE) { + timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); + } zend_class_entry *instance_ce = Z_OBJCE_P(object); if (instanceof_function(instance_ce, Calendar_ce_ptr)) { diff --git a/ext/intl/tests/bug69398.phpt b/ext/intl/tests/bug69398.phpt new file mode 100644 index 0000000000..ea7dbd5098 --- /dev/null +++ b/ext/intl/tests/bug69398.phpt @@ -0,0 +1,22 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. +--SKIPIF-- + += 51.1.2'); ?> +--FILE-- +setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'ko_KR'), "\n"; +?> +==DONE== + +--EXPECTF-- +04/04/2015 +15. 4. 4. +==DONE== + + -- cgit v1.2.1 From 2a0ed8a2eb091e309bf2cd1560a39ea66b094e07 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 6 Jun 2016 21:06:06 +0200 Subject: Add test for bug #53735 --- ext/intl/tests/bug53735.phpt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 ext/intl/tests/bug53735.phpt (limited to 'ext/intl') diff --git a/ext/intl/tests/bug53735.phpt b/ext/intl/tests/bug53735.phpt new file mode 100644 index 0000000000..5fc14e978c --- /dev/null +++ b/ext/intl/tests/bug53735.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #53735 NumberFormatter returns NaN when converting float point +--SKIPIF-- + += 51.2'); ?> +--FILE-- +format(23.25)); + +$f = new NumberFormatter('hu_HU', NumberFormatter::PERCENT, '#,##0%'); +var_dump($f->format(0.26)); + +?> +==DONE== +--EXPECTF-- +string(%d) "5,50 kr%A" +string(%d) "5,50 kr%A" +string(%d) "5,00 kr%A" +string(5) "23,25" +string(3) "26%" +==DONE== -- cgit v1.2.1 From 958f18c1a12a3f1ac6fd6e119ad57ff9c6701b05 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 17 Jun 2016 15:59:41 +0800 Subject: =?UTF-8?q?Fixed=20"implicit=20declaration=20of=20function=20?= =?UTF-8?q?=E2=80=98msgformat=5Ffix=5Fquotes=E2=80=99"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ext/intl/msgformat/msgformat_class.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ext/intl') diff --git a/ext/intl/msgformat/msgformat_class.h b/ext/intl/msgformat/msgformat_class.h index a90042e58f..6823595f6d 100644 --- a/ext/intl/msgformat/msgformat_class.h +++ b/ext/intl/msgformat/msgformat_class.h @@ -24,6 +24,11 @@ #include "../intl_common.h" #include "../intl_error.h" #include "../intl_data.h" + +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM < 48 +# define MSG_FORMAT_QUOTE_APOS 1 +#endif + #include "msgformat_data.h" typedef struct { @@ -54,8 +59,4 @@ extern zend_class_entry *MessageFormatter_ce_ptr; #define MSG_FORMAT_OBJECT(mfo) (mfo)->mf_data.umsgf -#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM < 48 -# define MSG_FORMAT_QUOTE_APOS 1 -#endif - #endif // #ifndef MSG_FORMAT_CLASS_H -- cgit v1.2.1