Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ PHP NEWS
- FPM:
. Fixed failed debug assertion when php_admin_value setting fails. (ilutov)

- Filter:
. Fixed bug GH-16993 (filter_var_array with FILTER_VALIDATE_INT|FILTER_NULL_ON_FAILURE
should emit warning for invalid filter usage). (alexandre-daubois)

- Intl:
. Added grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(),
grapheme_strripos(), grapheme_strstr(), grapheme_stristr() and
grapheme_levenshtein() functions add $locale parameter (Yuya Hamada).
. Fixed bug GH-11952 (Fix locale strings canonicalization for IntlDateFormatter
and NumberFormatter). (alexandre-daubois)

- Opcache:
. Fixed bug GH-19486 (Incorrect opline after deoptimization). (Arnaud)
. Fixed bug GH-19601 (Wrong JIT stack setup on aarch64/clang). (Arnaud)
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,10 @@ PHP 8.5 UPGRADE NOTES
TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage()
have dropped the false from the return type union. Returning false
was actually never possible.
. grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(),
grapheme_strripos(), grapheme_strstr(), grapheme_stristr() and
grapheme_levenshtein() functions add $locale parameter.
RFC: https://wiki.php.net/rfc/grapheme_add_locale_for_case_insensitive

- LDAP:
. ldap_get_option() now accepts a NULL connection, as ldap_set_option(),
Expand Down
8 changes: 8 additions & 0 deletions ext/filter/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,14 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op
zval nval;
ZVAL_DEREF(tmp);
ZVAL_DUP(&nval, tmp);

if (Z_TYPE_P(arg_elm) != IS_ARRAY) {
zend_long filter_id = zval_get_long(arg_elm);
if (!PHP_FILTER_ID_EXISTS(filter_id)) {
php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, filter_id);
}
}

php_filter_call(&nval, -1,
Z_TYPE_P(arg_elm) == IS_ARRAY ? Z_ARRVAL_P(arg_elm) : NULL,
Z_TYPE_P(arg_elm) == IS_ARRAY ? 0 : zval_get_long(arg_elm),
Expand Down
6 changes: 6 additions & 0 deletions ext/filter/tests/039.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,18 @@ array(1) {
["var_name"]=>
NULL
}

Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d
array(1) {
["var_name"]=>
string(0) ""
}
-- (5)

Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d
filter_var_array(): Argument #2 ($options) cannot contain empty keys

Warning: filter_var_array(): Unknown filter with ID 0 in %s on line %d
filter_var_array(): Argument #2 ($options) cannot contain empty keys

Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d
Expand Down
24 changes: 24 additions & 0 deletions ext/filter/tests/gh16993.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
GH-16993: filter_var_array should emit warning for unknown filters
--EXTENSIONS--
filter
--FILE--
<?php
$data = ['test' => '42'];

$result = filter_var_array($data, ['test' => FILTER_VALIDATE_INT|FILTER_NULL_ON_FAILURE]);
var_dump($result);

$result = filter_var_array($data, ['test' => ['filter' => FILTER_VALIDATE_INT, 'flags' => FILTER_NULL_ON_FAILURE]]);
var_dump($result);
?>
--EXPECTF--
Warning: filter_var_array(): Unknown filter with ID 134217985 in %s on line %d
array(1) {
["test"]=>
string(2) "42"
}
array(1) {
["test"]=>
int(42)
}
16 changes: 13 additions & 3 deletions ext/intl/dateformat/dateformat_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
extern "C" {
#include <unicode/ustring.h>
#include <unicode/udat.h>
#include <unicode/uloc.h>

#include "php_intl.h"
#include "dateformat_create.h"
Expand Down Expand Up @@ -106,7 +107,12 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
if (locale_len == 0) {
locale_str = (char *) intl_locale_get_default();
}
locale = Locale::createFromName(locale_str);

char* canonicalized_locale = canonicalize_locale_string(locale_str);
const char* final_locale = canonicalized_locale ? canonicalized_locale : locale_str;
const char* stored_locale = canonicalized_locale ? canonicalized_locale : locale_str;

locale = Locale::createFromName(final_locale);
/* get*Name accessors being set does not preclude being bogus */
if (locale.isBogus() || ((locale_len == 1 && locale_str[0] != 'C') || (locale_len > 1 && strlen(locale.getISO3Language()) == 0))) {
zend_argument_value_error(1, "\"%s\" is invalid", locale_str);
Expand Down Expand Up @@ -144,7 +150,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
}

DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type,
(UDateFormatStyle)date_type, locale_str, NULL, 0, svalue,
(UDateFormatStyle)date_type, final_locale, NULL, 0, svalue,
slength, &INTL_DATA_ERROR_CODE(dfo));

if (pattern_str && pattern_str_len > 0) {
Expand Down Expand Up @@ -176,9 +182,13 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
dfo->date_type = date_type;
dfo->time_type = time_type;
dfo->calendar = calendar_type;
dfo->requested_locale = estrdup(locale_str);
/* Store the canonicalized locale, or fallback to original if canonicalization failed */
dfo->requested_locale = estrdup(stored_locale);

error:
if (canonicalized_locale) {
efree(canonicalized_locale);
}
if (svalue) {
efree(svalue);
}
Expand Down
12 changes: 9 additions & 3 deletions ext/intl/formatter/formatter_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,18 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
return FAILURE;
}

/* Create an ICU number formatter. */
FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo));
char* canonicalized_locale = canonicalize_locale_string(locale);
const char* final_locale = canonicalized_locale ? canonicalized_locale : locale;

