summaryrefslogtreecommitdiff
path: root/ext/standard/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r--ext/standard/string.c411
1 files changed, 247 insertions, 164 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 0bb4d3a0a9..fc234aafad 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2018 The PHP Group |
+ | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,9 +23,7 @@
#include "php_rand.h"
#include "php_string.h"
#include "php_variables.h"
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
+#include <locale.h>
#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#endif
@@ -88,18 +86,8 @@ void register_string_constants(INIT_FUNC_ARGS)
REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
-#ifdef HAVE_LOCALECONV
/* If last members of struct lconv equal CHAR_MAX, no grouping is done */
-
-/* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */
-# ifndef HAVE_LIMITS_H
-# define CHAR_MAX 127
-# endif
-
REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT);
-#endif
-
-#ifdef HAVE_LOCALE_H
REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LC_TIME", LC_TIME, CONST_CS | CONST_PERSISTENT);
@@ -109,7 +97,6 @@ void register_string_constants(INIT_FUNC_ARGS)
# ifdef LC_MESSAGES
REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
# endif
-#endif
}
/* }}} */
@@ -182,15 +169,14 @@ static zend_string *php_hex2bin(const unsigned char *old, const size_t oldlen)
}
/* }}} */
-#ifdef HAVE_LOCALECONV
/* {{{ localeconv_r
* glibc's localeconv is not reentrant, so lets make it so ... sorta */
PHPAPI struct lconv *localeconv_r(struct lconv *out)
{
-# ifdef ZTS
+#ifdef ZTS
tsrm_mutex_lock( locale_mutex );
-# endif
+#endif
/* cur->locinfo is struct __crt_locale_info which implementation is
hidden in vc14. TODO revisit this and check if a workaround available
@@ -208,15 +194,15 @@ PHPAPI struct lconv *localeconv_r(struct lconv *out)
*out = *localeconv();
#endif
-# ifdef ZTS
+#ifdef ZTS
tsrm_mutex_unlock( locale_mutex );
-# endif
+#endif
return out;
}
/* }}} */
-# ifdef ZTS
+#ifdef ZTS
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(localeconv)
@@ -235,7 +221,6 @@ PHP_MSHUTDOWN_FUNCTION(localeconv)
return SUCCESS;
}
/* }}} */
-# endif
#endif
/* {{{ proto string bin2hex(string data)
@@ -716,7 +701,6 @@ PHP_FUNCTION(nl_langinfo)
#endif
/* }}} */
-#ifdef HAVE_STRCOLL
/* {{{ proto int strcoll(string str1, string str2)
Compares two strings using the current locale */
PHP_FUNCTION(strcoll)
@@ -732,7 +716,6 @@ PHP_FUNCTION(strcoll)
(const char *) ZSTR_VAL(s2)));
}
/* }}} */
-#endif
/* {{{ php_charmask
* Fills a 256-byte bytemask with input. You can specify a range like 'a..z',
@@ -1309,6 +1292,8 @@ PHP_FUNCTION(implode)
if (Z_TYPE_P(arg1) == IS_ARRAY) {
glue = zval_get_tmp_string(arg2, &tmp_glue);
pieces = arg1;
+ php_error_docref(NULL, E_DEPRECATED,
+ "Passing glue string after array is deprecated. Swap the parameters");
} else if (Z_TYPE_P(arg2) == IS_ARRAY) {
glue = zval_get_tmp_string(arg1, &tmp_glue);
pieces = arg2;
@@ -1766,7 +1751,7 @@ PHP_FUNCTION(pathinfo)
/* }}} */
/* {{{ php_stristr
- case insensitve strstr */
+ case insensitive strstr */
PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
{
php_strtolower(s, s_len);
@@ -1829,8 +1814,6 @@ static int php_needle_char(zval *needle, char *target)
*target = '\1';
return SUCCESS;
case IS_DOUBLE:
- *target = (char)(int)Z_DVAL_P(needle);
- return SUCCESS;
case IS_OBJECT:
*target = (char) zval_get_long(needle);
return SUCCESS;
@@ -2211,7 +2194,7 @@ PHP_FUNCTION(strripos)
php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
RETURN_FALSE;
}
- e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + (size_t)offset;
+ e = ZSTR_VAL(haystack) + (ZSTR_LEN(haystack) + (size_t)offset);
}
/* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */
*ZSTR_VAL(ord_needle) = tolower(*ZSTR_VAL(needle));
@@ -2415,52 +2398,53 @@ PHP_FUNCTION(substr)
Z_PARAM_LONG(l)
ZEND_PARSE_PARAMETERS_END();
- if (argc > 2) {
- if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) {
- RETURN_FALSE;
- } else if (l > (zend_long)ZSTR_LEN(str)) {
- l = ZSTR_LEN(str);
- }
- } else {
- l = ZSTR_LEN(str);
- }
-
if (f > (zend_long)ZSTR_LEN(str)) {
RETURN_FALSE;
- } else if (f < 0 && (size_t)-f > ZSTR_LEN(str)) {
- f = 0;
- }
-
- if (l < 0 && (l + (zend_long)ZSTR_LEN(str) - f) < 0) {
- RETURN_FALSE;
- }
-
- /* if "from" position is negative, count start position from the end
- * of the string
- */
- if (f < 0) {
- f = (zend_long)ZSTR_LEN(str) + f;
- if (f < 0) {
+ } else if (f < 0) {
+ /* if "from" position is negative, count start position from the end
+ * of the string
+ */
+ if ((size_t)-f > ZSTR_LEN(str)) {
f = 0;
+ } else {
+ f = (zend_long)ZSTR_LEN(str) + f;
}
- }
-
- /* if "length" position is negative, set it to the length
- * needed to stop that many chars from the end of the string
- */
- if (l < 0) {
- l = ((zend_long)ZSTR_LEN(str) - f) + l;
+ if (argc > 2) {
+ if (l < 0) {
+ /* if "length" position is negative, set it to the length
+ * needed to stop that many chars from the end of the string
+ */
+ if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
+ if ((size_t)(-l) > ZSTR_LEN(str)) {
+ RETURN_FALSE;
+ } else {
+ l = 0;
+ }
+ } else {
+ l = (zend_long)ZSTR_LEN(str) - f + l;
+ }
+ } else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
+ goto truncate_len;
+ }
+ } else {
+ goto truncate_len;
+ }
+ } else if (argc > 2) {
if (l < 0) {
- l = 0;
+ /* if "length" position is negative, set it to the length
+ * needed to stop that many chars from the end of the string
+ */
+ if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
+ RETURN_FALSE;
+ } else {
+ l = (zend_long)ZSTR_LEN(str) - f + l;
+ }
+ } else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
+ goto truncate_len;
}
- }
-
- if (f > (zend_long)ZSTR_LEN(str)) {
- RETURN_FALSE;
- }
-
- if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
- l = ZSTR_LEN(str) - f;
+ } else {
+truncate_len:
+ l = (zend_long)ZSTR_LEN(str) - f;
}
if (l == 0) {
@@ -2508,6 +2492,10 @@ PHP_FUNCTION(substr_replace)
convert_to_long_ex(from);
}
+ if (EG(exception)) {
+ return;
+ }
+
if (argc > 3) {
if (Z_TYPE_P(len) != IS_ARRAY) {
convert_to_long_ex(len);
@@ -2806,11 +2794,7 @@ PHP_FUNCTION(chr)
{
zend_long c;
- if (ZEND_NUM_ARGS() != 1) {
- WRONG_PARAM_COUNT;
- }
-
- ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
+ ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(c)
ZEND_PARSE_PARAMETERS_END_EX(c = 0);
@@ -3537,7 +3521,9 @@ PHP_FUNCTION(strtr)
php_strtr_array(return_value, str, pats);
}
} else {
- convert_to_string_ex(from);
+ if (!try_convert_to_string(from)) {
+ return;
+ }
RETURN_STR(php_strtr_ex(str,
Z_STRVAL_P(from),
@@ -3551,6 +3537,8 @@ PHP_FUNCTION(strtr)
Reverse a string */
#if ZEND_INTRIN_SSSE3_NATIVE
#include <tmmintrin.h>
+#elif defined(__aarch64__)
+#include <arm_neon.h>
#endif
PHP_FUNCTION(strrev)
{
@@ -3583,6 +3571,19 @@ PHP_FUNCTION(strrev)
e -= 16;
} while (e - s > 15);
}
+#elif defined(__aarch64__)
+ if (e - s > 15) {
+ do {
+ const uint8x16_t str = vld1q_u8((uint8_t *)(e - 15));
+ /* Synthesize rev128 with a rev64 + ext. */
+ const uint8x16_t rev = vrev64q_u8(str);
+ const uint8x16_t ext = (uint8x16_t)
+ vextq_u64((uint64x2_t)rev, (uint64x2_t)rev, 1);
+ vst1q_u8((uint8_t *)p, ext);
+ p += 16;
+ e -= 16;
+ } while (e - s > 15);
+ }
#endif
while (e >= s) {
*p++ = *e--;
@@ -3655,16 +3656,12 @@ PHP_FUNCTION(similar_text)
Z_PARAM_STR(t1)
Z_PARAM_STR(t2)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(percent)
+ Z_PARAM_ZVAL(percent)
ZEND_PARSE_PARAMETERS_END();
- if (ac > 2) {
- convert_to_double_ex(percent);
- }
-
if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) {
if (ac > 2) {
- Z_DVAL_P(percent) = 0;
+ ZEND_TRY_ASSIGN_REF_DOUBLE(percent, 0);
}
RETURN_LONG(0);
@@ -3673,7 +3670,7 @@ PHP_FUNCTION(similar_text)
sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2));
if (ac > 2) {
- Z_DVAL_P(percent) = sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2));
+ ZEND_TRY_ASSIGN_REF_DOUBLE(percent, sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2)));
}
RETURN_LONG(sim);
@@ -3751,24 +3748,6 @@ PHP_FUNCTION(stripslashes)
}
/* }}} */
-#ifndef HAVE_STRERROR
-/* {{{ php_strerror
- */
-char *php_strerror(int errnum)
-{
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- if ((unsigned int) errnum < sys_nerr) {
- return(sys_errlist[errnum]);
- }
-
- (void) snprintf(BG(str_ebuf), sizeof(php_basic_globals.str_ebuf), "Unknown error: %d", errnum);
- return(BG(str_ebuf));
-}
-/* }}} */
-#endif
-
/* {{{ php_stripcslashes
*/
PHPAPI void php_stripcslashes(zend_string *str)
@@ -3905,35 +3884,44 @@ PHPAPI zend_string *php_addslashes(zend_string *str) __attribute__((ifunc("resol
PHPAPI void php_stripslashes(zend_string *str) __attribute__((ifunc("resolve_stripslashes")));
ZEND_NO_SANITIZE_ADDRESS
+ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */
static void *resolve_addslashes() {
if (zend_cpu_supports_sse42()) {
return php_addslashes_sse42;
}
- return php_addslashes_default;
+ return php_addslashes_default;
}
ZEND_NO_SANITIZE_ADDRESS
+ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */
static void *resolve_stripslashes() {
if (zend_cpu_supports_sse42()) {
return php_stripslashes_sse42;
}
- return php_stripslashes_default;
+ return php_stripslashes_default;
}
# else /* ZEND_INTRIN_SSE4_2_FUNC_PTR */
-PHPAPI zend_string *(*php_addslashes)(zend_string *str) = NULL;
-PHPAPI void (*php_stripslashes)(zend_string *str) = NULL;
+static zend_string *(*php_addslashes_ptr)(zend_string *str) = NULL;
+static void (*php_stripslashes_ptr)(zend_string *str) = NULL;
+
+PHPAPI zend_string *php_addslashes(zend_string *str) {
+ return php_addslashes_ptr(str);
+}
+PHPAPI void php_stripslashes(zend_string *str) {
+ php_stripslashes_ptr(str);
+}
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(string_intrin)
{
if (zend_cpu_supports(ZEND_CPU_FEATURE_SSE42)) {
- php_addslashes = php_addslashes_sse42;
- php_stripslashes = php_stripslashes_sse42;
+ php_addslashes_ptr = php_addslashes_sse42;
+ php_stripslashes_ptr = php_stripslashes_sse42;
} else {
- php_addslashes = php_addslashes_default;
- php_stripslashes = php_stripslashes_default;
+ php_addslashes_ptr = php_addslashes_default;
+ php_stripslashes_ptr = php_stripslashes_default;
}
return SUCCESS;
}
@@ -4083,6 +4071,44 @@ do_escape:
/* }}} */
#endif
+#ifdef __aarch64__
+typedef union {
+ uint8_t mem[16];
+ uint64_t dw[2];
+} quad_word;
+
+static zend_always_inline quad_word aarch64_contains_slash_chars(uint8x16_t x) {
+ uint8x16_t s0 = vceqq_u8(x, vdupq_n_u8('\0'));
+ uint8x16_t s1 = vceqq_u8(x, vdupq_n_u8('\''));
+ uint8x16_t s2 = vceqq_u8(x, vdupq_n_u8('\"'));
+ uint8x16_t s3 = vceqq_u8(x, vdupq_n_u8('\\'));
+ uint8x16_t s01 = vorrq_u8(s0, s1);
+ uint8x16_t s23 = vorrq_u8(s2, s3);
+ uint8x16_t s0123 = vorrq_u8(s01, s23);
+ quad_word qw;
+ vst1q_u8(qw.mem, s0123);
+ return qw;
+}
+
+static zend_always_inline char *aarch64_add_slashes(quad_word res, const char *source, char *target)
+{
+ int i = 0;
+ for (; i < 16; i++) {
+ char s = source[i];
+ if (res.mem[i] == 0)
+ *target++ = s;
+ else {
+ *target++ = '\\';
+ if (s == '\0')
+ *target++ = '0';
+ else
+ *target++ = s;
+ }
+ }
+ return target;
+}
+#endif /* __aarch64__ */
+
#if !ZEND_INTRIN_SSE4_2_NATIVE
# if ZEND_INTRIN_SSE4_2_RESOLVER
zend_string *php_addslashes_default(zend_string *str) /* {{{ */
@@ -4103,6 +4129,19 @@ PHPAPI zend_string *php_addslashes(zend_string *str)
source = ZSTR_VAL(str);
end = source + ZSTR_LEN(str);
+# ifdef __aarch64__
+ quad_word res = {0};
+ if (ZSTR_LEN(str) > 15) {
+ do {
+ res = aarch64_contains_slash_chars(vld1q_u8((uint8_t *)source));
+ if (res.dw[0] | res.dw[1])
+ goto do_escape;
+ source += 16;
+ } while ((end - source) > 15);
+ }
+ /* Finish the last 15 bytes or less with the scalar loop. */
+# endif /* __aarch64__ */
+
while (source < end) {
switch (*source) {
case '\0':
@@ -4124,6 +4163,24 @@ do_escape:
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
target = ZSTR_VAL(new_str) + offset;
+# ifdef __aarch64__
+ if (res.dw[0] | res.dw[1]) {
+ target = aarch64_add_slashes(res, source, target);
+ source += 16;
+ }
+ for (; end - source > 15; source += 16) {
+ uint8x16_t x = vld1q_u8((uint8_t *)source);
+ res = aarch64_contains_slash_chars(x);
+ if (res.dw[0] | res.dw[1]) {
+ target = aarch64_add_slashes(res, source, target);
+ } else {
+ vst1q_u8((uint8_t*)target, x);
+ target += 16;
+ }
+ }
+ /* Finish the last 15 bytes or less with the scalar loop. */
+# endif /* __aarch64__ */
+
while (source < end) {
switch (*source) {
case '\0':
@@ -4161,6 +4218,37 @@ do_escape:
* be careful, this edits the string in-place */
static zend_always_inline char *php_stripslashes_impl(const char *str, char *out, size_t len)
{
+#ifdef __aarch64__
+ while (len > 15) {
+ uint8x16_t x = vld1q_u8((uint8_t *)str);
+ quad_word q;
+ vst1q_u8(q.mem, vceqq_u8(x, vdupq_n_u8('\\')));
+ if (q.dw[0] | q.dw[1]) {
+ int i = 0;
+ for (; i < 16; i++) {
+ if (q.mem[i] == 0) {
+ *out++ = str[i];
+ continue;
+ }
+
+ i++; /* skip the slash */
+ char s = str[i];
+ if (s == '0')
+ *out++ = '\0';
+ else
+ *out++ = s; /* preserve the next character */
+ }
+ str += i;
+ len -= i;
+ } else {
+ vst1q_u8((uint8_t*)out, x);
+ out += 16;
+ str += 16;
+ len -= 16;
+ }
+ }
+ /* Finish the last 15 bytes or less with the scalar loop. */
+#endif /* __aarch64__ */
while (len > 0) {
if (*str == '\\') {
str++; /* skip the slash */
@@ -4444,7 +4532,7 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
Z_PARAM_ZVAL(replace)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(zcount)
+ Z_PARAM_ZVAL(zcount)
ZEND_PARSE_PARAMETERS_END();
/* Make sure we're dealing with strings and do the replacement. */
@@ -4457,6 +4545,10 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
convert_to_string_ex(replace);
}
+ if (EG(exception)) {
+ return;
+ }
+
/* if subject is an array */
if (Z_TYPE_P(subject) == IS_ARRAY) {
array_init(return_value);
@@ -4481,8 +4573,7 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
count = php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity);
}
if (argc > 3) {
- zval_ptr_dtor(zcount);
- ZVAL_LONG(zcount, count);
+ ZEND_TRY_ASSIGN_REF_LONG(zcount, count);
}
}
/* }}} */
@@ -4785,6 +4876,7 @@ PHP_FUNCTION(strip_tags)
zval *allow=NULL;
const char *allowed_tags=NULL;
size_t allowed_tags_len=0;
+ smart_str tags_ss = {0};
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(str)
@@ -4792,15 +4884,34 @@ PHP_FUNCTION(strip_tags)
Z_PARAM_ZVAL(allow)
ZEND_PARSE_PARAMETERS_END();
- /* To maintain a certain BC, we allow anything for the second parameter and return original string */
if (allow) {
- convert_to_string(allow);
- allowed_tags = Z_STRVAL_P(allow);
- allowed_tags_len = Z_STRLEN_P(allow);
+ if (Z_TYPE_P(allow) == IS_ARRAY) {
+ zval *tmp;
+ zend_string *tag;
+
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(allow), tmp) {
+ tag = zval_get_string(tmp);
+ smart_str_appendc(&tags_ss, '<');
+ smart_str_append(&tags_ss, tag);
+ smart_str_appendc(&tags_ss, '>');
+ zend_string_release(tag);
+ } ZEND_HASH_FOREACH_END();
+ if (tags_ss.s) {
+ smart_str_0(&tags_ss);
+ allowed_tags = ZSTR_VAL(tags_ss.s);
+ allowed_tags_len = ZSTR_LEN(tags_ss.s);
+ }
+ } else {
+ /* To maintain a certain BC, we allow anything for the second parameter and return original string */
+ convert_to_string(allow);
+ allowed_tags = Z_STRVAL_P(allow);
+ allowed_tags_len = Z_STRLEN_P(allow);
+ }
}
buf = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
ZSTR_LEN(buf) = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0);
+ smart_str_free(&tags_ss);
RETURN_NEW_STR(buf);
}
/* }}} */
@@ -4822,7 +4933,6 @@ PHP_FUNCTION(setlocale)
Z_PARAM_VARIADIC('+', args, num_args)
ZEND_PARSE_PARAMETERS_END();
-#ifdef HAVE_SETLOCALE
idx = 0;
while (1) {
if (Z_TYPE(args[0]) == IS_ARRAY) {
@@ -4840,7 +4950,10 @@ PHP_FUNCTION(setlocale)
plocale = &args[i];
}
- loc = zval_get_string(plocale);
+ loc = zval_try_get_string(plocale);
+ if (UNEXPECTED(!loc)) {
+ return;
+ }
if (!strcmp("0", ZSTR_VAL(loc))) {
zend_string_release_ex(loc, 0);
@@ -4912,7 +5025,6 @@ PHP_FUNCTION(setlocale)
}
}
-#endif
RETURN_FALSE;
}
/* }}} */
@@ -4929,7 +5041,7 @@ PHP_FUNCTION(parse_str)
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STRING(arg, arglen)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(arrayArg)
+ Z_PARAM_ZVAL(arrayArg)
ZEND_PARSE_PARAMETERS_END();
res = estrndup(arg, arglen);
@@ -4951,9 +5063,12 @@ PHP_FUNCTION(parse_str)
zend_throw_error(NULL, "Cannot re-assign $this");
}
} else {
- /* Clear out the array that was passed in. */
- zval_ptr_dtor(arrayArg);
- array_init(arrayArg);
+ arrayArg = zend_try_array_init(arrayArg);
+ if (!arrayArg) {
+ efree(res);
+ return;
+ }
+
sapi_module.treat_data(PARSE_STRING, res, arrayArg);
}
}
@@ -5060,7 +5175,6 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const
uint8_t state = 0;
size_t pos;
char *allow_free = NULL;
- const char *allow_actual;
char is_xml = 0;
buf = estrndup(rbuf, len);
@@ -5071,7 +5185,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const
br = 0;
if (allow) {
allow_free = zend_str_tolower_dup_ex(allow, allow_len);
- allow_actual = allow_free ? allow_free : allow;
+ allow = allow_free ? allow_free : allow;
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf;
} else {
@@ -5176,7 +5290,7 @@ state_1:
}
*(tp++) = '>';
*tp='\0';
- if (php_tag_find(tbuf, tp-tbuf, allow_actual)) {
+ if (php_tag_find(tbuf, tp-tbuf, allow)) {
memcpy(rp, tbuf, tp-tbuf);
rp += tp-tbuf;
}
@@ -5377,11 +5491,11 @@ finish:
*rp = '\0';
}
efree((void *)buf);
- if (allow) {
+ if (tbuf) {
efree(tbuf);
- if (allow_free) {
- efree(allow_free);
- }
+ }
+ if (allow_free) {
+ efree(allow_free);
}
if (stateptr)
*stateptr = state;
@@ -5395,7 +5509,8 @@ Parse a CSV string into an array */
PHP_FUNCTION(str_getcsv)
{
zend_string *str;
- char delim = ',', enc = '"', esc = '\\';
+ char delim = ',', enc = '"';
+ int esc = (unsigned char) '\\';
char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
size_t delim_len = 0, enc_len = 0, esc_len = 0;
@@ -5409,7 +5524,9 @@ PHP_FUNCTION(str_getcsv)
delim = delim_len ? delim_str[0] : delim;
enc = enc_len ? enc_str[0] : enc;
- esc = esc_len ? esc_str[0] : esc;
+ if (esc_str != NULL) {
+ esc = esc_len ? (unsigned char) esc_str[0] : PHP_CSV_NO_ESCAPE;
+ }
php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str), return_value);
}
@@ -5606,7 +5723,6 @@ PHP_FUNCTION(localeconv)
array_init(&grouping);
array_init(&mon_grouping);
-#ifdef HAVE_LOCALECONV
{
struct lconv currlocdata;
@@ -5643,30 +5759,6 @@ PHP_FUNCTION(localeconv)
add_assoc_long( return_value, "p_sign_posn", currlocdata.p_sign_posn);
add_assoc_long( return_value, "n_sign_posn", currlocdata.n_sign_posn);
}
-#else
- /* Ok, it doesn't look like we have locale info floating around, so I guess it
- wouldn't hurt to just go ahead and return the POSIX locale information? */
-
- add_index_long(&grouping, 0, -1);
- add_index_long(&mon_grouping, 0, -1);
-
- add_assoc_string(return_value, "decimal_point", "\x2E");
- add_assoc_string(return_value, "thousands_sep", "");
- add_assoc_string(return_value, "int_curr_symbol", "");
- add_assoc_string(return_value, "currency_symbol", "");
- add_assoc_string(return_value, "mon_decimal_point", "\x2E");
- add_assoc_string(return_value, "mon_thousands_sep", "");
- add_assoc_string(return_value, "positive_sign", "");
- add_assoc_string(return_value, "negative_sign", "");
- add_assoc_long( return_value, "int_frac_digits", CHAR_MAX);
- add_assoc_long( return_value, "frac_digits", CHAR_MAX);
- add_assoc_long( return_value, "p_cs_precedes", CHAR_MAX);
- add_assoc_long( return_value, "p_sep_by_space", CHAR_MAX);
- add_assoc_long( return_value, "n_cs_precedes", CHAR_MAX);
- add_assoc_long( return_value, "n_sep_by_space", CHAR_MAX);
- add_assoc_long( return_value, "p_sign_posn", CHAR_MAX);
- add_assoc_long( return_value, "n_sign_posn", CHAR_MAX);
-#endif
zend_hash_str_update(Z_ARRVAL_P(return_value), "grouping", sizeof("grouping")-1, &grouping);
zend_hash_str_update(Z_ARRVAL_P(return_value), "mon_grouping", sizeof("mon_grouping")-1, &mon_grouping);
@@ -6361,12 +6453,3 @@ PHP_FUNCTION(utf8_decode)
RETURN_STR(php_utf8_decode(arg, arg_len));
}
/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */