Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
php5.16119
php-pcre-replace-impl-CWE-680.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File php-pcre-replace-impl-CWE-680.patch of Package php5.16119
Index: php-5.5.14/ext/pcre/php_pcre.c =================================================================== --- php-5.5.14.orig/ext/pcre/php_pcre.c 2014-06-25 15:06:23.000000000 +0200 +++ php-5.5.14/ext/pcre/php_pcre.c 2018-08-29 12:58:10.939640709 +0200 @@ -999,6 +999,47 @@ PHPAPI char *php_pcre_replace(char *rege } /* }}} */ +static int safe_address(int nmemb, int size, int offset) +{ + int res; + if (nmemb < 0 || nmemb < 0) { + return -1; + } + if (size == 0) { + res = 0; + } + else if(nmemb > INT_MAX / size) { + return -1; + } + else { + res = nmemb*size; + } + + if (res > INT_MAX - offset) { + return -1; + } + + return res + offset; +} + +#define safe_address_guarded(res, nmemb, size, offset) \ + { \ + if ((res = safe_address(nmemb, size, offset)) == -1) {\ + if (offsets) \ + efree(offsets); \ + if (subpat_names) \ + efree(subpat_names); \ + if (result) \ + efree(result); \ + zend_error_noreturn(E_ERROR, \ + "Possible integer overflow in memory allocation (%zu * %zu + %zu)", \ + nmemb, size, offset); \ + return NULL; \ + } \ + }\ + + + /* {{{ php_pcre_replace_impl() */ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC) @@ -1007,8 +1048,8 @@ PHPAPI char *php_pcre_replace_impl(pcre_ pcre_extra extra_data; /* Used locally for exec options */ int exoptions = 0; /* Execution options */ int count = 0; /* Count of matched subpatterns */ - int *offsets; /* Array of subpattern offsets */ - char **subpat_names; /* Array for named subpatterns */ + int *offsets = NULL; /* Array of subpattern offsets */ + char **subpat_names=NULL; /* Array for named subpatterns */ int num_subpats; /* Number of captured subpatterns */ int size_offsets; /* Size of the offsets array */ int new_len; /* Length of needed storage */ @@ -1021,7 +1062,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_ int start_offset; /* Where the new search starts */ int g_notempty=0; /* If the match should not be empty */ int replace_len=0; /* Length of replacement string */ - char *result, /* Result of replacement */ + char *result=NULL, /* Result of replacement */ *replace=NULL, /* Replacement string */ *new_buf, /* Temporary buffer for re-allocation */ *walkbuf, /* Location of current replacement in the result */ @@ -1077,7 +1118,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_ offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0); - alloc_len = 2 * subject_len + 1; + safe_address_guarded(alloc_len, 2, subject_len, 1); result = safe_emalloc(alloc_len, sizeof(char), 0); /* Initialize */ @@ -1115,11 +1156,12 @@ PHPAPI char *php_pcre_replace_impl(pcre_ if (eval) { eval_result_len = preg_do_eval(replace, replace_len, subject, offsets, count, &eval_result TSRMLS_CC); - new_len += eval_result_len; + safe_address_guarded(new_len, 1, eval_result_len, new_len); + } else if (is_callable_replace) { /* Use custom function to get replacement string and its length. */ eval_result_len = preg_do_repl_func(replace_val, subject, offsets, subpat_names, count, &eval_result TSRMLS_CC); - new_len += eval_result_len; + safe_address_guarded(new_len, 1, eval_result_len, new_len); } else { /* do regular substitution */ walk = replace; walk_last = 0; @@ -1132,18 +1174,18 @@ PHPAPI char *php_pcre_replace_impl(pcre_ } if (preg_get_backref(&walk, &backref)) { if (backref < count) - new_len += offsets[(backref<<1)+1] - offsets[backref<<1]; + safe_address_guarded(new_len, 1, new_len, offsets[(backref<<1)+1] - offsets[backref<<1]); continue; } } - new_len++; + safe_address_guarded(new_len, 1, new_len, 1); walk++; walk_last = walk[-1]; } } if (new_len + 1 > alloc_len) { - alloc_len = 1 + alloc_len + 2 * new_len; + safe_address_guarded(alloc_len, 2, new_len, 1 + alloc_len); new_buf = emalloc(alloc_len); memcpy(new_buf, result, *result_len); efree(result); @@ -1151,7 +1193,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_ } /* copy the part of the string before the match */ memcpy(&result[*result_len], piece, match-piece); - *result_len += match-piece; + safe_address_guarded(*result_len, 1, *result_len, match-piece); /* copy replacement and backrefs */ walkbuf = result + *result_len; @@ -1160,7 +1202,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_ * and clean up. */ if (eval || is_callable_replace) { memcpy(walkbuf, eval_result, eval_result_len); - *result_len += eval_result_len; + safe_address_guarded(*result_len, 1, *result_len, eval_result_len); STR_FREE(eval_result); } else { /* do regular backreference copying */ walk = replace; @@ -1203,9 +1245,9 @@ PHPAPI char *php_pcre_replace_impl(pcre_ memcpy(&result[*result_len], piece, 1); (*result_len)++; } else { - new_len = *result_len + subject_len - start_offset; + safe_address_guarded(new_len, 1, *result_len, subject_len - start_offset); if (new_len + 1 > alloc_len) { - alloc_len = new_len + 1; /* now we know exactly how long it is */ + safe_address_guarded(alloc_len, 1, new_len, 1); /* now we know exactly how long it is */ new_buf = safe_emalloc(alloc_len, sizeof(char), 0); memcpy(new_buf, result, *result_len); efree(result); @@ -1213,7 +1255,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_ } /* stick that last bit of string on our output */ memcpy(&result[*result_len], piece, subject_len - start_offset); - *result_len += subject_len - start_offset; + safe_address_guarded(*result_len, 1, *result_len, subject_len - start_offset); result[*result_len] = '\0'; break; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor