From d2d326a381d99fdf148ea30e2d96a7b525e35d9f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 1 Jul 2015 19:04:18 +0300 Subject: [PATCH] Cleanup (avoid reallocatios and side effects in php_strip_tags) --- Zend/zend_operators.c | 28 +++++++++++++++++++++++++++ Zend/zend_operators.h | 1 + ext/standard/file.c | 19 +------------------ ext/standard/filters.c | 2 +- ext/standard/php_string.h | 4 ++-- ext/standard/string.c | 40 +++++++++++++-------------------------- 6 files changed, 46 insertions(+), 48 deletions(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1abfcca7a53..2b90475ba0f 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2417,6 +2417,34 @@ ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length) /* {{{ */ } /* }}} */ +ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length) /* {{{ */ +{ + register const unsigned char *p = (const unsigned char*)source; + register const unsigned char *end = p + length; + + while (p < end) { + if (*p != zend_tolower_ascii(*p)) { + char *res = (char*)emalloc(length + 1); + register unsigned char *r; + + if (p != (const unsigned char*)source) { + memcpy(res, source, p - (const unsigned char*)source); + } + r = (unsigned char*)p + (res - source); + while (p < end) { + *r = zend_tolower_ascii(*p); + p++; + r++; + } + *r = '\0'; + return res; + } + p++; + } + return NULL; +} +/* }}} */ + ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str) /* {{{ */ { register unsigned char *p = (unsigned char*)ZSTR_VAL(str); diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 601508ca276..541d6f978fa 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -340,6 +340,7 @@ ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2); ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length); ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length); ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length); +ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length); ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str); ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2); diff --git a/ext/standard/file.c b/ext/standard/file.c index fc6bf5ae953..295c1ae1ecf 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1084,11 +1084,10 @@ PHPAPI PHP_FUNCTION(fgetss) size_t actual_len, retval_len; char *buf = NULL, *retval; php_stream *stream; - zend_string *allowed = NULL; char *allowed_tags=NULL; size_t allowed_tags_len=0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|lS", &fd, &bytes, &allowed) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ls", &fd, &bytes, &allowed_tags, &allowed_tags_len) == FAILURE) { RETURN_FALSE; } @@ -1113,24 +1112,8 @@ PHPAPI PHP_FUNCTION(fgetss) RETURN_FALSE; } - if (allowed != NULL) { -// TODO: reimplement to avoid reallocation ??? - if (ZSTR_IS_INTERNED(allowed)) { - allowed_tags = estrndup(ZSTR_VAL(allowed), ZSTR_LEN(allowed)); - allowed_tags_len = ZSTR_LEN(allowed); - } else { - allowed_tags = ZSTR_VAL(allowed); - allowed_tags_len = ZSTR_LEN(allowed); - } - } - retval_len = php_strip_tags(retval, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len); -// TODO: reimplement to avoid reallocation ??? - if (allowed && ZSTR_IS_INTERNED(allowed)) { - efree(allowed_tags); - } - // TODO: avoid reallocation ??? RETVAL_STRINGL(retval, retval_len); efree(retval); diff --git a/ext/standard/filters.c b/ext/standard/filters.c index 105e156c9e6..3a1f0750400 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -217,7 +217,7 @@ static php_stream_filter_status_t strfilter_strip_tags_filter( bucket = php_stream_bucket_make_writeable(buckets_in->head); consumed = bucket->buflen; - bucket->buflen = php_strip_tags(bucket->buf, bucket->buflen, &(inst->state), (char *)inst->allowed_tags, inst->allowed_tags_len); + bucket->buflen = php_strip_tags(bucket->buf, bucket->buflen, &(inst->state), inst->allowed_tags, inst->allowed_tags_len); php_stream_bucket_append(buckets_out, bucket); } diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index b5cf8f30517..8390bd79fef 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -133,8 +133,8 @@ PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len); PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle, size_t needle_len, char *str, size_t str_len); PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode); -PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *state, char *allow, size_t allow_len); -PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, char *allow, size_t allow_len, zend_bool allow_tag_spaces); +PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *state, const char *allow, size_t allow_len); +PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces); PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value); PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit); diff --git a/ext/standard/string.c b/ext/standard/string.c index 3a828ed675f..6c436f234f8 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -115,7 +115,7 @@ void register_string_constants(INIT_FUNC_ARGS) } /* }}} */ -int php_tag_find(char *tag, size_t len, char *set); +int php_tag_find(char *tag, size_t len, const char *set); /* this is read-only, so it's ok */ static char hexconvtab[] = "0123456789abcdef"; @@ -4451,26 +4451,15 @@ PHP_FUNCTION(strip_tags) } /* To maintain a certain BC, we allow anything for the second parameter and return original string */ - if (allow != NULL) { - convert_to_string_ex(allow); -// TODO: reimplement to avoid reallocation ??? - if (!Z_REFCOUNTED_P(allow)) { - allowed_tags = estrndup(Z_STRVAL_P(allow), Z_STRLEN_P(allow)); - allowed_tags_len = Z_STRLEN_P(allow); - } else { - allowed_tags = Z_STRVAL_P(allow); - allowed_tags_len = Z_STRLEN_P(allow); - } + if (allow) { + 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); - -// TODO: reimplement to avoid reallocation ??? - if (allow && !Z_REFCOUNTED_P(allow)) { - efree(allowed_tags); - } - RETURN_STR(buf); + RETURN_NEW_STR(buf); } /* }}} */ @@ -4608,7 +4597,7 @@ PHP_FUNCTION(parse_str) * 0 start tag * 1 first non-whitespace char seen */ -int php_tag_find(char *tag, size_t len, char *set) { +int php_tag_find(char *tag, size_t len, const char *set) { char c, *n, *t; int state=0, done=0; char *norm; @@ -4663,7 +4652,7 @@ int php_tag_find(char *tag, size_t len, char *set) { } /* }}} */ -PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *stateptr, char *allow, size_t allow_len) /* {{{ */ +PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len) /* {{{ */ { return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0); } @@ -4689,13 +4678,14 @@ PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *stateptr, char *allow, swm: Added ability to strip '; *tp='\0'; - if (php_tag_find(tbuf, tp-tbuf, allow)) { + if (php_tag_find(tbuf, tp-tbuf, allow_actual)) { memcpy(rp, tbuf, tp-tbuf); rp += tp-tbuf; }