diff options
Diffstat (limited to 'ext/pcre/php_pcre.c')
| -rw-r--r-- | ext/pcre/php_pcre.c | 39 | 
1 files changed, 18 insertions, 21 deletions
| diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 4a0afe1f89..8c7bf18b55 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -22,6 +22,7 @@  #include "php_globals.h"  #include "php_pcre.h"  #include "ext/standard/info.h" +#include "ext/standard/php_smart_str.h"  #if HAVE_PCRE || HAVE_BUNDLED_PCRE @@ -584,37 +585,36 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,  						int *offsets, int count, char **result)  {  	zval		 retval;			/* Return value from evaluation */ -	char		 backref_buf[4],	/* Buffer for string version of backref */ -				*code,				/* PHP code string */ -				*new_code,			/* Code as result of substitution */ +	char		*eval_str_end,		/* End of eval string */  				*match,				/* Current match for a backref */  				*esc_match,			/* Quote-escaped match */  				*walk,				/* Used to walk the code string */ +				*segment,			/* Start of segment to append while walking */  				 walk_last;			/* Last walked character */ -	int			 code_len;			/* Length of the code string */ -	int			 new_code_len;		/* Length of the substituted code string */  	int			 match_len;			/* Length of the match */  	int			 esc_match_len;		/* Length of the quote-escaped match */  	int			 result_len;		/* Length of the result of the evaluation */  	int			 backref;			/* Current backref */  	char        *compiled_string_description; +	smart_str    code = {0};  	CLS_FETCH();  	ELS_FETCH(); -	/* Save string to be evaluated, since we will be modifying it */ -	code = estrndup(eval_str, eval_str_len); -	walk = code; -	new_code_len = code_len = eval_str_len; +	eval_str_end = eval_str + eval_str_len; +	walk = segment = eval_str;  	walk_last = 0; -	while (*walk) { +	while (walk < eval_str_end) {  		/* If found a backreference.. */  		if ('\\' == *walk || '$' == *walk) { +			smart_str_appendl(&code, segment, walk - segment);  		  	if (walk_last == '\\') { -				memmove(walk-1, walk, code_len - (walk - code) + 1); +				code.c[code.len-1] = *walk++; +				segment = walk;  				walk_last = 0;  				continue;  			} +			segment = walk;  			if (preg_get_backref(walk+1, &backref)) {  				if (backref < count) {  					/* Find the corresponding string match and substitute it @@ -632,30 +632,27 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,  					esc_match_len = 0;  					match_len = 0;  				} -				sprintf(backref_buf, "%c%d", *walk, backref); -				new_code = php_str_to_str(code, code_len, -										  backref_buf, (backref > 9) ? 3 : 2, -										  esc_match, esc_match_len, &new_code_len); +				smart_str_appendl(&code, esc_match, esc_match_len);  				/* Adjust the walk pointer */ -				walk = new_code + (walk - code) + match_len; +				walk += (backref > 9 ? 3 : 2); +				segment = walk;  				/* Clean up and reassign */  				if (esc_match_len)  					efree(esc_match); -				efree(code); -				code = new_code; -				code_len = new_code_len;  				continue;  			}  		}  		walk++;  		walk_last = walk[-1];  	} +	smart_str_appendl(&code, segment, walk - segment); +	smart_str_0(&code);  	compiled_string_description = zend_make_compiled_string_description("regexp code");  	/* Run the code */ -	if (zend_eval_string(code, &retval, compiled_string_description CLS_CC ELS_CC) == FAILURE) { +	if (zend_eval_string(code.c, &retval, compiled_string_description CLS_CC ELS_CC) == FAILURE) {  		efree(compiled_string_description);  		zend_error(E_ERROR, "Failed evaluating code:\n%s\n", code);  		/* zend_error() does not return in this case */ @@ -669,7 +666,7 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,  	/* Clean up */  	zval_dtor(&retval); -	efree(code); +	smart_str_free(&code);  	return result_len;  } | 
