diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index 7a992b4966c18..5dc09b28247dd 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -182,6 +182,7 @@ void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL) { size_t new_len; unsigned char enc[256] = {0}; + zend_string* newval; if (!Z_REFCOUNTED_P(value)) { ZVAL_STRINGL(value, Z_STRVAL_P(value), Z_STRLEN_P(value)); @@ -206,10 +207,11 @@ void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL) php_filter_encode_html(value, enc); /* strip tags, implicitly also removes \0 chars */ - new_len = php_strip_tags_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), NULL, NULL, 0, 1); - Z_STRLEN_P(value) = new_len; + newval = php_strip_tags_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), NULL, NULL, 0, 1); + zval_ptr_dtor(value); + ZVAL_STR(value, newval); - if (new_len == 0) { + if (ZSTR_LEN(newval) == 0) { zval_ptr_dtor(value); if (flags & FILTER_FLAG_EMPTY_STRING_NULL) { ZVAL_NULL(value); diff --git a/ext/standard/file.c b/ext/standard/file.c index 4fa498cdf4df6..fd6052cc239e4 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1099,7 +1099,8 @@ PHPAPI PHP_FUNCTION(fgetss) zend_long bytes = 0; size_t len = 0; size_t actual_len, retval_len; - char *buf = NULL, *retval; + char *buf = NULL, *str; + zend_string* retval; php_stream *stream; char *allowed_tags=NULL; size_t allowed_tags_len=0; @@ -1125,18 +1126,16 @@ PHPAPI PHP_FUNCTION(fgetss) memset(buf, 0, len + 1); } - if ((retval = php_stream_get_line(stream, buf, len, &actual_len)) == NULL) { + if ((str = php_stream_get_line(stream, buf, len, &actual_len)) == NULL) { if (buf != NULL) { efree(buf); } RETURN_FALSE; } - retval_len = php_strip_tags(retval, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len); - - // TODO: avoid reallocation ??? - RETVAL_STRINGL(retval, retval_len); - efree(retval); + retval = php_strip_tags(str, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len); + efree(str); + RETURN_NEW_STR(retval); } /* }}} */ diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 7e49b3ee3b7c0..cd84baaa8e5f2 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -140,8 +140,8 @@ PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len); PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const char *needle, size_t needle_len, const 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, uint8_t *state, const char *allow, size_t allow_len); -PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces); +PHPAPI zend_string *php_strip_tags(char *rbuf, size_t len, uint8_t *state, const char *allow, size_t allow_len); +PHPAPI zend_string *php_strip_tags_ex(char *rbuf, size_t len, uint8_t *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 2f20d62a7485b..500bc63437cef 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4778,6 +4778,7 @@ PHP_FUNCTION(nl2br) PHP_FUNCTION(strip_tags) { zend_string *buf; + zend_string *newbuf; zend_string *str; zval *allow=NULL; const char *allowed_tags=NULL; @@ -4797,8 +4798,10 @@ PHP_FUNCTION(strip_tags) } 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); - RETURN_NEW_STR(buf); + newbuf = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0); + zend_string_release(buf); + + RETURN_NEW_STR(newbuf); } /* }}} */ @@ -5002,7 +5005,7 @@ int php_tag_find(char *tag, size_t len, const char *set) { } /* }}} */ -PHPAPI size_t php_strip_tags(char *rbuf, size_t len, uint8_t *stateptr, const char *allow, size_t allow_len) /* {{{ */ +PHPAPI zend_string *php_strip_tags(char *rbuf, size_t len, uint8_t *stateptr, const char *allow, size_t allow_len) /* {{{ */ { return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0); } @@ -5028,9 +5031,9 @@ PHPAPI size_t php_strip_tags(char *rbuf, size_t len, uint8_t *stateptr, const ch swm: Added ability to strip (>) + pos = rp - rbuf; + rbuf = erealloc(rbuf, len += 3); // there was room for 1 <, add 3 more chars + rp = rbuf + pos; + + // resize temporary buffer if necessary + if ((tp - tbuf) + 4 >= PHP_TAG_BUF_SIZE) { + pos = tp - tbuf; + tbuf = erealloc(tbuf, pos + PHP_TAG_BUF_SIZE + 1); // add room for < + tp = tbuf + pos; + } + + // store escaped < + strcpy(tp, "<"); + tp += 4; + } if (in_q) { break; } @@ -5135,6 +5155,23 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const depth--; break; } + if (in_q && allow) { + // resize return buffer to store escaped > (>) + pos = rp - rbuf; + rbuf = erealloc(rbuf, len += 3); // there was room for 1 <, add 3 more chars + rp = rbuf + pos; + + // resize temporary buffer + if ((tp - tbuf) + 4 >= PHP_TAG_BUF_SIZE) { + pos = tp - tbuf; + tbuf = erealloc(tbuf, pos + PHP_TAG_BUF_SIZE + 1); // add room for > + tp = tbuf + pos; + } + + // store escaped > + strcpy(tp, ">"); + tp += 4; + } if (in_q) { break; } @@ -5196,6 +5233,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const if (allow) { if (tp - tbuf >= PHP_TAG_BUF_SIZE) { pos = tp - tbuf; + tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1); tp = tbuf + pos; } @@ -5355,7 +5393,10 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const if (stateptr) *stateptr = state; - return (size_t)(rp - rbuf); + // copy string to new buffer + size_t new_len = (size_t)(rp-rbuf); + + return zend_string_init(rbuf, (size_t)(rp - rbuf), 0); } /* }}} */ diff --git a/ext/standard/tests/strings/bug74371.phpt b/ext/standard/tests/strings/bug74371.phpt new file mode 100644 index 0000000000000..f66a97731a8b0 --- /dev/null +++ b/ext/standard/tests/strings/bug74371.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #74371: strip_tags altering attributes +--FILE-- + :<">', '') . PHP_EOL; +echo strip_tags('\':> :<', '') . PHP_EOL; +echo strip_tags(':', '') . PHP_EOL; +echo strip_tags('<', '') . PHP_EOL; + +?> +--EXPECT-- +:> :< +':> :< +:alert(0) +< \ No newline at end of file