From 6ec5ab77df816a66e480f2d3dcf4f917c4390833 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 23 Dec 2014 04:29:41 +0300 Subject: [PATCH] Improved trim/ltrim/rtrim functions. Now php_trim() operates on zend_string and returns zend_string (it may return the same zend_string). --- ext/mbstring/mbstring.c | 12 ++--- ext/simplexml/simplexml.c | 9 ++-- ext/standard/http_fopen_wrapper.c | 72 ++++++++++++++++------------- ext/standard/mail.c | 16 +++---- ext/standard/php_string.h | 2 +- ext/standard/string.c | 77 ++++++++++++++++++++----------- 6 files changed, 111 insertions(+), 77 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 1e7cb5bd73a..d816ee52e75 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -1437,17 +1437,17 @@ static PHP_INI_MH(OnUpdate_mbstring_encoding_translation) /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes */ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes) { - zval tmp; + zend_string *tmp; void *re = NULL; if (!new_value) { new_value = entry->orig_value; } - php_trim(new_value->val, new_value->len, NULL, 0, &tmp, 3); + tmp = php_trim(new_value, NULL, 0, 3); - if (Z_STRLEN(tmp) > 0) { - if (!(re = _php_mb_compile_regex(Z_STRVAL(tmp)))) { - zval_dtor(&tmp); + if (tmp->len > 0) { + if (!(re = _php_mb_compile_regex(tmp->val))) { + zend_string_release(tmp); return FAILURE; } } @@ -1458,7 +1458,7 @@ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes) MBSTRG(http_output_conv_mimetypes) = re; - zval_dtor(&tmp); + zend_string_release(tmp); return SUCCESS; } /* }}} */ diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 692b5d368af..edaa48ba224 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -456,7 +456,8 @@ static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool int new_value = 0; zend_long cnt = 0; int retval = SUCCESS; - zval tmp_zv, trim_zv, zval_copy; + zval tmp_zv, zval_copy; + zend_string *trim_str; sxe = Z_SXEOBJ_P(object); @@ -474,9 +475,9 @@ static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool } } else { if (Z_TYPE_P(member) != IS_STRING) { - ZVAL_STR(&trim_zv, zval_get_string(member)); - php_trim(Z_STRVAL(trim_zv), Z_STRLEN(trim_zv), NULL, 0, &tmp_zv, 3); - zval_dtor(&trim_zv); + trim_str = zval_get_string(member); + ZVAL_STR(&tmp_zv, php_trim(trim_str, NULL, 0, 3)); + zend_string_release(trim_str); member = &tmp_zv; } diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 032c6c7e360..01e3b2cfe43 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -118,7 +118,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, int use_ssl; int use_proxy = 0; char *scratch = NULL; - char *tmp = NULL; + zend_string *tmp = NULL; char *ua_str = NULL; zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name; size_t scratch_len = 0; @@ -440,88 +440,96 @@ finish: smart_str_0(&tmpstr); /* Remove newlines and spaces from start and end. there's at least one extra \r\n at the end that needs to go. */ if (tmpstr.s) { - tmp = php_trim(tmpstr.s->val, tmpstr.s->len, NULL, 0, NULL, 3); + tmp = php_trim(tmpstr.s, NULL, 0, 3); smart_str_free(&tmpstr); } - } - if (Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval)) { + } else if (Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval)) { /* Remove newlines and spaces from start and end php_trim will estrndup() */ - tmp = php_trim(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval), NULL, 0, NULL, 3); + tmp = php_trim(Z_STR_P(tmpzval), NULL, 0, 3); } - if (tmp && tmp[0] != '\0') { + if (tmp && tmp->len) { char *s; + char *t; - user_headers = estrdup(tmp); + user_headers = estrndup(tmp->val, tmp->len); + + if (IS_INTERNED(tmp)) { + tmp = zend_string_init(tmp->val, tmp->len, 0); + } else if (GC_REFCOUNT(tmp) > 1) { + GC_REFCOUNT(tmp)--; + tmp = zend_string_init(tmp->val, tmp->len, 0); + } /* Make lowercase for easy comparison against 'standard' headers */ - php_strtolower(tmp, strlen(tmp)); + php_strtolower(tmp->val, tmp->len); + t = tmp->val; if (!header_init) { /* strip POST headers on redirect */ - strip_header(user_headers, tmp, "content-length:"); - strip_header(user_headers, tmp, "content-type:"); + strip_header(user_headers, t, "content-length:"); + strip_header(user_headers, t, "content-type:"); } - if ((s = strstr(tmp, "user-agent:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "user-agent:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_USER_AGENT; } - if ((s = strstr(tmp, "host:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "host:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_HOST; } - if ((s = strstr(tmp, "from:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "from:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_FROM; } - if ((s = strstr(tmp, "authorization:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "authorization:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_AUTH; } - if ((s = strstr(tmp, "content-length:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "content-length:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_CONTENT_LENGTH; } - if ((s = strstr(tmp, "content-type:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "content-type:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_TYPE; } - if ((s = strstr(tmp, "connection:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if ((s = strstr(t, "connection:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_CONNECTION; } /* remove Proxy-Authorization header */ - if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) && - (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + if (use_proxy && use_ssl && (s = strstr(t, "proxy-authorization:")) && + (s == t || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { char *p = s + sizeof("proxy-authorization:") - 1; - while (s > tmp && (*(s-1) == ' ' || *(s-1) == '\t')) s--; + while (s > t && (*(s-1) == ' ' || *(s-1) == '\t')) s--; while (*p != 0 && *p != '\r' && *p != '\n') p++; while (*p == '\r' || *p == '\n') p++; if (*p == 0) { - if (s == tmp) { + if (s == t) { efree(user_headers); user_headers = NULL; } else { - while (s > tmp && (*(s-1) == '\r' || *(s-1) == '\n')) s--; - user_headers[s - tmp] = 0; + while (s > t && (*(s-1) == '\r' || *(s-1) == '\n')) s--; + user_headers[s - t] = 0; } } else { - memmove(user_headers + (s - tmp), user_headers + (p - tmp), strlen(p) + 1); + memmove(user_headers + (s - t), user_headers + (p - t), strlen(p) + 1); } } } if (tmp) { - efree(tmp); + zend_string_release(tmp); } } diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 69b80e7baae..e752c042fea 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -100,16 +100,16 @@ PHP_FUNCTION(ezmlm_hash) Send an email message */ PHP_FUNCTION(mail) { - char *to=NULL, *message=NULL, *headers=NULL, *headers_trimmed=NULL; + char *to=NULL, *message=NULL; char *subject=NULL; - zend_string *extra_cmd=NULL; - size_t to_len, message_len, headers_len = 0; + zend_string *extra_cmd=NULL, *headers=NULL, *headers_trimmed=NULL; + size_t to_len, message_len; size_t subject_len, i; char *force_extra_parameters = INI_STR("mail.force_extra_parameters"); char *to_r, *subject_r; char *p, *e; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|sS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &headers_len, &extra_cmd) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|SS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &extra_cmd) == FAILURE) { return; } @@ -118,8 +118,8 @@ PHP_FUNCTION(mail) MAIL_ASCIIZ_CHECK(subject, subject_len); MAIL_ASCIIZ_CHECK(message, message_len); if (headers) { - MAIL_ASCIIZ_CHECK(headers, headers_len); - headers_trimmed = php_trim(headers, headers_len, NULL, 0, NULL, 2); + MAIL_ASCIIZ_CHECK(headers->val, headers->len); + headers_trimmed = php_trim(headers, NULL, 0, 2); } if (extra_cmd) { MAIL_ASCIIZ_CHECK(extra_cmd->val, extra_cmd->len); @@ -171,14 +171,14 @@ PHP_FUNCTION(mail) extra_cmd = php_escape_shell_cmd(extra_cmd->val); } - if (php_mail(to_r, subject_r, message, headers_trimmed, extra_cmd ? extra_cmd->val : NULL)) { + if (php_mail(to_r, subject_r, message, headers_trimmed ? headers_trimmed->val : NULL, extra_cmd ? extra_cmd->val : NULL)) { RETVAL_TRUE; } else { RETVAL_FALSE; } if (headers_trimmed) { - efree(headers_trimmed); + zend_string_release(headers_trimmed); } if (extra_cmd) { diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index c79bfb20fe5..8e0ad5c97a0 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -132,7 +132,7 @@ PHPAPI zend_string *php_str_to_str_ex(char *haystack, size_t length, char *needl size_t needle_len, char *str, size_t str_len, int case_sensitivity, size_t *replace_count); 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 char *php_trim(char *c, size_t len, char *what, size_t what_len, zval *return_value, 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_ex(char *rbuf, size_t len, int *stateptr, char *allow, size_t allow_len, zend_bool allow_tag_spaces); PHPAPI size_t php_char_to_str_ex(char *str, size_t len, char from, char *to, size_t to_len, zval *result, int case_sensitivity, size_t *replace_count); diff --git a/ext/standard/string.c b/ext/standard/string.c index 2668161c09d..e275e6456ce 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -788,48 +788,73 @@ static inline int php_charmask(unsigned char *input, size_t len, char *mask) * mode 3 : trim left and right * what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0') */ -PHPAPI char *php_trim(char *c, size_t len, char *what, size_t what_len, zval *return_value, int mode) +PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode) { + const char *c = str->val; + size_t len = str->len; register size_t i; size_t trimmed = 0; char mask[256]; if (what) { php_charmask((unsigned char*)what, what_len, mask); - } else { - php_charmask((unsigned char*)" \n\r\t\v\0", 6, mask); - } - if (mode & 1) { - for (i = 0; i < len; i++) { - if (mask[(unsigned char)c[i]]) { - trimmed++; - } else { - break; - } - } - len -= trimmed; - c += trimmed; - } - if (mode & 2) { - if (len > 0) { - i = len - 1; - do { + if (mode & 1) { + for (i = 0; i < len; i++) { if (mask[(unsigned char)c[i]]) { - len--; + trimmed++; } else { break; } - } while (i-- != 0); + } + len -= trimmed; + c += trimmed; + } + if (mode & 2) { + if (len > 0) { + i = len - 1; + do { + if (mask[(unsigned char)c[i]]) { + len--; + } else { + break; + } + } while (i-- != 0); + } + } + } else { + if (mode & 1) { + for (i = 0; i < len; i++) { + if ((unsigned char)c[i] <= ' ' && + (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) { + trimmed++; + } else { + break; + } + } + len -= trimmed; + c += trimmed; + } + if (mode & 2) { + if (len > 0) { + i = len - 1; + do { + if ((unsigned char)c[i] <= ' ' && + (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) { + len--; + } else { + break; + } + } while (i-- != 0); + } } } - if (return_value) { - RETVAL_STRINGL(c, len); + if (str->len == len) { + return zend_string_copy(str); } else { - return estrndup(c, len); + return zend_string_init(c, len, 0); } - return ""; } /* }}} */ @@ -853,7 +878,7 @@ static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode) ZEND_PARSE_PARAMETERS_END(); #endif - php_trim(str->val, str->len, (what ? what->val : NULL), (what ? what->len : 0), return_value, mode); + ZVAL_STR(return_value, php_trim(str, (what ? what->val : NULL), (what ? what->len : 0), mode)); } /* }}} */