1
0
mirror of https://github.com/php/php-src.git synced 2026-04-12 18:43:37 +02:00

Merge branch 'PHP-5.6.22' into PHP-5.6

* PHP-5.6.22:
  Fix memory leak in imagescale()
  Update NEWS
  Better fix for bug #72135
  Fixed bug #72227: imagescale out-of-bounds read
  Fix bug #72241: get_icu_value_internal out-of-bounds read
  Fix bug #72135 - don't create strings with lengths outside int range
  prepare for 5.6.22RC1
  Add check for string overflow to all string add operations
  Fix bug #72114 - int/size_t confusion in fread
  Updated NEWS
  Fixed bug #71331 - Uninitialized pointer in phar_make_dirstream()

Conflicts:
	configure.in
	main/php_version.h
This commit is contained in:
Stanislav Malyshev
2016-05-24 17:21:22 -07:00
8 changed files with 216 additions and 151 deletions

View File

@@ -1397,7 +1397,13 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + 1;
char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
char *buf;
if (UNEXPECTED(length < 0)) {
zend_error(E_ERROR, "String size overflow");
}
buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
buf[length - 1] = (char) Z_LVAL_P(op2);
buf[length] = 0;
@@ -1410,7 +1416,13 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
char *buf;
if (UNEXPECTED(length < 0)) {
zend_error(E_ERROR, "String size overflow");
}
buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
buf[length] = 0;

View File