if(spattern) {
FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, final_locale, NULL, &INTL_DATA_ERROR_CODE(nfo));

if (spattern) {
efree(spattern);
}

if (canonicalized_locale) {
efree(canonicalized_locale);
}

INTL_CTOR_CHECK_STATUS(nfo, "number formatter creation failed");
return SUCCESS;
Expand Down
58 changes: 34 additions & 24 deletions ext/intl/grapheme/grapheme_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,20 @@ PHP_FUNCTION(grapheme_strlen)
/* {{{ Find position of first occurrence of a string within another */
PHP_FUNCTION(grapheme_strpos)
{
char *haystack, *needle;
size_t haystack_len, needle_len;
char *haystack, *needle, *locale = "";
size_t haystack_len, needle_len, locale_len = 0;
const char *found;
zend_long loffset = 0;
int32_t offset = 0;
size_t noffset = 0;
zend_long ret_pos;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(haystack, haystack_len)
Z_PARAM_STRING(needle, needle_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(loffset)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if ( OUTSIDE_STRING(loffset, haystack_len) ) {
Expand Down Expand Up @@ -121,7 +122,7 @@ PHP_FUNCTION(grapheme_strpos)
}

/* do utf16 part of the strpos */
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 0 /* fIgnoreCase */, 0 /* last */ );
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* fIgnoreCase */ 0, /* last */ 0, locale);

