From 5557b499824a29ef12492cb2c2f69d587b1ae2b8 Mon Sep 17 00:00:00 2001 From: Matt Wilmas Date: Wed, 1 Apr 2009 17:04:17 +0000 Subject: [PATCH] explode() stuff: - Fixed bug #47560 (explode()'s limit parameter odd behaviour) by reverting change for bug #47546 - Changed int to long where needed (should fix memory errors from overflow seen in bug #47854) - Simplified logic a bit with limit and its default value - php_explode_negative_limit(): removed safe_emalloc (not needed; plain erealloc is used later) - Moved declarations/allocation to optimize if the delimiter isn't found - Changed ALLOC_STEP size for less realloc's (and maybe better memory block alignment?) --- ext/standard/php_string.h | 2 +- ext/standard/string.c | 52 ++++++++++++------------ ext/standard/tests/strings/bug47546.phpt | 24 ----------- 3 files changed, 28 insertions(+), 50 deletions(-) delete mode 100644 ext/standard/tests/strings/bug47546.phpt diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index f46072fe792..4a9c8fba9d8 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -158,7 +158,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow, PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_len, zval *result, int case_sensitivity, int *replace_count); PHPAPI int php_char_to_str(char *str, uint len, char from, char *to, int to_len, zval *result); PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC); -PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, int limit); +PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, long limit); PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end); PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end); diff --git a/ext/standard/string.c b/ext/standard/string.c index 16a087a4eaa..ec500fc74dd 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1137,7 +1137,7 @@ PHP_FUNCTION(wordwrap) /* {{{ php_explode */ -PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, int limit) +PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, long limit) { char *p1, *p2, *endp; @@ -1152,7 +1152,7 @@ PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, ze add_next_index_stringl(return_value, p1, p2-p1, 1); p1 = p2 + delim_len; } while ( (p2 = php_memnstr(p1, delim, delim_len, endp)) != NULL && - (limit == -1 || --limit > 1) ); + --limit > 1 ); if ( p1 <= endp ) { add_next_index_stringl(return_value, p1, endp-p1, 1); @@ -1163,12 +1163,10 @@ PHPAPI void php_explode(char *delim, uint delim_len, char *str, uint str_len, ze /* {{{ php_explode_negative_limit */ -PHPAPI void php_explode_negative_limit(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, int limit) +PHPAPI void php_explode_negative_limit(char *delim, uint delim_len, char *str, uint str_len, zend_uchar str_type, zval *return_value, long limit) { -#define EXPLODE_ALLOC_STEP 50 +#define EXPLODE_ALLOC_STEP 64 char *p1, *p2, *endp; - int allocated = EXPLODE_ALLOC_STEP, found = 0, i = 0, to_return = 0; - char **positions = safe_emalloc(allocated, sizeof(char *), 0); endp = str + str_len; p1 = str; @@ -1180,6 +1178,10 @@ PHPAPI void php_explode_negative_limit(char *delim, uint delim_len, char *str, u by doing nothing we return empty array */ } else { + int allocated = EXPLODE_ALLOC_STEP, found = 0; + long i, to_return; + char **positions = emalloc(allocated * sizeof(char *)); + positions[found++] = p1; do { if ( found >= allocated ) { @@ -1195,8 +1197,8 @@ PHPAPI void php_explode_negative_limit(char *delim, uint delim_len, char *str, u add_next_index_stringl(return_value, positions[i], (positions[i+1]-delim_len) - positions[i], 1); } + efree(positions); } - efree(positions); #undef EXPLODE_ALLOC_STEP } /* }}} */ @@ -1204,7 +1206,7 @@ PHPAPI void php_explode_negative_limit(char *delim, uint delim_len, char *str, u /* {{{ php_u_explode * Unicode capable version of php_explode() */ -static void php_u_explode(UChar *delim, uint delim_len, UChar *str, uint str_len, zval *return_value, int limit) +static void php_u_explode(UChar *delim, uint delim_len, UChar *str, uint str_len, zval *return_value, long limit) { UChar *p1, *p2, *endp; @@ -1219,7 +1221,7 @@ static void php_u_explode(UChar *delim, uint delim_len, UChar *str, uint str_len add_next_index_unicodel(return_value, p1, p2-p1, 1); p1 = (UChar *)p2 + delim_len; } while ((p2 = zend_u_memnstr(p1, delim, delim_len, endp)) != NULL && - (limit == -1 || --limit > 1) ); + --limit > 1 ); if ( p1 <= endp ) { add_next_index_unicodel(return_value, p1, endp-p1, 1); @@ -1231,12 +1233,10 @@ static void php_u_explode(UChar *delim, uint delim_len, UChar *str, uint str_len /* {{{ php_u_explode_negative_limit * Unicode capable version of php_explode_negative_limit() */ -static void php_u_explode_negative_limit(UChar *delim, uint delim_len, UChar *str, uint str_len, zval *return_value, int limit) +static void php_u_explode_negative_limit(UChar *delim, uint delim_len, UChar *str, uint str_len, zval *return_value, long limit) { -#define EXPLODE_ALLOC_STEP 50 +#define EXPLODE_ALLOC_STEP 64 UChar *p1, *p2, *endp; - int allocated = EXPLODE_ALLOC_STEP, found = 0, i = 0, to_return = 0; - UChar **positions = safe_emalloc(allocated, sizeof(UChar *), 0); endp = str + str_len; p1 = str; @@ -1248,6 +1248,10 @@ static void php_u_explode_negative_limit(UChar *delim, uint delim_len, UChar *st by doing nothing we return empty array */ } else { + int allocated = EXPLODE_ALLOC_STEP, found = 0; + long i, to_return; + UChar **positions = emalloc(allocated * sizeof(UChar *)); + positions[found++] = p1; do { if ( found >= allocated ) { @@ -1263,8 +1267,8 @@ static void php_u_explode_negative_limit(UChar *delim, uint delim_len, UChar *st add_next_index_unicodel(return_value, positions[i], (positions[i+1]-delim_len) - positions[i], 1); } + efree(positions); } - efree(positions); #undef EXPLODE_ALLOC_STEP } /* }}} */ @@ -1276,10 +1280,9 @@ PHP_FUNCTION(explode) void *str, *delim; int str_len, delim_len; zend_uchar str_type, delim_type; - long limit = -1; - int argc = ZEND_NUM_ARGS(); + long limit = LONG_MAX; /* No limit */ - if (zend_parse_parameters(argc TSRMLS_CC, "TT|l", &delim, &delim_len, &delim_type, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT|l", &delim, &delim_len, &delim_type, &str, &str_len, &str_type, &limit) == FAILURE) { return; } @@ -1292,7 +1295,7 @@ PHP_FUNCTION(explode) array_init(return_value); if ( str_len == 0 ) { - if (limit >= 0 || argc == 2) { + if (limit >= 0) { if ( str_type == IS_UNICODE ) { add_next_index_unicodel(return_value, USTR_MAKE(""), sizeof("")-1, 0); } else { @@ -1302,14 +1305,13 @@ PHP_FUNCTION(explode) return; } - - if (limit == 0 || limit == 1) { + if (limit > 1) { if ( str_type == IS_UNICODE ) { - add_index_unicodel(return_value, 0, (UChar *)str, str_len, 1); + php_u_explode((UChar *)delim, delim_len, (UChar *)str, str_len, return_value, limit); } else { - add_index_stringl(return_value, 0, (char *)str, str_len, 1); + php_explode((char *)delim, delim_len, (char *)str, str_len, str_type, return_value, limit); } - } else if (limit < -1 && argc == 3) { + } else if (limit < 0) { if ( str_type == IS_UNICODE ) { php_u_explode_negative_limit((UChar *)delim, delim_len, (UChar *)str, str_len, return_value, limit); } else { @@ -1317,9 +1319,9 @@ PHP_FUNCTION(explode) } } else { if ( str_type == IS_UNICODE ) { - php_u_explode((UChar *)delim, delim_len, (UChar *)str, str_len, return_value, limit); + add_index_unicodel(return_value, 0, (UChar *)str, str_len, 1); } else { - php_explode((char *)delim, delim_len, (char *)str, str_len, str_type, return_value, limit); + add_index_stringl(return_value, 0, (char *)str, str_len, 1); } } } diff --git a/ext/standard/tests/strings/bug47546.phpt b/ext/standard/tests/strings/bug47546.phpt deleted file mode 100644 index f04f9be05a0..00000000000 --- a/ext/standard/tests/strings/bug47546.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Bug #47546 (Default value for limit parameter in explode is 0, not -1) ---FILE-- - ---EXPECT-- -Array -( - [0] => one - [1] => two - [2] => three - [3] => four -) -Array -( - [0] => one - [1] => two - [2] => three - [3] => four -)