@@ -41,8 +41,8 @@
downscaling using the fixed point implementations are usually much faster
than the existing gdImageCopyResampled while having a similar or better
quality.
For image rotations, the optimized versions have a lazy antialiasing for
For image rotations, the optimized versions have a lazy antialiasing for
the edges of the images. For a much better antialiased result, the affine
function is recommended.
*/
@@ -635,7 +635,7 @@ static inline int _color_blend (const int dst, const int src)
}
}
static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor)
static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor)
{
const gdFixed f_127 = gd_itofx(127);
register int c = src->tpixels[y][x];
@@ -932,9 +932,6 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
double dTotalWeight = 0.0;
int iSrc;
res->ContribRow[u].Left = iLeft;
res->ContribRow[u].Right = iRight;
/* Cut edge points to fit in filter window in case of spill-off */
if (iRight - iLeft + 1 > windows_size) {
if (iLeft < ((int)src_size - 1 / 2)) {
@@ -944,6 +941,9 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
}
}
res->ContribRow[u].Left = iLeft;
res->ContribRow[u].Right = iRight;
for (iSrc = iLeft; iSrc <= iRight; iSrc++) {
dTotalWeight += (res->ContribRow[u].Weights[iSrc-iLeft] = scale_f_d * (*pFilter)(scale_f_d * (dCenter - (double)iSrc)));
}
@@ -1096,7 +1096,7 @@ gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsig
_gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
_gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
gdFree(tmp_im);
gdImageDestroy(tmp_im);
return dst;
}
@@ -2284,7 +2284,7 @@ int gdTransformAffineGetImage(gdImagePtr *dst,
if (!src->trueColor) {
gdImagePaletteToTrueColor(src);
}
/* Translate to dst origin (0,0) */
gdAffineTranslate(m, -bbox.x, -bbox.y);
gdAffineConcat(m, affine, m);
@@ -2343,7 +2343,7 @@ int gdTransformAffineCopy(gdImagePtr dst,
if (src->interpolation_id == GD_BILINEAR_FIXED || src->interpolation_id == GD_BICUBIC_FIXED || src->interpolation_id == GD_NEAREST_NEIGHBOUR) {
interpolation_id_bak = src->interpolation_id;
interpolation_bak = src->interpolation;
gdImageSetInterpolationMethod(src, GD_BICUBIC);
}

View File

@@ -0,0 +1,15 @@
--TEST--
Bug #72227: imagescale out-of-bounds read
--SKIPIF--
<?php
if (!extension_loaded('gd')) die("skip gd extension not available\n");
?>
--FILE--
<?php
$img = imagecreatetruecolor ( 100, 100);
imagescale($img, 13, 1, IMG_BICUBIC);
?>
DONE
--EXPECT--
DONE

View File

@@ -65,26 +65,26 @@ ZEND_EXTERN_MODULE_GLOBALS( intl )
*/
static const char * const LOC_GRANDFATHERED[] = {
"art-lojban", "i-klingon", "i-lux", "i-navajo", "no-bok", "no-nyn",
"cel-gaulish", "en-GB-oed", "i-ami",
"i-bnn", "i-default", "i-enochian",
"i-mingo", "i-pwn", "i-tao",
"cel-gaulish", "en-GB-oed", "i-ami",
"i-bnn", "i-default", "i-enochian",
"i-mingo", "i-pwn", "i-tao",
"i-tay", "i-tsu", "sgn-BE-fr",
"sgn-BE-nl", "sgn-CH-de", "zh-cmn",
"zh-cmn-Hans", "zh-cmn-Hant", "zh-gan" ,
"zh-guoyu", "zh-hakka", "zh-min",
"zh-min-nan", "zh-wuu", "zh-xiang",
"zh-min-nan", "zh-wuu", "zh-xiang",
"zh-yue", NULL
};
/* Based on IANA registry at the time of writing this code
* This array lists the preferred values for the grandfathered tags if applicable
* This is in sync with the array LOC_GRANDFATHERED
* This is in sync with the array LOC_GRANDFATHERED
* e.g. the offsets of the grandfathered tags match the offset of the preferred value
*/
static const int LOC_PREFERRED_GRANDFATHERED_LEN = 6;
static const char * const LOC_PREFERRED_GRANDFATHERED[] = {
"jbo", "tlh", "lb",
"nv", "nb", "nn",
"nv", "nb", "nn",
NULL
};
@@ -122,7 +122,7 @@ static int16_t findOffset(const char* const* list, const char* key)
/*}}}*/
static char* getPreferredTag(const char* gf_tag)
{
{
char* result = NULL;
int grOffset = 0;
@@ -141,15 +141,15 @@ static char* getPreferredTag(const char* gf_tag)
}
/* {{{
* returns the position of next token for lookup
* returns the position of next token for lookup
* or -1 if no token
* strtokr equivalent search for token in reverse direction
* strtokr equivalent search for token in reverse direction
*/
static int getStrrtokenPos(char* str, int savedPos)
{
int result =-1;
int i;
for(i=savedPos-1; i>=0; i--) {
if(isIDSeparator(*(str+i)) ){
/* delimiter found; check for singleton */
@@ -171,7 +171,7 @@ static int getStrrtokenPos(char* str, int savedPos)
/* }}} */
/* {{{
* returns the position of a singleton if present
* returns the position of a singleton if present
* returns -1 if no singleton
* strtok equivalent search for singleton
*/
@@ -180,7 +180,7 @@ static int getSingletonPos(const char* str)
int result =-1;
int i=0;
int len = 0;
if( str && ((len=strlen(str))>0) ){
for( i=0; i<len ; i++){
if( isIDSeparator(*(str+i)) ){
@@ -198,7 +198,7 @@ static int getSingletonPos(const char* str)
}
}
}/* end of for */
}
return result;
}
@@ -224,7 +224,7 @@ PHP_NAMED_FUNCTION(zif_locale_get_default)
PHP_NAMED_FUNCTION(zif_locale_set_default)
{
char* locale_name = NULL;
int len=0;
int len=0;
if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
&locale_name ,&len ) == FAILURE)
@@ -240,14 +240,14 @@ PHP_NAMED_FUNCTION(zif_locale_set_default)
len = strlen(locale_name);
}
zend_alter_ini_entry(LOCALE_INI_NAME, sizeof(LOCALE_INI_NAME), locale_name, len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
zend_alter_ini_entry(LOCALE_INI_NAME, sizeof(LOCALE_INI_NAME), locale_name, len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
RETURN_TRUE;
}
/* }}} */
/* {{{
* Gets the value from ICU
* Gets the value from ICU
* common code shared by get_primary_language,get_script or get_region or get_variant
* result = 0 if error, 1 if successful , -1 if no value
*/
@@ -284,7 +284,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
}
}
singletonPos = getSingletonPos( loc_name );
singletonPos = getSingletonPos( loc_name );
if( singletonPos == 0){
/* singleton at start of script, region , variant etc.
* or invalid singleton at start of language */
@@ -299,7 +299,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
} /* end of if != LOC_CANONICAL_TAG */
if( mod_loc_name == NULL){
mod_loc_name = estrdup(loc_name );
mod_loc_name = estrdup(loc_name );
}
/* Proceed to ICU */
@@ -326,6 +326,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
if( U_FAILURE( status ) ) {
if( status == U_BUFFER_OVERFLOW_ERROR ) {
status = U_ZERO_ERROR;
buflen++; /* add space for \0 */
continue;
}
@@ -366,7 +367,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
* Gets the value from ICU , called when PHP userspace function is called
* common code shared by get_primary_language,get_script or get_region or get_variant
*/
static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
{
const char* loc_name = NULL;
@@ -422,37 +423,37 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
}
/* }}} */
/* {{{ proto static string Locale::getScript($locale)
* gets the script for the $locale
/* {{{ proto static string Locale::getScript($locale)
* gets the script for the $locale
}}} */
/* {{{ proto static string locale_get_script($locale)
* gets the script for the $locale
/* {{{ proto static string locale_get_script($locale)
* gets the script for the $locale
*/
PHP_FUNCTION( locale_get_script )
PHP_FUNCTION( locale_get_script )
{
get_icu_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
/* }}} */
/* {{{ proto static string Locale::getRegion($locale)
* gets the region for the $locale
/* {{{ proto static string Locale::getRegion($locale)
* gets the region for the $locale
}}} */
/* {{{ proto static string locale_get_region($locale)
* gets the region for the $locale
/* {{{ proto static string locale_get_region($locale)
* gets the region for the $locale
*/
PHP_FUNCTION( locale_get_region )
PHP_FUNCTION( locale_get_region )
{
get_icu_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
/* }}} */
/* {{{ proto static string Locale::getPrimaryLanguage($locale)
* gets the primary language for the $locale
/* {{{ proto static string Locale::getPrimaryLanguage($locale)
* gets the primary language for the $locale
}}} */
/* {{{ proto static string locale_get_primary_language($locale)
* gets the primary language for the $locale
/* {{{ proto static string locale_get_primary_language($locale)
* gets the primary language for the $locale
*/
PHP_FUNCTION(locale_get_primary_language )
PHP_FUNCTION(locale_get_primary_language )
{
get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -460,9 +461,9 @@ PHP_FUNCTION(locale_get_primary_language )
/* {{{
* common code shared by display_xyz functions to get the value from ICU
* common code shared by display_xyz functions to get the value from ICU
}}} */
static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
{
const char* loc_name = NULL;
int loc_name_len = 0;
@@ -488,7 +489,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME
intl_error_reset( NULL TSRMLS_CC );
if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
&loc_name, &loc_name_len ,
&loc_name, &loc_name_len ,
&disp_loc_name ,&disp_loc_name_len ) == FAILURE)
{
spprintf(&msg , 0, "locale_get_display_%s : unable to parse input params", tag_name );
@@ -525,7 +526,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME
if( mod_loc_name==NULL ){
mod_loc_name = estrdup( loc_name );
}
/* Check if disp_loc_name passed , if not use default locale */
if( !disp_loc_name){
disp_loc_name = estrdup(intl_locale_get_default(TSRMLS_C));
@@ -604,7 +605,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME
/* {{{ proto static string get_display_name($locale[, $in_locale = null])
* gets the name for the $locale in $in_locale or default_locale
*/
PHP_FUNCTION(locale_get_display_name)
PHP_FUNCTION(locale_get_display_name)
{
get_icu_disp_value_src_php( DISP_NAME , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -616,7 +617,7 @@ PHP_FUNCTION(locale_get_display_name)
/* {{{ proto static string get_display_language($locale[, $in_locale = null])
* gets the language for the $locale in $in_locale or default_locale
*/
PHP_FUNCTION(locale_get_display_language)
PHP_FUNCTION(locale_get_display_language)
{
get_icu_disp_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -628,7 +629,7 @@ PHP_FUNCTION(locale_get_display_language)
/* {{{ proto static string get_display_script($locale, $in_locale = null)
* gets the script for the $locale in $in_locale or default_locale
*/
PHP_FUNCTION(locale_get_display_script)
PHP_FUNCTION(locale_get_display_script)
{
get_icu_disp_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -640,7 +641,7 @@ PHP_FUNCTION(locale_get_display_script)
/* {{{ proto static string get_display_region($locale, $in_locale = null)
* gets the region for the $locale in $in_locale or default_locale
*/
PHP_FUNCTION(locale_get_display_region)
PHP_FUNCTION(locale_get_display_region)
{
get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -654,7 +655,7 @@ PHP_FUNCTION(locale_get_display_region)
* proto static string get_display_variant($locale, $in_locale = null)
* gets the variant for the $locale in $in_locale or default_locale
*/
PHP_FUNCTION(locale_get_display_variant)
PHP_FUNCTION(locale_get_display_variant)
{
get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
@@ -667,7 +668,7 @@ PHP_FUNCTION(locale_get_display_variant)
/* {{{ proto static array locale_get_keywords(string $locale) {
* return an associative array containing keyword-value
* pairs for this locale. The keys are keys to the array (doh!)
*/
*/
PHP_FUNCTION( locale_get_keywords )
{
UEnumeration* e = NULL;
@@ -679,10 +680,10 @@ PHP_FUNCTION( locale_get_keywords )
const char* loc_name = NULL;
int loc_name_len = 0;
/*
ICU expects the buffer to be allocated before calling the function
and so the buffer size has been explicitly specified
ICU uloc.h #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
/*
ICU expects the buffer to be allocated before calling the function
and so the buffer size has been explicitly specified
ICU uloc.h #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
hence the kw_value buffer size is 100
*/
char* kw_value = NULL;
@@ -721,7 +722,7 @@ PHP_FUNCTION( locale_get_keywords )
kw_value_len=uloc_getKeywordValue( loc_name,kw_key, kw_value, kw_value_len+1 , &status );
} else if(!U_FAILURE(status)) {
kw_value = erealloc( kw_value , kw_value_len+1);
}
}
if (U_FAILURE(status)) {
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "locale_get_keywords: Error encountered while getting the keyword value for the keyword", 0 TSRMLS_CC );
if( kw_value){
@@ -740,10 +741,10 @@ PHP_FUNCTION( locale_get_keywords )
}
/* }}} */
/* {{{ proto static string Locale::canonicalize($locale)
* @return string the canonicalized locale
/* {{{ proto static string Locale::canonicalize($locale)
* @return string the canonicalized locale
* }}} */
/* {{{ proto static string locale_canonicalize(Locale $loc, string $locale)
/* {{{ proto static string locale_canonicalize(Locale $loc, string $locale)
* @param string $locale The locale string to canonicalize
*/
PHP_FUNCTION(locale_canonicalize)
@@ -752,10 +753,10 @@ PHP_FUNCTION(locale_canonicalize)
}
/* }}} */
/* {{{ append_key_value
/* {{{ append_key_value
* Internal function which is called from locale_compose
* gets the value for the key_name and appends to the loc_name
* returns 1 if successful , -1 if not found ,
* returns 1 if successful , -1 if not found ,
* 0 if array element is not a string , -2 if buffer-overflow
*/
static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_name)
@@ -767,7 +768,7 @@ static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_
/* element value is not a string */
return FAILURE;
}
if(strcmp(key_name, LOC_LANG_TAG) != 0 &&
if(strcmp(key_name, LOC_LANG_TAG) != 0 &&
strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) {
/* not lang or grandfathered tag */
smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
@@ -792,11 +793,11 @@ static void add_prefix(smart_str* loc_name, char* key_name)
}
/* }}} */
/* {{{ append_multiple_key_values
/* {{{ append_multiple_key_values
* Internal function which is called from locale_compose
* gets the multiple values for the key_name and appends to the loc_name
* used for 'variant','extlang','private'
* returns 1 if successful , -1 if not found ,
* used for 'variant','extlang','private'
* returns 1 if successful , -1 if not found ,
* 0 if array element is not a string , -2 if buffer-overflow
*/
static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, char* key_name TSRMLS_DC)
@@ -850,8 +851,8 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr,
/* Multiple variant values as variant0, variant1 ,variant2 */
isFirstSubtag = 0;
for( i=0 ; i< max_value; i++ ){
snprintf( cur_key_name , 30, "%s%d", key_name , i);
for( i=0 ; i< max_value; i++ ){
snprintf( cur_key_name , 30, "%s%d", key_name , i);
if( zend_hash_find( hash_arr , cur_key_name , strlen(cur_key_name) + 1,(void **)&ele_value ) == SUCCESS ){
if( Z_TYPE_PP(ele_value)!= IS_STRING ){
/* variant is not a string */
@@ -873,7 +874,7 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr,
/*{{{
* If applicable sets error message and aborts locale_compose gracefully
* returns 0 if locale_compose needs to be aborted
* returns 0 if locale_compose needs to be aborted
* otherwise returns 1
*/
static int handleAppendResult( int result, smart_str* loc_name TSRMLS_DC)
@@ -890,11 +891,11 @@ static int handleAppendResult( int result, smart_str* loc_name TSRMLS_DC)
/* }}} */
#define RETURN_SMART_STR(s) smart_str_0((s)); RETURN_STRINGL((s)->c, (s)->len, 0)
/* {{{ proto static string Locale::composeLocale($array)
* Creates a locale by combining the parts of locale-ID passed
/* {{{ proto static string Locale::composeLocale($array)
* Creates a locale by combining the parts of locale-ID passed
* }}} */
/* {{{ proto static string compose_locale($array)
* Creates a locale by combining the parts of locale-ID passed
/* {{{ proto static string compose_locale($array)
* Creates a locale by combining the parts of locale-ID passed
* }}} */
PHP_FUNCTION(locale_compose)
{
@@ -920,7 +921,7 @@ PHP_FUNCTION(locale_compose)
RETURN_FALSE;
/* Check for grandfathered first */
result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG);
result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG);
if( result == SUCCESS){
RETURN_SMART_STR(loc_name);
}
@@ -929,7 +930,7 @@ PHP_FUNCTION(locale_compose)
}
/* Not grandfathered */
result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG);
result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG);
if( result == LOC_NOT_FOUND ){
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
"locale_compose: parameter array does not contain 'language' tag.", 0 TSRMLS_CC );
@@ -947,11 +948,11 @@ PHP_FUNCTION(locale_compose)
}
/* Script */
result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG);
result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG);
if( !handleAppendResult( result, loc_name TSRMLS_CC)){
RETURN_FALSE;
}
/* Region */
result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG);
if( !handleAppendResult( result, loc_name TSRMLS_CC)){
@@ -959,7 +960,7 @@ PHP_FUNCTION(locale_compose)
}
/* Variant */
result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC);
result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC);
if( !handleAppendResult( result, loc_name TSRMLS_CC)){
RETURN_FALSE;
}
@@ -985,16 +986,16 @@ static char* get_private_subtags(const char* loc_name)
{
char* result =NULL;
int singletonPos = 0;
int len =0;
int len =0;
const char* mod_loc_name =NULL;
if( loc_name && (len = strlen(loc_name)>0 ) ){
mod_loc_name = loc_name ;
mod_loc_name = loc_name ;
len = strlen(mod_loc_name);
while( (singletonPos = getSingletonPos(mod_loc_name))!= -1){
if( singletonPos!=-1){
if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){
if( singletonPos!=-1){
if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){
/* private subtag start found */
if( singletonPos + 2 == len){
/* loc_name ends with '-x-' ; return NULL */
@@ -1019,7 +1020,7 @@ static char* get_private_subtags(const char* loc_name)
} /* end of while */
}
return result;
}
/* }}} */
@@ -1044,20 +1045,20 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name
} else {
key_value = get_icu_value_internal( loc_name , key_name , &result,1 );
}
if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) ||
if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) ||
( strcmp(key_name , LOC_VARIANT_TAG)==0) ){
if( result > 0 && key_value){
/* Tokenize on the "_" or "-" */
token = php_strtok_r( key_value , DELIMITER ,&last_ptr);
token = php_strtok_r( key_value , DELIMITER ,&last_ptr);
if( cur_key_name ){
efree( cur_key_name);
}
cur_key_name = (char*)ecalloc( 25, 25);
sprintf( cur_key_name , "%s%d", key_name , cnt++);
sprintf( cur_key_name , "%s%d", key_name , cnt++);
add_assoc_string( hash_arr, cur_key_name , token ,TRUE );
/* tokenize on the "_" or "-" and stop at singleton if any */
while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){
sprintf( cur_key_name , "%s%d", key_name , cnt++);
sprintf( cur_key_name , "%s%d", key_name , cnt++);
add_assoc_string( hash_arr, cur_key_name , token , TRUE );
}
/*
@@ -1077,16 +1078,16 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name
}
/*if( key_name != LOC_PRIVATE_TAG && key_value){*/
if( key_value){
efree(key_value);
efree(key_value);
}
return cur_result;
}
/* }}} */
/* {{{ proto static array Locale::parseLocale($locale)
/* {{{ proto static array Locale::parseLocale($locale)
* parses a locale-id into an array the different parts of it
}}} */
/* {{{ proto static array parse_locale($locale)
/* {{{ proto static array parse_locale($locale)
* parses a locale-id into an array the different parts of it
*/
PHP_FUNCTION(locale_parse)
@@ -1144,7 +1145,7 @@ PHP_FUNCTION(locale_get_all_variants)
char* saved_ptr = NULL;
intl_error_reset( NULL TSRMLS_CC );
if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
&loc_name, &loc_name_len ) == FAILURE)
{
@@ -1162,15 +1163,15 @@ PHP_FUNCTION(locale_get_all_variants)
array_init( return_value );
/* If the locale is grandfathered, stop, no variants */
if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){
if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){
/* ("Grandfathered Tag. No variants."); */
}
else {
else {
/* Call ICU variant */
variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0);
if( result > 0 && variant){
/* Tokenize on the "_" or "-" */
token = php_strtok_r( variant , DELIMITER , &saved_ptr);
token = php_strtok_r( variant , DELIMITER , &saved_ptr);
add_next_index_stringl( return_value, token , strlen(token) ,TRUE );
/* tokenize on the "_" or "-" and stop at singleton if any */
while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){
@@ -1181,7 +1182,7 @@ PHP_FUNCTION(locale_get_all_variants)
efree( variant );
}
}
}
/* }}} */
@@ -1220,11 +1221,11 @@ static int strToMatch(const char* str ,char *retstr)
/* }}} */
/* {{{ proto static boolean Locale::filterMatches(string $langtag, string $locale[, bool $canonicalize])
* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm
* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm
*/
/* }}} */
/* {{{ proto boolean locale_filter_matches(string $langtag, string $locale[, bool $canonicalize])
* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm
* Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm
*/
PHP_FUNCTION(locale_filter_matches)
{
@@ -1243,13 +1244,13 @@ PHP_FUNCTION(locale_filter_matches)
char* cur_lang_tag = NULL;
char* cur_loc_range = NULL;
zend_bool boolCanonical = 0;
zend_bool boolCanonical = 0;
UErrorCode status = U_ZERO_ERROR;
intl_error_reset( NULL TSRMLS_CC );
if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b",
&lang_tag, &lang_tag_len , &loc_range , &loc_range_len ,
&lang_tag, &lang_tag_len , &loc_range , &loc_range_len ,
&boolCanonical) == FAILURE)
{
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
@@ -1270,7 +1271,7 @@ PHP_FUNCTION(locale_filter_matches)
/* canonicalize loc_range */
can_loc_range=get_icu_value_internal( loc_range , LOC_CANONICALIZE_TAG , &result , 0);
if( result ==0) {
intl_error_set( NULL, status,
intl_error_set( NULL, status,
"locale_filter_matches : unable to canonicalize loc_range" , 0 TSRMLS_CC );
RETURN_FALSE;
}
@@ -1278,7 +1279,7 @@ PHP_FUNCTION(locale_filter_matches)
/* canonicalize lang_tag */
can_lang_tag = get_icu_value_internal( lang_tag , LOC_CANONICALIZE_TAG , &result , 0);
if( result ==0) {
intl_error_set( NULL, status,
intl_error_set( NULL, status,
"locale_filter_matches : unable to canonicalize lang_tag" , 0 TSRMLS_CC );
RETURN_FALSE;
}
@@ -1306,11 +1307,11 @@ PHP_FUNCTION(locale_filter_matches)
/* check if prefix */
token = strstr( cur_lang_tag , cur_loc_range );
if( token && (token==cur_lang_tag) ){
/* check if the char. after match is SEPARATOR */
chrcheck = token + (strlen(cur_loc_range));
if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){
if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){
if( cur_lang_tag){
efree( cur_lang_tag );
}
@@ -1346,7 +1347,7 @@ PHP_FUNCTION(locale_filter_matches)
else{
/* Convert to lower case for case-insensitive comparison */
cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1);
result = strToMatch( lang_tag , cur_lang_tag);
if( result == 0) {
efree( cur_lang_tag );
@@ -1362,11 +1363,11 @@ PHP_FUNCTION(locale_filter_matches)
/* check if prefix */
token = strstr( cur_lang_tag , cur_loc_range );
if( token && (token==cur_lang_tag) ){
/* check if the char. after match is SEPARATOR */
chrcheck = token + (strlen(cur_loc_range));
if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){
if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){
if( cur_lang_tag){
efree( cur_lang_tag );
}
@@ -1393,7 +1394,7 @@ PHP_FUNCTION(locale_filter_matches)
static void array_cleanup( char* arr[] , int arr_size)
{
int i=0;
for( i=0; i< arr_size; i++ ){
for( i=0; i< arr_size; i++ ){
if( arr[i*2] ){
efree( arr[i*2]);
}
@@ -1403,7 +1404,7 @@ static void array_cleanup( char* arr[] , int arr_size)
#define LOOKUP_CLEAN_RETURN(value) array_cleanup(cur_arr, cur_arr_len); return (value)
/* {{{
* returns the lookup result to lookup_loc_range_src_php
* returns the lookup result to lookup_loc_range_src_php
* internal function
*/
static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int canonicalize TSRMLS_DC)
@@ -1427,7 +1428,7 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
for(zend_hash_internal_pointer_reset(hash_arr);
zend_hash_has_more_elements(hash_arr) == SUCCESS;
zend_hash_move_forward(hash_arr)) {
if (zend_hash_get_current_data(hash_arr, (void**)&ele_value) == FAILURE) {
/* Should never actually fail since the key is known to exist.*/
continue;
@@ -1436,7 +1437,7 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
/* element value is not a string */
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: locale array element is not a string", 0 TSRMLS_CC);
LOOKUP_CLEAN_RETURN(NULL);
}
}
cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_PP(ele_value), Z_STRLEN_PP(ele_value));
result = strToMatch(Z_STRVAL_PP(ele_value), cur_arr[cur_arr_len*2]);
if(result == 0) {
@@ -1444,12 +1445,12 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
LOOKUP_CLEAN_RETURN(NULL);
}
cur_arr[cur_arr_len*2+1] = Z_STRVAL_PP(ele_value);
cur_arr_len++ ;
cur_arr_len++ ;
} /* end of for */
/* Canonicalize array elements */
if(canonicalize) {
for(i=0; i<cur_arr_len; i++) {
for(i=0; i<cur_arr_len; i++) {
lang_tag = get_icu_value_internal(cur_arr[i*2], LOC_CANONICALIZE_TAG, &result, 0);
if(result != 1 || lang_tag == NULL || !lang_tag[0]) {
if(lang_tag) {
@@ -1459,7 +1460,7 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
LOOKUP_CLEAN_RETURN(NULL);
}
cur_arr[i*2] = erealloc(cur_arr[i*2], strlen(lang_tag)+1);
result = strToMatch(lang_tag, cur_arr[i*2]);
result = strToMatch(lang_tag, cur_arr[i*2]);
efree(lang_tag);
if(result == 0) {
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
@@ -1482,11 +1483,11 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
} else {
loc_range = can_loc_range;
}
}
}
cur_loc_range = ecalloc(1, strlen(loc_range)+1);
/* convert to lower and replace hyphens */
result = strToMatch(loc_range, cur_loc_range);
result = strToMatch(loc_range, cur_loc_range);
if(can_loc_range) {
efree(can_loc_range);
}
@@ -1498,8 +1499,8 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
/* Lookup for the lang_tag match */
saved_pos = strlen(cur_loc_range);
while(saved_pos > 0) {
for(i=0; i< cur_arr_len; i++){
if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) {
for(i=0; i< cur_arr_len; i++){
if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) {
/* Match found */
return_value = estrdup(canonicalize?cur_arr[i*2]:cur_arr[i*2+1]);
efree(cur_loc_range);
@@ -1515,14 +1516,14 @@ static char* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int ca
}
/* }}} */
/* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]])
/* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]])
* Searchs the items in $langtag for the best match to the language
* range
* range
*/
/* }}} */
/* {{{ proto string locale_lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]])
* Searchs the items in $langtag for the best match to the language
* range
* range
*/
PHP_FUNCTION(locale_lookup)
{
@@ -1552,8 +1553,8 @@ PHP_FUNCTION(locale_lookup)
if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) {
RETURN_EMPTY_STRING();
}
}
result = lookup_loc_range(loc_range, hash_arr, boolCanonical TSRMLS_CC);
if(result == NULL || result[0] == '\0') {
if( fallback_loc ) {
@@ -1590,10 +1591,10 @@ PHP_FUNCTION(locale_accept_from_http)
"locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC );
RETURN_FALSE;
}
available = ures_openAvailableLocales(NULL, &status);
INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list");
len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN,
len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN,
&outResult, http_accept, available, &status);
uenum_close(available);
INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale");

View File

@@ -0,0 +1,14 @@
--TEST--
Bug #72241: get_icu_value_internal out-of-bounds read
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
--FILE--
<?php
$var1=str_repeat("A", 1000);
$out = locale_get_primary_language($var1);
echo strlen($out) . PHP_EOL;
echo unpack('H*', $out)[1] . PHP_EOL;
--EXPECT--
1000
61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161

View File

@@ -1762,6 +1762,12 @@ PHPAPI PHP_FUNCTION(fread)
RETURN_FALSE;
}
if (len > INT_MAX) {
/* string length is int in 5.x so we can not read more than int */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be no more than %d", INT_MAX);
RETURN_FALSE;
}
Z_STRVAL_P(return_value) = emalloc(len + 1);
Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);

View File

@@ -175,7 +175,7 @@ static inline unsigned int get_next_char(
else
MB_FAILURE(pos, 4);
}
this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */
MB_FAILURE(pos, 4);
@@ -449,7 +449,7 @@ det_charset:
if (charset_hint) {
int found = 0;
/* now walk the charset map and look for the codeset */
for (i = 0; charset_map[i].codeset; i++) {
if (len == strlen(charset_map[i].codeset) && strncasecmp(charset_hint, charset_map[i].codeset, len) == 0) {
@@ -557,7 +557,7 @@ static inline unsigned char unimap_bsearch(const uni_to_enc *table, unsigned cod
return 0;
code_key = (unsigned short) code_key_a;
while (l <= h) {
m = l + (h - l) / 2;
if (code_key < m->un_code_point)
@@ -583,7 +583,7 @@ static inline int map_from_unicode(unsigned code, enum entity_charset charset, u
/* identity mapping of code points to unicode */
if (code > 0xFF) {
return FAILURE;
}
}
*res = code;
break;
@@ -602,7 +602,7 @@ static inline int map_from_unicode(unsigned code, enum entity_charset charset, u
return FAILURE;
}
break;
case cs_8859_15:
if (code < 0xA4 || (code > 0xBE && code <= 0xFF)) {
*res = code;
@@ -646,7 +646,7 @@ static inline int map_from_unicode(unsigned code, enum entity_charset charset, u
case cs_cp866:
table = unimap_cp866;
table_size = sizeof(unimap_cp866) / sizeof(*unimap_cp866);
table_over_7F:
if (code <= 0x7F) {
*res = code;
@@ -722,7 +722,7 @@ static inline int unicode_cp_is_allowed(unsigned uni_cp, int document_type)
* Not sure this is the relevant part for HTML 5, though. I opted to
* disallow the characters that would result in a parse error when
* preprocessing of the input stream. See also section 8.1.3.
*
*
* It's unclear if XHTML 1.0 allows C1 characters. I'll opt to apply to
* XHTML 1.0 the same rules as for XML 1.0.
* See <http://cmsmcq.com/2007/C1.xml>.
@@ -786,7 +786,7 @@ static inline int numeric_entity_is_allowed(unsigned uni_cp, int document_type)
/* {{{ process_numeric_entity
* Auxiliary function to traverse_for_entities.
* On input, *buf should point to the first character after # and on output, it's the last
* byte read, no matter if there was success or insuccess.
* byte read, no matter if there was success or insuccess.
*/
static inline int process_numeric_entity(const char **buf, unsigned *code_point)
{
@@ -796,7 +796,7 @@ static inline int process_numeric_entity(const char **buf, unsigned *code_point)
if (hexadecimal && (**buf != '\0'))
(*buf)++;
/* strtol allows whitespace and other stuff in the beginning
* we're not interested */
if ((hexadecimal && !isxdigit(**buf)) ||
@@ -981,7 +981,7 @@ static void traverse_for_entities(
goto invalid_code;
/* are we allowed to decode this entity in this document type?
* HTML 5 is the only that has a character that cannot be used in
* HTML 5 is the only that has a character that cannot be used in
* a numeric entity but is allowed literally (U+000D). The
* unoptimized version would be ... || !numeric_entity_is_allowed(code) */
if (!unicode_cp_is_allowed(code, doctype) ||
@@ -1008,9 +1008,9 @@ static void traverse_for_entities(
}
}
}
assert(*next == ';');
if (((code == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
(code == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE)))
/* && code2 == '\0' always true for current maps */)
@@ -1038,7 +1038,7 @@ invalid_code:
*(q++) = *p;
}
}
*q = '\0';
*retlen = (size_t)(q - ret);
}
@@ -1078,7 +1078,7 @@ static entity_table_opt determine_entity_table(int all, int doctype)
entity_table_opt retval = {NULL};
assert(!(doctype == ENT_HTML_DOC_XML1 && all));
if (all) {
retval.ms_table = (doctype == ENT_HTML_DOC_HTML5) ?
entity_ms_table_html5 : entity_ms_table_html4;
@@ -1123,13 +1123,13 @@ PHPAPI char *php_unescape_html_entities(unsigned char *old, size_t oldlen, size_
if (retlen == 0) {
goto empty_source;
}
inverse_map = unescape_inverse_map(all, flags);
/* replace numeric entities */
traverse_for_entities(old, oldlen, ret, &retlen, all, flags, inverse_map, charset);
empty_source:
empty_source:
*newlen = retlen;
return ret;
}
@@ -1153,7 +1153,7 @@ static inline void find_entity_for_char(
{
unsigned stage1_idx = ENT_STAGE1_INDEX(k);
const entity_stage3_row *c;
if (stage1_idx > 0x1D) {
*entity = NULL;
*entity_len = 0;
@@ -1174,7 +1174,7 @@ static inline void find_entity_for_char(
if (!(*cursor < oldlen))
goto no_suitable_2nd;
next_char = get_next_char(charset, old, oldlen, cursor, &status);
next_char = get_next_char(charset, old, oldlen, cursor, &status);
if (status == FAILURE)
goto no_suitable_2nd;
@@ -1199,7 +1199,7 @@ no_suitable_2nd:
*entity = (const unsigned char *)
c->data.multicodepoint_table[0].leading_entry.default_entity;
*entity_len = c->data.multicodepoint_table[0].leading_entry.default_entity_len;
}
}
}
/* }}} */
@@ -1267,7 +1267,7 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
/* initial estimate */
if (oldlen < 64) {
maxlen = 128;
maxlen = 128;
} else {
maxlen = 2 * oldlen;
if (maxlen < oldlen) {
@@ -1435,6 +1435,11 @@ encode_amp:
}
replaced[len] = '\0';
*newlen = len;
if(len > INT_MAX) {
zend_error_noreturn(E_ERROR, "Escaped string is too long");
efree(replaced);
return NULL;
}
return replaced;
}
@@ -1597,7 +1602,7 @@ static inline void write_s3row_data(
} else {
spe_cp = uni_cp;
}
written_k2 = write_octet_sequence(&key[written_k1], charset, spe_cp);
memcpy(&entity[1], mcpr[i].normal_entry.entity, l);
entity[l + 1] = ';';
@@ -1635,7 +1640,7 @@ PHP_FUNCTION(get_html_translation_table)
LIMIT_ALL(all, doctype, charset);
array_init(return_value);
entity_table = determine_entity_table(all, doctype);
if (all && !CHARSET_UNICODE_COMPAT(charset)) {
to_uni_table = enc_to_uni_index[charset];

View File

@@ -0,0 +1,12 @@
--TEST--
Bug #72114 (Integer underflow / arbitrary null write in fread/gzread)
--FILE--
<?php
ini_set('memory_limit', "2500M");
$fp = fopen("/dev/zero", "r");
fread($fp, 2147483648);
?>
Done
--EXPECTF--
Warning: fread(): Length parameter must be no more than 2147483647 in %s/bug72114.php on line %d
Done