Cleanup (avoid reallocatios and side effects in php_strip_tags)

This commit is contained in:
Dmitry Stogov 2015-07-01 19:04:18 +03:00
parent 068f63ceb2
commit d2d326a381
6 changed files with 46 additions and 48 deletions

View File

@ -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) /* {{{ */ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str) /* {{{ */
{ {
register unsigned char *p = (unsigned char*)ZSTR_VAL(str); register unsigned char *p = (unsigned char*)ZSTR_VAL(str);

View File

@ -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 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_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(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 zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str);
ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2); ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2);

View File

@ -1084,11 +1084,10 @@ PHPAPI PHP_FUNCTION(fgetss)
size_t actual_len, retval_len; size_t actual_len, retval_len;
char *buf = NULL, *retval; char *buf = NULL, *retval;
php_stream *stream; php_stream *stream;
zend_string *allowed = NULL;
char *allowed_tags=NULL; char *allowed_tags=NULL;
size_t allowed_tags_len=0; 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; RETURN_FALSE;
} }
@ -1113,24 +1112,8 @@ PHPAPI PHP_FUNCTION(fgetss)
RETURN_FALSE; 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); 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 ??? // TODO: avoid reallocation ???
RETVAL_STRINGL(retval, retval_len); RETVAL_STRINGL(retval, retval_len);
efree(retval); efree(retval);

View File

@ -217,7 +217,7 @@ static php_stream_filter_status_t strfilter_strip_tags_filter(
bucket = php_stream_bucket_make_writeable(buckets_in->head); bucket = php_stream_bucket_make_writeable(buckets_in->head);
consumed = bucket->buflen; 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); php_stream_bucket_append(buckets_out, bucket);
} }

View File

@ -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, PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle,
size_t needle_len, char *str, size_t str_len); 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 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(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, char *allow, size_t allow_len, zend_bool allow_tag_spaces); 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_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); PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit);

View File

@ -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 */ /* this is read-only, so it's ok */
static char hexconvtab[] = "0123456789abcdef"; 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 */ /* To maintain a certain BC, we allow anything for the second parameter and return original string */
if (allow != NULL) { if (allow) {
convert_to_string_ex(allow); convert_to_string(allow);
// TODO: reimplement to avoid reallocation ??? allowed_tags = Z_STRVAL_P(allow);
if (!Z_REFCOUNTED_P(allow)) { allowed_tags_len = Z_STRLEN_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);
}
} }
buf = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0); 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); ZSTR_LEN(buf) = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0);
RETURN_NEW_STR(buf);
// TODO: reimplement to avoid reallocation ???
if (allow && !Z_REFCOUNTED_P(allow)) {
efree(allowed_tags);
}
RETURN_STR(buf);
} }
/* }}} */ /* }}} */
@ -4608,7 +4597,7 @@ PHP_FUNCTION(parse_str)
* 0 start tag * 0 start tag
* 1 first non-whitespace char seen * 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; char c, *n, *t;
int state=0, done=0; int state=0, done=0;
char *norm; 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); 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 <?xml tags without assuming it PHP swm: Added ability to strip <?xml tags without assuming it PHP
code. code.
*/ */
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_ex(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces)
{ {
char *tbuf, *buf, *p, *tp, *rp, c, lc; char *tbuf, *buf, *p, *tp, *rp, c, lc;
int br, depth=0, in_q = 0; int br, depth=0, in_q = 0;
int state = 0; int state = 0;
size_t pos, i = 0; size_t pos, i = 0;
char *allow_free = NULL; char *allow_free = NULL;
const char *allow_actual;
if (stateptr) if (stateptr)
state = *stateptr; state = *stateptr;
@ -4707,12 +4697,8 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, char *all
rp = rbuf; rp = rbuf;
br = 0; br = 0;
if (allow) { if (allow) {
//??? if (ZSTR_IS_INTERNED(allow)) { allow_free = zend_str_tolower_dup_ex(allow, allow_len);
//??? allow_free = allow = zend_str_tolower_dup(allow, allow_len); allow_actual = allow_free ? allow_free : allow;
//??? } else {
allow_free = NULL;
php_strtolower(allow, allow_len);
//??? }
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1); tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf; tp = tbuf;
} else { } else {
@ -4804,7 +4790,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, char *all
} }
*(tp++) = '>'; *(tp++) = '>';
*tp='\0'; *tp='\0';
if (php_tag_find(tbuf, tp-tbuf, allow)) { if (php_tag_find(tbuf, tp-tbuf, allow_actual)) {
memcpy(rp, tbuf, tp-tbuf); memcpy(rp, tbuf, tp-tbuf);
rp += tp-tbuf; rp += tp-tbuf;
} }