if ( ret_pos >= 0 ) {
RETURN_LONG(ret_pos);
Expand All @@ -134,19 +135,20 @@ PHP_FUNCTION(grapheme_strpos)
/* {{{ Find position of first occurrence of a string within another, ignoring case differences */
PHP_FUNCTION(grapheme_stripos)
{
char *haystack, *needle;
size_t haystack_len, needle_len;
char *haystack, *needle, *locale = "";
size_t haystack_len, needle_len, locale_len = 0;
const char *found;
zend_long loffset = 0;
int32_t offset = 0;
zend_long ret_pos;
int is_ascii;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(haystack, haystack_len)
Z_PARAM_STRING(needle, needle_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(loffset)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if ( OUTSIDE_STRING(loffset, haystack_len) ) {
Expand Down Expand Up @@ -185,7 +187,7 @@ PHP_FUNCTION(grapheme_stripos)
}

/* do utf16 part of the strpos */
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 1 /* fIgnoreCase */, 0 /*last */ );
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* fIgnoreCase */ 1, /*last */ 0, locale);

if ( ret_pos >= 0 ) {
RETURN_LONG(ret_pos);
Expand All @@ -200,17 +202,19 @@ PHP_FUNCTION(grapheme_stripos)
PHP_FUNCTION(grapheme_strrpos)
{
char *haystack, *needle;
size_t haystack_len, needle_len;
char *locale = "";
size_t haystack_len, needle_len, locale_len = 0;
zend_long loffset = 0;
int32_t offset = 0;
zend_long ret_pos;
int is_ascii;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(haystack, haystack_len)
Z_PARAM_STRING(needle, needle_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(loffset)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if ( OUTSIDE_STRING(loffset, haystack_len) ) {
Expand Down Expand Up @@ -242,7 +246,7 @@ PHP_FUNCTION(grapheme_strrpos)
/* else we need to continue via utf16 */
}

ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 0 /* f_ignore_case */, 1/* last */);
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* f_ignore_case */ 0, /* last */ 1, locale);

if ( ret_pos >= 0 ) {
RETURN_LONG(ret_pos);
Expand All @@ -257,18 +261,19 @@ PHP_FUNCTION(grapheme_strrpos)
/* {{{ Find position of last occurrence of a string within another, ignoring case */
PHP_FUNCTION(grapheme_strripos)
{
char *haystack, *needle;
size_t haystack_len, needle_len;
char *haystack, *needle, *locale = "";
size_t haystack_len, needle_len, locale_len = 0;
zend_long loffset = 0;
int32_t offset = 0;
zend_long ret_pos;
int is_ascii;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(haystack, haystack_len)
Z_PARAM_STRING(needle, needle_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(loffset)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if ( OUTSIDE_STRING(loffset, haystack_len) ) {
Expand Down Expand Up @@ -309,7 +314,7 @@ PHP_FUNCTION(grapheme_strripos)
/* else we need to continue via utf16 */
}

ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 1 /* f_ignore_case */, 1 /*last */);
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* f_ignore_case */ 1, /*last */ 1, locale);

if ( ret_pos >= 0 ) {
RETURN_LONG(ret_pos);
Expand All @@ -324,10 +329,10 @@ PHP_FUNCTION(grapheme_strripos)
/* {{{ Returns part of a string */
PHP_FUNCTION(grapheme_substr)
{
char *str;
char *str, *locale = "";
zend_string *u8_sub_str;
UChar *ustr;
size_t str_len;
size_t str_len, locale_len = 0;
int32_t ustr_len;
zend_long lstart = 0, length = 0;
int32_t start = 0;
Expand All @@ -339,11 +344,12 @@ PHP_FUNCTION(grapheme_substr)
int32_t (*iter_func)(UBreakIterator *);
bool no_length = true;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(str, str_len)
Z_PARAM_LONG(lstart)
Z_PARAM_OPTIONAL
Z_PARAM_LONG_OR_NULL(length, no_length)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if (lstart < INT32_MIN || lstart > INT32_MAX) {
Expand Down Expand Up @@ -537,17 +543,18 @@ PHP_FUNCTION(grapheme_substr)
/* {{{ strstr_common_handler */
static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_case)
{
char *haystack, *needle;
char *haystack, *needle, *locale = "";
const char *found;
size_t haystack_len, needle_len;
size_t haystack_len, needle_len, locale_len = 0;
int32_t ret_pos, uchar_pos;
bool part = false;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STRING(haystack, haystack_len)
Z_PARAM_STRING(needle, needle_len)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(part)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if ( !f_ignore_case ) {
Expand All @@ -574,7 +581,7 @@ static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_cas
}

/* need to work in utf16 */
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case, 0 /*last */ );
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case, /* last */ 0, locale);

if ( ret_pos < 0 ) {
RETURN_FALSE;
Expand Down Expand Up @@ -919,14 +926,17 @@ PHP_FUNCTION(grapheme_levenshtein)
zend_long cost_ins = 1;
zend_long cost_rep = 1;
zend_long cost_del = 1;
char *locale = "";
size_t locale_len = 0;

ZEND_PARSE_PARAMETERS_START(2, 5)
ZEND_PARSE_PARAMETERS_START(2, 6)
Z_PARAM_STR(string1)
Z_PARAM_STR(string2)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(cost_ins)
Z_PARAM_LONG(cost_rep)
Z_PARAM_LONG(cost_del)
Z_PARAM_PATH(locale, locale_len)
ZEND_PARSE_PARAMETERS_END();

if (cost_ins <= 0 || cost_ins > UINT_MAX / 4) {
Expand Down Expand Up @@ -1043,7 +1053,7 @@ PHP_FUNCTION(grapheme_levenshtein)
RETVAL_FALSE;
goto out_bi2;
}
UCollator *collator = ucol_open("", &ustatus);
UCollator *collator = ucol_open(locale, &ustatus);
if (U_FAILURE(ustatus)) {
intl_error_set_code(NULL, ustatus);

Expand Down
4 changes: 2 additions & 2 deletions ext/intl/grapheme/grapheme_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char


/* {{{ grapheme_strpos_utf16 - strrpos using utf16*/
int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last)
int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last, const char* locale)
{
UChar *uhaystack = NULL, *uneedle = NULL;
int32_t uhaystack_len = 0, uneedle_len = 0, char_pos, ret_pos, offset_pos = 0;
Expand Down Expand Up @@ -136,7 +136,7 @@ int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle,
}

status = U_ZERO_ERROR;
src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, "", bi, &status);
src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, locale, bi, &status);
STRPOS_CHECK_STATUS(status, "Error creating search object");

if(f_ignore_case) {
Expand Down
4 changes: 2 additions & 2 deletions ext/intl/grapheme/grapheme_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ zend_long grapheme_ascii_check(const unsigned char *day, size_t len);
void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len);
zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset);

int32_t grapheme_strrpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int f_ignore_case);
int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int *puchar_pos, int f_ignore_case, int last);
int32_t grapheme_strrpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int f_ignore_case, const char *locale);
int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int *puchar_pos, int f_ignore_case, int last, const char *locale);

int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len );

Expand Down
Loading
Loading