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) /* {{{ */
{
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 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);

View File

@ -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);

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);
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);
}

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,
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);

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 */
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 <?xml tags without assuming it PHP
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;
int br, depth=0, in_q = 0;
int state = 0;
size_t pos, i = 0;
char *allow_free = NULL;
const char *allow_actual;
if (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;
br = 0;
if (allow) {
//??? if (ZSTR_IS_INTERNED(allow)) {
//??? allow_free = allow = zend_str_tolower_dup(allow, allow_len);
//??? } else {
allow_free = NULL;
php_strtolower(allow, allow_len);
//??? }
allow_free = zend_str_tolower_dup_ex(allow, allow_len);
allow_actual = allow_free ? allow_free : allow;
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf;
} else {
@ -4804,7 +4790,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, char *all
}
*(tp++) = '>';
*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;
}