From 479b82c0d4c4c0cf3f3ccb4333ba9f2d8df65edd Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 17:26:09 +0800 Subject: [PATCH 1/9] Fixed invalid write in vsprintf tests --- Zend/zend_execute_API.c | 4 ++-- ext/standard/formatted_print.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 26791c357bf..0bb4c6f0a30 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -251,14 +251,14 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ * so that if handler used some class, crash would not happen */ if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { zeh = &EG(user_error_handler); - ZVAL_UNDEF(&EG(user_error_handler)); zval_ptr_dtor(zeh); + ZVAL_UNDEF(&EG(user_error_handler)); } if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zeh = &EG(user_exception_handler); - ZVAL_UNDEF(&EG(user_exception_handler)); zval_ptr_dtor(zeh); + ZVAL_UNDEF(&EG(user_exception_handler)); } zend_stack_destroy(&EG(user_error_handlers_error_reporting)); diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index 6317c8214cd..b8724dea55d 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -395,9 +395,7 @@ php_formatted_print(int param_count, int use_array, int format_offset TSRMLS_DC) zval array; z_format = &args[format_offset]; - ZVAL_COPY_VALUE(&array, &args[1 + format_offset]); - - SEPARATE_ZVAL(&array); + ZVAL_DUP(&array, &args[1 + format_offset]); convert_to_array_ex(&array); argc = 1 + zend_hash_num_elements(Z_ARRVAL(array)); @@ -411,6 +409,7 @@ php_formatted_print(int param_count, int use_array, int format_offset TSRMLS_DC) i++; } efree(args); + zval_dtor(&array); args = newargs; format_offset = 0; } From e687939f01bfed685534b23aed5d78a8e20ce18e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 17:30:39 +0800 Subject: [PATCH 2/9] Fixed wrong array to string convertion --- Zend/zend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend.c b/Zend/zend.c index 485c6a38803..532cdf35e2d 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -248,7 +248,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop case IS_ARRAY: zend_error(E_NOTICE, "Array to string conversion"); // TODO: ??? use interned string - Z_STR_P(expr_copy) = STR_INIT("Array", 1, 0); + Z_STR_P(expr_copy) = STR_INIT("Array", sizeof("Array") - 1, 0); break; case IS_OBJECT: { From a9529b8ad3becd738787211d649fd96cb80f2885 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 17:35:47 +0800 Subject: [PATCH 3/9] Refactor chunk_split returning zend_string to avoid memleak --- ext/standard/string.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index cfbcfa8a213..de069167089 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2105,33 +2105,33 @@ PHP_FUNCTION(strrchr) /* {{{ php_chunk_split */ -static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen, int *destlen) +static zend_string *php_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen) { - char *dest; char *p, *q; int chunks; /* complete chunks! */ int restlen; int out_len; + zend_string *dest; chunks = srclen / chunklen; restlen = srclen - chunks * chunklen; /* srclen % chunklen */ - if(chunks > INT_MAX - 1) { + if (chunks > INT_MAX - 1) { return NULL; } out_len = chunks + 1; - if(endlen !=0 && out_len > INT_MAX/endlen) { + if (endlen !=0 && out_len > INT_MAX/endlen) { return NULL; } out_len *= endlen; - if(out_len > INT_MAX - srclen - 1) { + if (out_len > INT_MAX - srclen - 1) { return NULL; } out_len += srclen + 1; - dest = safe_emalloc((int)out_len, sizeof(char), 0); + dest = STR_ALLOC(out_len * sizeof(char), 0); - for (p = src, q = dest; p < (src + srclen - chunklen + 1); ) { + for (p = src, q = dest->val; p < (src + srclen - chunklen + 1); ) { memcpy(q, p, chunklen); q += chunklen; memcpy(q, end, endlen); @@ -2147,11 +2147,9 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c } *q = '\0'; - if (destlen) { - *destlen = q - dest; - } + dest->len = q - dest->val; - return(dest); + return dest; } /* }}} */ @@ -2160,12 +2158,11 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c PHP_FUNCTION(chunk_split) { char *str; - char *result; char *end = "\r\n"; int endlen = 2; long chunklen = 76; - int result_len; int str_len; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len, &chunklen, &end, &endlen) == FAILURE) { return; @@ -2178,24 +2175,21 @@ PHP_FUNCTION(chunk_split) if (chunklen > str_len) { /* to maintain BC, we must return original string + ending */ - result_len = endlen + str_len; - result = emalloc(result_len + 1); - memcpy(result, str, str_len); - memcpy(result + str_len, end, endlen); - result[result_len] = '\0'; -//??? RETURN_STRINGL(result, result_len, 0); - RETURN_STRINGL(result, result_len); + result = STR_ALLOC(endlen + str_len, 0); + memcpy(result->val, str, str_len); + memcpy(result->val + str_len, end, endlen); + result->val[result->len] = '\0'; + RETURN_STR(result); } if (!str_len) { RETURN_EMPTY_STRING(); } - result = php_chunk_split(str, str_len, end, endlen, chunklen, &result_len); + result = php_chunk_split(str, str_len, end, endlen, chunklen); if (result) { -//??? RETURN_STRINGL(result, result_len, 0); - RETURN_STRINGL(result, result_len); + RETURN_STR(result); } else { RETURN_FALSE; } From b5291556352ecd7a3675cbdfb133e0f7f49984a1 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 17:40:18 +0800 Subject: [PATCH 4/9] Fixed memory leak in nlbr --- ext/standard/string.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index de069167089..40618f8e047 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4164,12 +4164,12 @@ PHP_FUNCTION(hebrevc) PHP_FUNCTION(nl2br) { /* in brief this inserts
or
before matched regexp \n\r?|\r\n? */ - char *tmp, *str; - int new_length; - char *end, *target; + char *tmp, *str; + char *end, *target; int repl_cnt = 0; int str_len; zend_bool is_xhtml = 1; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &is_xhtml) == FAILURE) { return; @@ -4203,8 +4203,8 @@ PHP_FUNCTION(nl2br) { size_t repl_len = is_xhtml ? (sizeof("
") - 1) : (sizeof("
") - 1); - new_length = str_len + repl_cnt * repl_len; - tmp = target = safe_emalloc(repl_cnt, repl_len, str_len + 1); + result = STR_ALLOC(repl_cnt * repl_len + str_len, 0); + target = result->val; } while (str < end) { @@ -4235,8 +4235,7 @@ PHP_FUNCTION(nl2br) *target = '\0'; -//??? RETURN_STRINGL(tmp, new_length, 0); - RETURN_STRINGL(tmp, new_length); + RETURN_STR(result); } /* }}} */ From 9e9f6c7123599a022a9acfeb52d0ad2152200827 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 17:44:42 +0800 Subject: [PATCH 5/9] Fixed memory leak in str_pad --- ext/standard/string.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 40618f8e047..1e8e55be934 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5158,13 +5158,12 @@ PHP_FUNCTION(str_pad) long pad_length; /* Length to pad to */ /* Helper variables */ - size_t num_pad_chars; /* Number of padding characters (total - input size) */ - char *result = NULL; /* Resulting string */ - int result_len = 0; /* Length of the resulting string */ + size_t num_pad_chars; /* Number of padding characters (total - input size) */ char *pad_str_val = " "; /* Pointer to padding string */ int pad_str_len = 1; /* Length of the padding string */ long pad_type_val = STR_PAD_RIGHT; /* The padding type value */ int i, left_pad=0, right_pad=0; + zend_string *result = NULL; /* Resulting string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sl", &input, &input_len, &pad_length, &pad_str_val, &pad_str_len, &pad_type_val) == FAILURE) { @@ -5192,7 +5191,9 @@ PHP_FUNCTION(str_pad) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding length is too long"); return; } - result = (char *)emalloc(input_len + num_pad_chars + 1); + + result = STR_ALLOC(input_len + num_pad_chars, 0); + result->len = 0; /* We need to figure out the left/right padding lengths. */ switch (pad_type_val) { @@ -5214,20 +5215,19 @@ PHP_FUNCTION(str_pad) /* First we pad on the left. */ for (i = 0; i < left_pad; i++) - result[result_len++] = pad_str_val[i % pad_str_len]; + result->val[result->len++] = pad_str_val[i % pad_str_len]; /* Then we copy the input string. */ - memcpy(result + result_len, input, input_len); - result_len += input_len; + memcpy(result->val + result->len, input, input_len); + result->len += input_len; /* Finally, we pad on the right. */ for (i = 0; i < right_pad; i++) - result[result_len++] = pad_str_val[i % pad_str_len]; + result->val[result->len++] = pad_str_val[i % pad_str_len]; - result[result_len] = '\0'; + result->val[result->len] = '\0'; -//??? RETURN_STRINGL(result, result_len, 0); - RETURN_STRINGL(result, result_len); + RETURN_STR(result); } /* }}} */ From 5adeaa147d273e9adcde44c7dbc06b44a9f1d845 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 18:12:30 +0800 Subject: [PATCH 6/9] Refactoring php_stream_copy_to_mem to return zend_string --- ext/phar/phar.c | 11 ++++++---- ext/standard/exec.c | 10 ++++----- ext/standard/file.c | 27 ++++++++++------------- ext/standard/streamsfuncs.c | 12 +++-------- main/php_streams.h | 9 ++++---- main/streams/streams.c | 43 +++++++++++++++++++++---------------- 6 files changed, 53 insertions(+), 59 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 867c664171b..a23c1b89c23 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2604,6 +2604,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, } if (user_stub) { + zend_string *suser_stub; if (len < 0) { /* resource passed in */ if (!(php_stream_from_zval_no_verify(stubfile, (zval **)user_stub))) { @@ -2623,7 +2624,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, } user_stub = 0; - if (!(len = php_stream_copy_to_mem(stubfile, &user_stub, len, 0)) || !user_stub) { + if (!(suser_stub = php_stream_copy_to_mem(stubfile, len, 0))) { if (closeoldfile) { php_stream_close(oldfile); } @@ -2634,6 +2635,8 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, return EOF; } free_user_stub = 1; + user_stub = suser_stub->val; + len = suser_stub->len; } else { free_user_stub = 0; } @@ -2648,7 +2651,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, spprintf(error, 0, "illegal stub for phar \"%s\"", phar->fname); } if (free_user_stub) { - efree(user_stub); + STR_FREE(suser_stub); } return EOF; } @@ -2665,13 +2668,13 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, spprintf(error, 0, "unable to create stub from string in new phar \"%s\"", phar->fname); } if (free_user_stub) { - efree(user_stub); + STR_FREE(suser_stub); } return EOF; } phar->halt_offset = len + 5; if (free_user_stub) { - efree(user_stub); + STR_FREE(suser_stub); } } else { size_t written; diff --git a/ext/standard/exec.c b/ext/standard/exec.c index 8bb8fefba5f..7c440bf7919 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -438,10 +438,9 @@ PHP_FUNCTION(escapeshellarg) PHP_FUNCTION(shell_exec) { FILE *in; - size_t total_readbytes; char *command; int command_len; - char *ret; + zend_string *ret; php_stream *stream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &command, &command_len) == FAILURE) { @@ -458,12 +457,11 @@ PHP_FUNCTION(shell_exec) } stream = php_stream_fopen_from_pipe(in, "rb"); - total_readbytes = php_stream_copy_to_mem(stream, &ret, PHP_STREAM_COPY_ALL, 0); + ret = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0); php_stream_close(stream); - if (total_readbytes > 0) { -//??? RETVAL_STRINGL(ret, total_readbytes, 0); - RETVAL_STRINGL(ret, total_readbytes); + if (ret->len > 0) { + RETVAL_STR(ret); } } /* }}} */ diff --git a/ext/standard/file.c b/ext/standard/file.c index 5004b119c6c..c4327fab4e6 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -520,14 +520,13 @@ PHP_FUNCTION(file_get_contents) { char *filename; int filename_len; - char *contents; zend_bool use_include_path = 0; php_stream *stream; - int len; long offset = -1; long maxlen = PHP_STREAM_COPY_ALL; zval *zcontext = NULL; php_stream_context *context = NULL; + zend_string *contents; /* Parse arguments */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) { @@ -554,12 +553,8 @@ PHP_FUNCTION(file_get_contents) RETURN_FALSE; } - if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) { -//??? RETVAL_STRINGL(contents, len, 0); - RETVAL_STRINGL(contents, len); - efree(contents); - } else if (len == 0) { - RETVAL_EMPTY_STRING(); + if ((contents = php_stream_copy_to_mem(stream, maxlen, 0)) != NULL) { + RETVAL_STR(contents); } else { RETVAL_FALSE; } @@ -715,9 +710,8 @@ PHP_FUNCTION(file) { char *filename; int filename_len; - char *target_buf=NULL, *p, *s, *e; + char *p, *s, *e; register int i = 0; - int target_len; char eol_marker = '\n'; long flags = 0; zend_bool use_include_path; @@ -726,6 +720,7 @@ PHP_FUNCTION(file) php_stream *stream; zval *zcontext = NULL; php_stream_context *context = NULL; + zend_string *target_buf; /* Parse arguments */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) { @@ -750,11 +745,11 @@ PHP_FUNCTION(file) /* Initialize return array */ array_init(return_value); - if ((target_len = php_stream_copy_to_mem(stream, &target_buf, PHP_STREAM_COPY_ALL, 0))) { - s = target_buf; - e = target_buf + target_len; + if ((target_buf = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) { + s = target_buf->val; + e = target_buf->val + target_buf->len; - if (!(p = (char*)php_stream_locate_eol(stream, target_buf, target_len TSRMLS_CC))) { + if (!(p = (char*)php_stream_locate_eol(stream, target_buf TSRMLS_CC))) { p = e; goto parse_eol; } @@ -775,7 +770,7 @@ parse_eol: } else { do { int windows_eol = 0; - if (p != target_buf && eol_marker == '\n' && *(p - 1) == '\r') { + if (p != target_buf->val && eol_marker == '\n' && *(p - 1) == '\r') { windows_eol++; } if (skip_blank_lines && !(p-s-windows_eol)) { @@ -795,7 +790,7 @@ parse_eol: } if (target_buf) { - efree(target_buf); + STR_FREE(target_buf); } php_stream_close(stream); } diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index b5608f450d2..32f24c4df0b 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -412,8 +412,7 @@ PHP_FUNCTION(stream_get_contents) zval *zsrc; long maxlen = PHP_STREAM_COPY_ALL, desiredpos = -1L; - int len; - char *contents = NULL; + zend_string *contents; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ll", &zsrc, &maxlen, &desiredpos) == FAILURE) { RETURN_FALSE; @@ -441,14 +440,9 @@ PHP_FUNCTION(stream_get_contents) } } - len = php_stream_copy_to_mem(stream, &contents, maxlen, 0); + contents = php_stream_copy_to_mem(stream, maxlen, 0); - if (contents) { -//??? RETVAL_STRINGL(contents, len, 0); - RETVAL_STRINGL(contents, len); - } else { - RETVAL_EMPTY_STRING(); - } + RETURN_STR(contents); } /* }}} */ diff --git a/main/php_streams.h b/main/php_streams.h index f434e6db75c..ad16d4b74f7 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -61,7 +61,7 @@ END_EXTERN_C() * the ultimate ancestor, which is useful, because there can be several layers of calls */ #define php_stream_alloc_rel(ops, thisptr, persistent, mode) _php_stream_alloc((ops), (thisptr), (persistent), (mode) STREAMS_REL_CC TSRMLS_CC) -#define php_stream_copy_to_mem_rel(src, buf, maxlen, persistent) _php_stream_copy_to_mem((src), (buf), (maxlen), (persistent) STREAMS_REL_CC TSRMLS_CC) +#define php_stream_copy_to_mem_rel(src, maxlen, persistent) _php_stream_copy_to_mem((src), (buf), (maxlen), (persistent) STREAMS_REL_CC TSRMLS_CC) #define php_stream_fopen_rel(filename, mode, opened, options) _php_stream_fopen((filename), (mode), (opened), (options) STREAMS_REL_CC TSRMLS_CC) @@ -440,9 +440,8 @@ PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size /* read all data from stream and put into a buffer. Caller must free buffer * when done. */ -PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen, - int persistent STREAMS_DC TSRMLS_DC); -#define php_stream_copy_to_mem(src, buf, maxlen, persistent) _php_stream_copy_to_mem((src), (buf), (maxlen), (persistent) STREAMS_CC TSRMLS_CC) +PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int persistent STREAMS_DC TSRMLS_DC); +#define php_stream_copy_to_mem(src, maxlen, persistent) _php_stream_copy_to_mem((src), (maxlen), (persistent) STREAMS_CC TSRMLS_CC) /* output all data from a stream */ PHPAPI size_t _php_stream_passthru(php_stream * src STREAMS_DC TSRMLS_DC); @@ -546,7 +545,7 @@ PHPAPI int php_register_url_stream_wrapper_volatile(const char *protocol, php_st PHPAPI int php_unregister_url_stream_wrapper_volatile(const char *protocol TSRMLS_DC); PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const char **path_for_open, int options TSRMLS_DC); -PHPAPI const char *php_stream_locate_eol(php_stream *stream, const char *buf, size_t buf_len TSRMLS_DC); +PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf TSRMLS_DC); #define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC TSRMLS_CC) #define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC TSRMLS_CC) diff --git a/main/streams/streams.c b/main/streams/streams.c index fe592c5e9b0..e80a87c860e 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -833,7 +833,7 @@ PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_D return (stream->ops->stat)(stream, ssb TSRMLS_CC); } -PHPAPI const char *php_stream_locate_eol(php_stream *stream, const char *buf, size_t buf_len TSRMLS_DC) +PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf TSRMLS_DC) { size_t avail; const char *cr, *lf, *eol = NULL; @@ -843,8 +843,8 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, const char *buf, si readptr = (char*)stream->readbuf + stream->readpos; avail = stream->writepos - stream->readpos; } else { - readptr = buf; - avail = buf_len; + readptr = buf->val; + avail = buf->len; } /* Look for EOL */ @@ -913,7 +913,7 @@ PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen, int done = 0; readptr = (char*)stream->readbuf + stream->readpos; - eol = php_stream_locate_eol(stream, NULL, 0 TSRMLS_CC); + eol = php_stream_locate_eol(stream, NULL TSRMLS_CC); if (eol) { cpysz = eol - readptr + 1; @@ -1411,7 +1411,7 @@ PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC) } -PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen, int persistent STREAMS_DC TSRMLS_DC) +PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int persistent STREAMS_DC TSRMLS_DC) { size_t ret = 0; char *ptr; @@ -1419,9 +1419,10 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen int step = CHUNK_SIZE; int min_room = CHUNK_SIZE / 4; php_stream_statbuf ssbuf; + zend_string *result; if (maxlen == 0) { - return 0; + return STR_EMPTY_ALLOC(); } if (maxlen == PHP_STREAM_COPY_ALL) { @@ -1429,7 +1430,8 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen } if (maxlen > 0) { - ptr = *buf = pemalloc_rel_orig(maxlen + 1, persistent); + result = STR_ALLOC(maxlen, persistent); + ptr = result->val; while ((len < maxlen) && !php_stream_eof(src)) { ret = php_stream_read(src, ptr, maxlen - len); if (!ret) { @@ -1440,11 +1442,12 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen } if (len) { *ptr = '\0'; + result->len = len; } else { - pefree(*buf, persistent); - *buf = NULL; + STR_FREE(result); + result = NULL; } - return len; + return result; } /* avoid many reallocs by allocating a good sized chunk to begin with, if @@ -1459,26 +1462,28 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen max_len = step; } - ptr = *buf = pemalloc_rel_orig(max_len, persistent); + result = STR_ALLOC(max_len, persistent); + ptr = result->val; - while((ret = php_stream_read(src, ptr, max_len - len))) { + while ((ret = php_stream_read(src, ptr, max_len - len))) { len += ret; if (len + min_room >= max_len) { - *buf = perealloc_rel_orig(*buf, max_len + step, persistent); + result = STR_REALLOC(result, max_len + step, persistent); max_len += step; - ptr = *buf + len; + ptr = result->val + len; } else { ptr += ret; } } if (len) { - *buf = perealloc_rel_orig(*buf, len + 1, persistent); - (*buf)[len] = '\0'; + result = STR_REALLOC(result, len, persistent); + result->val[len] = '\0'; } else { - pefree(*buf, persistent); - *buf = NULL; + STR_FREE(result); + result = NULL; } - return len; + + return result; } /* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */ From 57a3feb4225566ed9dda92d0e1e5c08c11a3448f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 18:15:40 +0800 Subject: [PATCH 7/9] Fixed memory leak in strrev --- ext/standard/string.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 1e8e55be934..be4d874b067 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3121,15 +3121,16 @@ PHP_FUNCTION(strtr) PHP_FUNCTION(strrev) { char *str; - char *e, *n, *p; + char *e, *p; int str_len; + zend_string *n; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { return; } - n = emalloc(str_len+1); - p = n; + n = STR_ALLOC(str_len, 0); + p = n->val; e = str + str_len; @@ -3139,8 +3140,7 @@ PHP_FUNCTION(strrev) *p = '\0'; -//??? RETVAL_STRINGL(n, str_len, 0); - RETVAL_STRINGL(n, str_len); + RETVAL_STR(n); } /* }}} */ From 1e5a4f281d21abab8101301ea155f9c0394ab02f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 18:32:09 +0800 Subject: [PATCH 8/9] Refactor php_uu(en/de)code to returning zend_string --- ext/standard/php_uuencode.h | 4 ++-- ext/standard/string.c | 16 ++++++------- ext/standard/uuencode.c | 47 ++++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/ext/standard/php_uuencode.h b/ext/standard/php_uuencode.h index 5b2b8526060..fedfe660e99 100644 --- a/ext/standard/php_uuencode.h +++ b/ext/standard/php_uuencode.h @@ -24,8 +24,8 @@ PHP_FUNCTION(convert_uudecode); PHP_FUNCTION(convert_uuencode); -PHPAPI int php_uudecode(char *src, int src_len, char **dest); -PHPAPI int php_uuencode(char *src, int src_len, char **dest); +PHPAPI zend_string *php_uudecode(char *src, int src_len); +PHPAPI zend_string *php_uuencode(char *src, int src_len); #endif /* PHP_UUENCODE_H */ diff --git a/ext/standard/string.c b/ext/standard/string.c index be4d874b067..af3c192f10b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1344,15 +1344,15 @@ PHP_FUNCTION(strtoupper) { char *arg; int arglen; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arglen) == FAILURE) { return; } - arg = estrndup(arg, arglen); - php_strtoupper(arg, arglen); -//??? RETURN_STRINGL(arg, arglen, 0); - RETURN_STRINGL(arg, arglen); + result = STR_INIT(arg, arglen, 0); + php_strtoupper(result->val, result->len); + RETURN_STR(result); } /* }}} */ @@ -1379,15 +1379,15 @@ PHP_FUNCTION(strtolower) { char *str; int arglen; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &arglen) == FAILURE) { return; } - str = estrndup(str, arglen); - php_strtolower(str, arglen); -//??? RETURN_STRINGL(str, arglen, 0); - RETURN_STRINGL(str, arglen); + result = STR_INIT(str, arglen, 0); + php_strtolower(result->val, result->len); + RETURN_STR(result); } /* }}} */ diff --git a/ext/standard/uuencode.c b/ext/standard/uuencode.c index c12c27ec65a..2a1de6ed464 100644 --- a/ext/standard/uuencode.c +++ b/ext/standard/uuencode.c @@ -65,13 +65,15 @@ #define PHP_UU_DEC(c) (((c) - ' ') & 077) -PHPAPI int php_uuencode(char *src, int src_len, char **dest) /* {{{ */ +PHPAPI zend_string *php_uuencode(char *src, int src_len) /* {{{ */ { int len = 45; char *p, *s, *e, *ee; + zend_string *dest; /* encoded length is ~ 38% greater than the original */ - p = *dest = safe_emalloc((size_t) ceil(src_len * 1.38), 1, 46); + dest = STR_ALLOC((size_t)ceil(src_len * 1.38) + 46, 0); + p = dest->val; s = src; e = src + src_len; @@ -120,16 +122,19 @@ PHPAPI int php_uuencode(char *src, int src_len, char **dest) /* {{{ */ *p++ = '\n'; *p = '\0'; - return (p - *dest); + dest = STR_REALLOC(dest, p - dest->val, 0); + return dest; } /* }}} */ -PHPAPI int php_uudecode(char *src, int src_len, char **dest) /* {{{ */ +PHPAPI zend_string *php_uudecode(char *src, int src_len) /* {{{ */ { int len, total_len=0; char *s, *e, *p, *ee; + zend_string *dest; - p = *dest = safe_emalloc((size_t) ceil(src_len * 0.75), 1, 1); + dest = STR_ALLOC((size_t) ceil(src_len * 0.75), 0); + p = dest->val; s = src; e = src + src_len; @@ -165,7 +170,7 @@ PHPAPI int php_uudecode(char *src, int src_len, char **dest) /* {{{ */ s++; } - if ((len = total_len > (p - *dest))) { + if ((len = total_len > (p - dest->val))) { *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4; if (len > 1) { *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2; @@ -175,13 +180,15 @@ PHPAPI int php_uudecode(char *src, int src_len, char **dest) /* {{{ */ } } - *(*dest + total_len) = '\0'; + dest->len = total_len; + dest->val[dest->len] = '\0'; - return total_len; + return dest; err: - efree(*dest); - return -1; + STR_FREE(dest); + + return NULL; } /* }}} */ @@ -189,17 +196,14 @@ err: uuencode a string */ PHP_FUNCTION(convert_uuencode) { - char *src, *dst; - int src_len, dst_len; + char *src; + int src_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &src, &src_len) == FAILURE || src_len < 1) { RETURN_FALSE; } - dst_len = php_uuencode(src, src_len, &dst); - -//??? RETURN_STRINGL(dst, dst_len, 0); - RETURN_STRINGL(dst, dst_len); + RETURN_STR(php_uuencode(src, src_len)); } /* }}} */ @@ -207,21 +211,20 @@ PHP_FUNCTION(convert_uuencode) decode a uuencoded string */ PHP_FUNCTION(convert_uudecode) { - char *src, *dst; - int src_len, dst_len; + char *src; + int src_len; + zend_string *dest; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &src, &src_len) == FAILURE || src_len < 1) { RETURN_FALSE; } - dst_len = php_uudecode(src, src_len, &dst); - if (dst_len < 0) { + if ((dest = php_uudecode(src, src_len)) == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The given parameter is not a valid uuencoded string"); RETURN_FALSE; } -//??? RETURN_STRINGL(dst, dst_len, 0); - RETURN_STRINGL(dst, dst_len); + RETURN_STR(dest); } /* }}} */ From 93428dc6b902f23e56bf01e87c63ea0d6d6c03a4 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 24 Feb 2014 18:48:22 +0800 Subject: [PATCH 9/9] Refactor base64 to returning zend_string --- ext/standard/base64.c | 72 ++++++++++++++----------------- ext/standard/base64.h | 6 +-- ext/standard/http_fopen_wrapper.c | 8 ++-- ext/standard/password.c | 19 ++++---- main/main.c | 13 +++--- 5 files changed, 55 insertions(+), 63 deletions(-) diff --git a/ext/standard/base64.c b/ext/standard/base64.c index bcc2fa6b84a..3bc96267b29 100644 --- a/ext/standard/base64.c +++ b/ext/standard/base64.c @@ -53,21 +53,18 @@ static const short base64_reverse_table[256] = { }; /* }}} */ -PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, int *ret_length) /* {{{ */ +PHPAPI zend_string *php_base64_encode(const unsigned char *str, int length) /* {{{ */ { const unsigned char *current = str; unsigned char *p; - unsigned char *result; + zend_string *result; if (length < 0) { - if (ret_length != NULL) { - *ret_length = 0; - } return NULL; } - result = (unsigned char *) safe_emalloc((length + 2) / 3, 4 * sizeof(char), 1); - p = result; + result = STR_ALLOC(((length + 2) / 3) * 4 * sizeof(char), 0); + p = (unsigned char *)result->val; while (length > 2) { /* keep going until we have less than 24 bits */ *p++ = base64_table[current[0] >> 2]; @@ -92,10 +89,10 @@ PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, in *p++ = base64_pad; } } - if (ret_length != NULL) { - *ret_length = (int)(p - result); - } *p = '\0'; + + result->len = (p - (unsigned char *)result->val); + return result; } /* }}} */ @@ -134,20 +131,20 @@ void php_base64_init(void) */ /* }}} */ -PHPAPI unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_length) /* {{{ */ +PHPAPI zend_string *php_base64_decode(const unsigned char *str, int length) /* {{{ */ { - return php_base64_decode_ex(str, length, ret_length, 0); + return php_base64_decode_ex(str, length, 0); } /* }}} */ -PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, int *ret_length, zend_bool strict) /* {{{ */ +PHPAPI zend_string *php_base64_decode_ex(const unsigned char *str, int length, zend_bool strict) /* {{{ */ { const unsigned char *current = str; int ch, i = 0, j = 0, k; /* this sucks for threaded environments */ - unsigned char *result; + zend_string *result; - result = (unsigned char *)safe_emalloc(length, 1, 1); + result = STR_ALLOC(length, 0); /* run through the whole string, converting as we go */ while ((ch = *current++) != '\0' && length-- > 0) { @@ -161,7 +158,7 @@ PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, continue; } } - efree(result); + STR_FREE(result); return NULL; } continue; @@ -171,24 +168,24 @@ PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, if ((!strict && ch < 0) || ch == -1) { /* a space or some other separator character, we simply skip over */ continue; } else if (ch == -2) { - efree(result); + STR_FREE(result); return NULL; } switch(i % 4) { case 0: - result[j] = ch << 2; + result->val[j] = ch << 2; break; case 1: - result[j++] |= ch >> 4; - result[j] = (ch & 0x0f) << 4; + result->val[j++] |= ch >> 4; + result->val[j] = (ch & 0x0f) << 4; break; case 2: - result[j++] |= ch >>2; - result[j] = (ch & 0x03) << 6; + result->val[j++] |= ch >>2; + result->val[j] = (ch & 0x03) << 6; break; case 3: - result[j++] |= ch; + result->val[j++] |= ch; break; } i++; @@ -199,18 +196,17 @@ PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, if (ch == base64_pad) { switch(i % 4) { case 1: - efree(result); + STR_FREE(result); return NULL; case 2: k++; case 3: - result[k] = 0; + result->val[k] = 0; } } - if(ret_length) { - *ret_length = j; - } - result[j] = '\0'; + result->len = j; + result->val[result->len] = '\0'; + return result; } /* }}} */ @@ -220,16 +216,15 @@ PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, PHP_FUNCTION(base64_encode) { char *str; - unsigned char *result; - int str_len, ret_length; + int str_len; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { return; } - result = php_base64_encode((unsigned char*)str, str_len, &ret_length); + result = php_base64_encode((unsigned char*)str, str_len); if (result != NULL) { -//??? RETVAL_STRINGL((char*)result, ret_length, 0); - RETVAL_STRINGL((char*)result, ret_length); + RETURN_STR(result); } else { RETURN_FALSE; } @@ -241,17 +236,16 @@ PHP_FUNCTION(base64_encode) PHP_FUNCTION(base64_decode) { char *str; - unsigned char *result; zend_bool strict = 0; - int str_len, ret_length; + int str_len; + zend_string *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &strict) == FAILURE) { return; } - result = php_base64_decode_ex((unsigned char*)str, str_len, &ret_length, strict); + result = php_base64_decode_ex((unsigned char*)str, str_len, strict); if (result != NULL) { -//??? RETVAL_STRINGL((char*)result, ret_length, 0); - RETVAL_STRINGL((char*)result, ret_length); + RETURN_STR(result); } else { RETURN_FALSE; } diff --git a/ext/standard/base64.h b/ext/standard/base64.h index 2358c58951a..e58565702a9 100644 --- a/ext/standard/base64.h +++ b/ext/standard/base64.h @@ -24,9 +24,9 @@ PHP_FUNCTION(base64_decode); PHP_FUNCTION(base64_encode); -PHPAPI extern unsigned char *php_base64_encode(const unsigned char *, int, int *); -PHPAPI extern unsigned char *php_base64_decode_ex(const unsigned char *, int, int *, zend_bool); -PHPAPI extern unsigned char *php_base64_decode(const unsigned char *, int, int *); +PHPAPI extern zend_string *php_base64_encode(const unsigned char *, int); +PHPAPI extern zend_string *php_base64_decode_ex(const unsigned char *, int, zend_bool); +PHPAPI extern zend_string *php_base64_decode(const unsigned char *, int); #endif /* BASE64_H */ diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index db87e6907cb..55a1d12cc78 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -526,6 +526,7 @@ finish: /* auth header if it was specified */ if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) { + zend_string *stmp; /* decode the strings first */ php_url_decode(resource->user, strlen(resource->user)); @@ -539,15 +540,14 @@ finish: strcat(scratch, resource->pass); } - tmp = (char*)php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL); + stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch)); - if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) { + if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", stmp->val) > 0) { php_stream_write(stream, scratch, strlen(scratch)); php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); } - efree(tmp); - tmp = NULL; + STR_FREE(stmp); } /* if the user has configured who they are, send a From: line */ diff --git a/ext/standard/password.c b/ext/standard/password.c index a76bf847d31..f5b925f530c 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -82,28 +82,27 @@ static int php_password_salt_is_alphabet(const char *str, const size_t len) /* { static int php_password_salt_to64(const char *str, const size_t str_len, const size_t out_len, char *ret) /* {{{ */ { size_t pos = 0; - size_t ret_len = 0; - unsigned char *buffer; + zend_string *buffer; if ((int) str_len < 0) { return FAILURE; } - buffer = php_base64_encode((unsigned char*) str, (int) str_len, (int*) &ret_len); - if (ret_len < out_len) { + buffer = php_base64_encode((unsigned char*) str, (int) str_len); + if (buffer->len < out_len) { /* Too short of an encoded string generated */ - efree(buffer); + STR_RELEASE(buffer); return FAILURE; } for (pos = 0; pos < out_len; pos++) { - if (buffer[pos] == '+') { + if (buffer->val[pos] == '+') { ret[pos] = '.'; - } else if (buffer[pos] == '=') { - efree(buffer); + } else if (buffer->val[pos] == '=') { + STR_FREE(buffer); return FAILURE; } else { - ret[pos] = buffer[pos]; + ret[pos] = buffer->val[pos]; } } - efree(buffer); + STR_FREE(buffer); return SUCCESS; } /* }}} */ diff --git a/main/main.c b/main/main.c index 9d6fe67755e..821a1a7bfb9 100644 --- a/main/main.c +++ b/main/main.c @@ -2584,19 +2584,18 @@ PHPAPI int php_handle_auth_data(const char *auth TSRMLS_DC) if (auth && auth[0] != '\0' && strncmp(auth, "Basic ", 6) == 0) { char *pass; - char *user; + zend_string *user; - user = php_base64_decode(auth + 6, strlen(auth) - 6, NULL); + user = php_base64_decode(auth + 6, strlen(auth) - 6); if (user) { - pass = strchr(user, ':'); + pass = strchr(user->val, ':'); if (pass) { *pass++ = '\0'; - SG(request_info).auth_user = user; + SG(request_info).auth_user = estrndup(user->val, user->len); SG(request_info).auth_password = estrdup(pass); ret = 0; - } else { - efree(user); - } + } + STR_FREE(user); } }