diff options
27 files changed, 522 insertions, 215 deletions
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 84a3508ded..5a5bccecab 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -651,14 +651,14 @@ CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC) /* {{{ memcmp(path, (*bucket)->path, path_len) == 0) { realpath_cache_bucket *r = *bucket; *bucket = (*bucket)->next; - + /* if the pointers match then only subtract the length of the path */ if(r->path == r->realpath) { CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1; } else { CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1; } - + free(r); return; } else { @@ -734,7 +734,7 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p realpath_cache_bucket *r = *bucket; *bucket = (*bucket)->next; - /* if the pointers match then only subtract the length of the path */ + /* if the pointers match then only subtract the length of the path */ if(r->path == r->realpath) { CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1; } else { diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index a93493fd3e..54b59f75d4 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -15,7 +15,7 @@ | Author: Sterling Hughes <sterling@php.net> | +----------------------------------------------------------------------+ */ - + /* $Id$ */ #ifdef HAVE_CONFIG_H @@ -138,29 +138,33 @@ struct php_bz2_stream_data_t { static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract; - size_t ret; - - ret = BZ2_bzread(self->bz_file, buf, count); + int bz2_ret; + + bz2_ret = BZ2_bzread(self->bz_file, buf, count); - if (ret == 0) { + if (bz2_ret < 0) { + stream->eof = 1; + return -1; + } + if (bz2_ret == 0) { stream->eof = 1; } - return ret; + return (size_t)bz2_ret; } static size_t php_bz2iop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) { struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract; - return BZ2_bzwrite(self->bz_file, (char*)buf, count); + return BZ2_bzwrite(self->bz_file, (char*)buf, count); } static int php_bz2iop_close(php_stream *stream, int close_handle TSRMLS_DC) { struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract; int ret = EOF; - + if (close_handle) { BZ2_bzclose(self->bz_file); } @@ -196,7 +200,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, const char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC) { struct php_bz2_stream_data_t *self; - + self = emalloc(sizeof(*self)); self->stream = innerstream; @@ -227,7 +231,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, virtual_filepath_ex(path, &path_copy, NULL TSRMLS_CC); #else path_copy = path; -#endif +#endif if (php_check_open_basedir(path_copy TSRMLS_CC)) { #ifdef VIRTUAL_DIR @@ -235,7 +239,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, #endif return NULL; } - + /* try and open it directly first */ bz_file = BZ2_bzopen(path_copy, mode); @@ -246,11 +250,11 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, efree(path_copy); #endif path_copy = NULL; - + if (bz_file == NULL) { /* that didn't work, so try and get something from the network/wrapper */ stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST, opened_path); - + if (stream) { php_socket_t fd; if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) { @@ -265,7 +269,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, VCWD_UNLINK(*opened_path); } } - + if (bz_file) { retstream = _php_stream_bz2open_from_BZFILE(bz_file, mode, stream STREAMS_REL_CC TSRMLS_CC); if (retstream) { @@ -341,7 +345,7 @@ static PHP_FUNCTION(bzread) if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &bz, &len)) { RETURN_FALSE; } - + php_stream_from_zval(stream, &bz); if ((len + 1) < 1) { @@ -351,13 +355,13 @@ static PHP_FUNCTION(bzread) Z_STRVAL_P(return_value) = emalloc(len + 1); Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len); - + if (Z_STRLEN_P(return_value) < 0) { efree(Z_STRVAL_P(return_value)); php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read valid bz2 data from stream"); - RETURN_FALSE; + RETURN_FALSE; } - + Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; Z_TYPE_P(return_value) = IS_STRING; } @@ -373,7 +377,7 @@ static PHP_FUNCTION(bzopen) BZFILE *bz; /* The compressed file stream */ php_stream *stream = NULL; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &file, &mode, &mode_len) == FAILURE) { return; } @@ -389,15 +393,15 @@ static PHP_FUNCTION(bzopen) php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty"); RETURN_FALSE; } - + if (CHECK_ZVAL_NULL_PATH(*file)) { RETURN_FALSE; } stream = php_stream_bz2open(NULL, - Z_STRVAL_PP(file), - mode, - REPORT_ERRORS, + Z_STRVAL_PP(file), + mode, + REPORT_ERRORS, NULL); } else if (Z_TYPE_PP(file) == IS_RESOURCE) { /* If it is a resource, than its a stream resource */ @@ -406,7 +410,7 @@ static PHP_FUNCTION(bzopen) php_stream_from_zval(stream, file); stream_mode_len = strlen(stream->mode); - + if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode); RETURN_FALSE; @@ -440,7 +444,7 @@ static PHP_FUNCTION(bzopen) if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) { RETURN_FALSE; } - + bz = BZ2_bzdopen(fd, mode); stream = php_stream_bz2open_from_BZFILE(bz, mode, stream); @@ -494,7 +498,7 @@ static PHP_FUNCTION(bzcompress) work_factor = 0, /* Work factor for compression algorithm */ argc; /* Argument count */ int source_len; /* Length of the source data */ - unsigned int dest_len; /* Length of the destination buffer */ + unsigned int dest_len; /* Length of the destination buffer */ argc = ZEND_NUM_ARGS(); @@ -503,19 +507,19 @@ static PHP_FUNCTION(bzcompress) } /* Assign them to easy to use variables, dest_len is initially the length of the data - + .01 x length of data + 600 which is the largest size the results of the compression - could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net + + .01 x length of data + 600 which is the largest size the results of the compression + could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net for pointing this out). */ dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600); - + /* Allocate the destination buffer */ dest = emalloc(dest_len + 1); - + /* Handle the optional arguments */ if (argc > 1) { block_size = zblock_size; } - + if (argc > 2) { work_factor = zwork_factor; } @@ -565,7 +569,7 @@ static PHP_FUNCTION(bzdecompress) /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */ bzs.avail_out = source_len * 2; bzs.next_out = dest = emalloc(bzs.avail_out + 1); - + while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; @@ -591,13 +595,13 @@ static PHP_FUNCTION(bzdecompress) /* {{{ php_bz2_error() The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) -{ +{ zval *bzp; /* BZip2 Resource Pointer */ php_stream *stream; const char *errstr; /* Error string */ int errnum; /* Error number */ struct php_bz2_stream_data_t *self; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &bzp) == FAILURE) { return; } @@ -609,10 +613,10 @@ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) } self = (struct php_bz2_stream_data_t *) stream->abstract; - + /* Fetch the error information */ errstr = BZ2_bzerror(self->bz_file, &errnum); - + /* Determine what to return */ switch (opt) { case PHP_BZ_ERRNO: @@ -623,7 +627,7 @@ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) break; case PHP_BZ_ERRBOTH: array_init(return_value); - + add_assoc_long (return_value, "errno", errnum); add_assoc_string(return_value, "errstr", (char*)errstr, 1); break; diff --git a/ext/bz2/tests/72613.bz2 b/ext/bz2/tests/72613.bz2 Binary files differnew file mode 100644 index 0000000000..0b932f8d91 --- /dev/null +++ b/ext/bz2/tests/72613.bz2 diff --git a/ext/bz2/tests/bug72613.phpt b/ext/bz2/tests/bug72613.phpt new file mode 100644 index 0000000000..82547e6ae0 --- /dev/null +++ b/ext/bz2/tests/bug72613.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #72613 (Inadequate error handling in bzread()) +--SKIPIF-- +<?php if (!extension_loaded("bz2")) print "skip"; ?> +--FILE-- +<?php +$fp = bzopen(__DIR__.'/72613.bz2', 'r'); +if ($fp === FALSE) { + exit("ERROR: bzopen()"); +} +$data = ""; +while (!feof($fp)) { + $res = bzread($fp); + if ($res === FALSE) { + exit("ERROR: bzread()"); + } + $data .= $res; +} +bzclose($fp); +?> +DONE +--EXPECT-- +DONE
\ No newline at end of file diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 1ff4b4b14e..5564de4b4a 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -2613,6 +2613,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP *pszEncoding = NULL; /* Copy the comment */ if (ByteCount>=8) { + const zend_encoding *from, *to; if (!memcmp(szValuePtr, "UNICODE\0", 8)) { *pszEncoding = estrdup((const char*)szValuePtr); szValuePtr = szValuePtr+8; @@ -2633,14 +2634,16 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP } else { decode = ImageInfo->decode_unicode_le; } + to = zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC); + from = zend_multibyte_fetch_encoding(decode TSRMLS_CC); /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */ - if (zend_multibyte_encoding_converter( + if (!to || !from || zend_multibyte_encoding_converter( (unsigned char**)pszInfoPtr, &len, (unsigned char*)szValuePtr, ByteCount, - zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC), - zend_multibyte_fetch_encoding(decode TSRMLS_CC) + to, + from TSRMLS_CC) == (size_t)-1) { len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount); } @@ -2655,13 +2658,15 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP szValuePtr = szValuePtr+8; ByteCount -= 8; /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */ - if (zend_multibyte_encoding_converter( + to = zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC); + from = zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le TSRMLS_CC); + if (!to || !from || zend_multibyte_encoding_converter( (unsigned char**)pszInfoPtr, &len, (unsigned char*)szValuePtr, ByteCount, - zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC), - zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le TSRMLS_CC) + to, + from TSRMLS_CC) == (size_t)-1) { len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount); } @@ -2732,6 +2737,12 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu break; } + if (maker_note->offset >= value_len) { + /* Do not go past the value end */ + exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data too short: 0x%04X offset 0x%04X", value_len, maker_note->offset); + return FALSE; + } + dir_start = value_ptr + maker_note->offset; #ifdef EXIF_DEBUG @@ -2760,10 +2771,19 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu offset_base = value_ptr; break; case MN_OFFSET_GUESS: + if (maker_note->offset + 10 + 4 >= value_len) { + /* Can not read dir_start+10 since it's beyond value end */ + exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data too short: 0x%04X", value_len); + return FALSE; + } offset_diff = 2 + NumDirEntries*12 + 4 - php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel); #ifdef EXIF_DEBUG exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Using automatic offset correction: 0x%04X", ((int)dir_start-(int)offset_base+maker_note->offset+displacement) + offset_diff); #endif + if (offset_diff < 0 || offset_diff >= value_len ) { + exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data bad offset: 0x%04X length 0x%04X", offset_diff, value_len); + return FALSE; + } offset_base = value_ptr + offset_diff; break; default: @@ -2772,7 +2792,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu } if ((2+NumDirEntries*12) > value_len) { - exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 2 + x%04X*12 = x%04X > x%04X", NumDirEntries, 2+NumDirEntries*12, value_len); + exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 2 + 0x%04X*12 = 0x%04X > 0x%04X", NumDirEntries, 2+NumDirEntries*12, value_len); return FALSE; } @@ -3058,7 +3078,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha break; case TAG_MAKER_NOTE: - exif_process_IFD_in_MAKERNOTE(ImageInfo, value_ptr, byte_count, offset_base, IFDlength, displacement TSRMLS_CC); + if (!exif_process_IFD_in_MAKERNOTE(ImageInfo, value_ptr, byte_count, offset_base, IFDlength, displacement TSRMLS_CC)) { + EFREE_IF(outside); + return FALSE; + } break; case TAG_EXIF_IFD_POINTER: diff --git a/ext/exif/tests/bug54002.phpt b/ext/exif/tests/bug54002.phpt index c51fa58897..8f85339190 100644 --- a/ext/exif/tests/bug54002.phpt +++ b/ext/exif/tests/bug54002.phpt @@ -13,8 +13,4 @@ exif_read_data(__DIR__ . '/bug54002_2.jpeg'); --EXPECTF-- Warning: exif_read_data(bug54002_1.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d -Warning: exif_read_data(bug54002_1.jpeg): Process tag(xA000=FlashPixVer): Illegal pointer offset(%s) in %sbug54002.php on line %d - -Warning: exif_read_data(bug54002_2.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d - -Warning: exif_read_data(bug54002_2.jpeg): Process tag(xA000=FlashPixVer): Illegal pointer offset(%s) in %sbug54002.php on line %d +Warning: exif_read_data(bug54002_2.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d
\ No newline at end of file diff --git a/ext/exif/tests/bug62523_2.phpt b/ext/exif/tests/bug62523_2.phpt index ddc8ae824e..c533d42652 100644 --- a/ext/exif/tests/bug62523_2.phpt +++ b/ext/exif/tests/bug62523_2.phpt @@ -10,7 +10,9 @@ echo "Test\n"; var_dump(count(exif_read_data(__DIR__."/bug62523_2.jpg"))); ?> Done ---EXPECT-- +--EXPECTF-- Test -int(76) + +Warning: exif_read_data(bug62523_2.jpg): IFD data bad offset: 0xADB23672 length 0x0D94 in %s/bug62523_2.php on line %d +int(30) Done diff --git a/ext/exif/tests/bug72603.jpeg b/ext/exif/tests/bug72603.jpeg Binary files differnew file mode 100644 index 0000000000..1764c805fb --- /dev/null +++ b/ext/exif/tests/bug72603.jpeg diff --git a/ext/exif/tests/bug72603.phpt b/ext/exif/tests/bug72603.phpt new file mode 100644 index 0000000000..a4295f9848 --- /dev/null +++ b/ext/exif/tests/bug72603.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #72603 (Out of bound read in exif_process_IFD_in_MAKERNOTE) +--SKIPIF-- +<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?> +--FILE-- +<?php +var_dump(count(exif_read_data(dirname(__FILE__) . "/bug72603.jpeg"))); +?> +--EXPECTF-- +Warning: exif_read_data(bug72603.jpeg): IFD data bad offset: 0x058C length 0x001C in %s/bug72603.php on line %d +int(13)
\ No newline at end of file diff --git a/ext/exif/tests/bug72618.jpg b/ext/exif/tests/bug72618.jpg Binary files differnew file mode 100644 index 0000000000..0a61ae2e02 --- /dev/null +++ b/ext/exif/tests/bug72618.jpg diff --git a/ext/exif/tests/bug72618.phpt b/ext/exif/tests/bug72618.phpt new file mode 100644 index 0000000000..424c0ec402 --- /dev/null +++ b/ext/exif/tests/bug72618.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug 72618 (NULL Pointer Dereference in exif_process_user_comment) +--SKIPIF-- +<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?> +--FILE-- +<?php +var_dump(count(exif_read_data(dirname(__FILE__) . "/bug72618.jpg"))); +?> +--EXPECTF-- +Warning: exif_read_data(bug72618.jpg): IFD data bad offset: 0x058E length 0x0030 in %s/bug72618.php on line %d +int(13)
\ No newline at end of file diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 18959fc3a8..fc63cd379c 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -190,7 +190,7 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy) return NULL; } - if (overflow2(sizeof(int), sx)) { + if (overflow2(sizeof(int *), sx)) { return NULL; } diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index fb34982582..b9c4c2878e 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -879,20 +879,39 @@ int getPixelInterpolated(gdImagePtr im, const double x, const double y, const in static inline LineContribType * _gdContributionsAlloc(unsigned int line_length, unsigned int windows_size) { unsigned int u = 0; - LineContribType *res; + LineContribType *res; + int overflow_error = 0; res = (LineContribType *) gdMalloc(sizeof(LineContribType)); if (!res) { return NULL; } - res->WindowSize = windows_size; - res->LineLength = line_length; - res->ContribRow = (ContributionType *) gdMalloc(line_length * sizeof(ContributionType)); - - for (u = 0 ; u < line_length ; u++) { - res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double)); - } - return res; + res->WindowSize = windows_size; + res->LineLength = line_length; + if (overflow2(line_length, sizeof(ContributionType))) { + return NULL; + } + res->ContribRow = (ContributionType *) gdMalloc(line_length * sizeof(ContributionType)); + if (res->ContribRow == NULL) { + gdFree(res); + return NULL; + } + for (u = 0 ; u < line_length ; u++) { + if (overflow2(windows_size, sizeof(double))) { + overflow_error = 1; + } else { + res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double)); + } + if (overflow_error == 1 || res->ContribRow[u].Weights == NULL) { + u--; + while (u >= 0) { + gdFree(res->ContribRow[u].Weights); + u--; + } + return NULL; + } + } + return res; } static inline void _gdContributionsFree(LineContribType * p) @@ -907,59 +926,62 @@ static inline void _gdContributionsFree(LineContribType * p) static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsigned int src_size, double scale_d, const interpolation_method pFilter) { - double width_d; - double scale_f_d = 1.0; - const double filter_width_d = DEFAULT_BOX_RADIUS; + double width_d; + double scale_f_d = 1.0; + const double filter_width_d = DEFAULT_BOX_RADIUS; int windows_size; unsigned int u; LineContribType *res; + int overflow_error = 0; - if (scale_d < 1.0) { - width_d = filter_width_d / scale_d; - scale_f_d = scale_d; - } else { - width_d= filter_width_d; - } - - windows_size = 2 * (int)ceil(width_d) + 1; - res = _gdContributionsAlloc(line_size, windows_size); + if (scale_d < 1.0) { + width_d = filter_width_d / scale_d; + scale_f_d = scale_d; + } else { + width_d= filter_width_d; + } - for (u = 0; u < line_size; u++) { - const double dCenter = (double)u / scale_d; - /* get the significant edge points affecting the pixel */ - register int iLeft = MAX(0, (int)floor (dCenter - width_d)); - int iRight = MIN((int)ceil(dCenter + width_d), (int)src_size - 1); - double dTotalWeight = 0.0; + windows_size = 2 * (int)ceil(width_d) + 1; + res = _gdContributionsAlloc(line_size, windows_size); + if (res == NULL) { + return NULL; + } + for (u = 0; u < line_size; u++) { + const double dCenter = (double)u / scale_d; + /* get the significant edge points affecting the pixel */ + register int iLeft = MAX(0, (int)floor (dCenter - width_d)); + int iRight = MIN((int)ceil(dCenter + width_d), (int)src_size - 1); + double dTotalWeight = 0.0; int iSrc; - /* 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)) { - iLeft++; - } else { - 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)) { + iLeft++; + } else { + iRight--; + } + } - res->ContribRow[u].Left = iLeft; - res->ContribRow[u].Right = iRight; + 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))); - } + for (iSrc = iLeft; iSrc <= iRight; iSrc++) { + dTotalWeight += (res->ContribRow[u].Weights[iSrc-iLeft] = scale_f_d * (*pFilter)(scale_f_d * (dCenter - (double)iSrc))); + } if (dTotalWeight < 0.0) { _gdContributionsFree(res); return NULL; } - if (dTotalWeight > 0.0) { - for (iSrc = iLeft; iSrc <= iRight; iSrc++) { - res->ContribRow[u].Weights[iSrc-iLeft] /= dTotalWeight; - } - } - } - return res; + if (dTotalWeight > 0.0) { + for (iSrc = iLeft; iSrc <= iRight; iSrc++) { + res->ContribRow[u].Weights[iSrc-iLeft] /= dTotalWeight; + } + } + } + return res; } static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImagePtr dst, unsigned int dst_width, unsigned int row, LineContribType *contrib) diff --git a/ext/gd/tests/bug72512_0.phpt b/ext/gd/tests/bug72512_0.phpt new file mode 100644 index 0000000000..5f98662d45 --- /dev/null +++ b/ext/gd/tests/bug72512_0.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #72512 gdImageTrueColorToPaletteBody allows arbitrary write/read access, var 0 +--SKIPIF-- +<?php + if (!extension_loaded('gd')) die("skip gd extension not available\n"); +?> +--FILE-- +<?php + +$img = imagecreatetruecolor(13, 1007); + +imagecolortransparent($img, -10066304); +imagetruecolortopalette($img, TRUE, 3); +imagescale($img, 1, 65535); +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/gd/tests/bug72512_1.phpt b/ext/gd/tests/bug72512_1.phpt new file mode 100644 index 0000000000..bba01a7118 --- /dev/null +++ b/ext/gd/tests/bug72512_1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #72512 gdImageTrueColorToPaletteBody allows arbitrary write/read access, var 1 +--SKIPIF-- +<?php + if (!extension_loaded('gd')) die("skip gd extension not available\n"); +?> +--FILE-- +<?php + +$img = imagecreatetruecolor(100, 100); +imagecolortransparent($img, -1000000); +imagetruecolortopalette($img, TRUE, 3); +imagecolortransparent($img, 9); + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index 31f60b39a4..443856ff5e 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1591,6 +1591,24 @@ PHP_FUNCTION(locale_accept_from_http) "locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC ); RETURN_FALSE; } + if(http_accept_len > ULOC_FULLNAME_CAPACITY) { + /* check each fragment, if any bigger than capacity, can't do it due to bug #72533 */ + char *start = http_accept; + char *end; + size_t len; + do { + end = strchr(start, ','); + len = end ? end-start : http_accept_len-(start-http_accept); + if(len > ULOC_FULLNAME_CAPACITY) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "locale_accept_from_http: locale string too long", 0 TSRMLS_CC ); + RETURN_FALSE; + } + if(end) { + start = end+1; + } + } while(end != NULL); + } available = ures_openAvailableLocales(NULL, &status); INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list"); diff --git a/ext/intl/tests/bug72533.phpt b/ext/intl/tests/bug72533.phpt new file mode 100644 index 0000000000..c7fcba39d0 --- /dev/null +++ b/ext/intl/tests/bug72533.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #72533 (locale_accept_from_http out-of-bounds access) +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php + +function ut_main() +{ + $ret = var_export(ut_loc_accept_http(str_repeat('x', 256)), true); + $ret .= "\n"; + if(intl_is_failure(intl_get_error_code())) { + $ret .= var_export(intl_get_error_message(), true); + } + $ret .= "\n"; + $ret .= var_export(ut_loc_accept_http(str_repeat('en,', 256)), true); + $ret .= "\n"; + if(intl_is_failure(intl_get_error_code())) { + $ret .= var_export(intl_get_error_message(), true); + } + return $ret; +} + +include_once( 'ut_common.inc' ); +ut_run(); +?> +--EXPECTF-- +false +'locale_accept_from_http: locale string too long: U_ILLEGAL_ARGUMENT_ERROR' +'en'
\ No newline at end of file diff --git a/ext/session/session.c b/ext/session/session.c index b4e5a327c1..c668bb7b2a 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -867,7 +867,7 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */ if (php_var_unserialize(&session_vars, &val, endptr, &var_hash TSRMLS_CC)) { var_push_dtor(&var_hash, &session_vars); } - + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); if (PS(http_session_vars)) { zval_ptr_dtor(&PS(http_session_vars)); @@ -932,6 +932,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) { + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return FAILURE; } diff --git a/ext/session/tests/bug72562.phpt b/ext/session/tests/bug72562.phpt new file mode 100644 index 0000000000..d85e48b069 --- /dev/null +++ b/ext/session/tests/bug72562.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #72562: Use After Free in unserialize() with Unexpected Session Deserialization +--SKIPIF-- +<?php include('skipif.inc'); ?> +--FILE-- +<?php + +ini_set('session.serialize_handler', 'php_binary'); +session_start(); +$sess = "\x1xi:1;\x2y"; +session_decode($sess); +$uns_1 = '{'; +$out_1[] = unserialize($uns_1); +unset($out_1); +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; +for ($i = 0; $i < 5; $i++) { + $v[$i] = $fakezval.$i; +} +$uns_2 = 'R:2;'; +$out_2 = unserialize($uns_2); +var_dump($out_2); + +function ptr2str($ptr) +{ + $out = ''; + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + return $out; +} +?> +--EXPECTF-- +Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/bug72562.php on line %d + +Notice: unserialize(): Error at offset 0 of 1 bytes in %s/bug72562.php on line %d + +Notice: unserialize(): Error at offset 4 of 4 bytes in %s/bug72562.php on line %d +bool(false) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index d5e21f911c..b88cdcd14c 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -473,7 +473,7 @@ static void php_snmp_session_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) static void php_snmp_object_free_storage(void *object TSRMLS_DC) { php_snmp_object *intern = (php_snmp_object *)object; - + if (!intern) { return; } @@ -481,7 +481,7 @@ static void php_snmp_object_free_storage(void *object TSRMLS_DC) netsnmp_session_free(&(intern->session)); zend_object_std_dtor(&intern->zo TSRMLS_CC); - + efree(intern); } @@ -501,7 +501,7 @@ static zend_object_value php_snmp_object_new(zend_class_entry *class_type TSRMLS retval.handlers = (zend_object_handlers *) &php_snmp_object_handlers; return retval; - + } /* {{{ php_snmp_error @@ -554,7 +554,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D char *dbuf = (char *)NULL; int buflen = sizeof(sbuf) - 1; int val_len = vars->val_len; - + /* use emalloc() for large values, use static array otherwize */ /* There is no way to know the size of buffer snprint_value() needs in order to print a value there. @@ -700,7 +700,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D * SNMP object fetcher/setter for all SNMP versions * */ -static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, +static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, struct snmp_session *session, struct objid_query *objid_query) { @@ -719,7 +719,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, /* we start with retval=FALSE. If any actual data is acquired, retval will be set to appropriate type */ RETVAL_FALSE; - + /* reset errno and errstr */ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, ""); @@ -803,8 +803,8 @@ retry: } for (vars = response->variables; vars; vars = vars->next_variable) { /* do not output errors as values */ - if ( vars->type == SNMP_ENDOFMIBVIEW || - vars->type == SNMP_NOSUCHOBJECT || + if ( vars->type == SNMP_ENDOFMIBVIEW || + vars->type == SNMP_NOSUCHOBJECT || vars->type == SNMP_NOSUCHINSTANCE ) { if ((st & SNMP_CMD_WALK) && Z_TYPE_P(return_value) == IS_ARRAY) { break; @@ -814,8 +814,8 @@ retry: php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, buf2); continue; } - - if ((st & SNMP_CMD_WALK) && + + if ((st & SNMP_CMD_WALK) && (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { /* not part of this subtree */ if (Z_TYPE_P(return_value) == IS_ARRAY) { /* some records are fetched already, shut down further lookup */ keepwalking = 0; @@ -1099,7 +1099,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu efree(objid_query->vars); return FALSE; } - } else { + } else { memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib)); objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid); } @@ -1435,7 +1435,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) int session_less_mode = (getThis() == NULL); php_snmp_object *snmp_object; php_snmp_object glob_snmp_object; - + objid_query.max_repetitions = -1; objid_query.non_repeaters = 0; objid_query.valueretrieval = SNMP_G(valueretrieval); @@ -1548,7 +1548,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) } php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query); - + efree(objid_query.vars); if (session_less_mode) { @@ -1561,7 +1561,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) } /* }}} */ -/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) Fetch a SNMP object */ PHP_FUNCTION(snmpget) { @@ -1569,7 +1569,7 @@ PHP_FUNCTION(snmpget) } /* }}} */ -/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) Fetch a SNMP object */ PHP_FUNCTION(snmpgetnext) { @@ -1577,7 +1577,7 @@ PHP_FUNCTION(snmpgetnext) } /* }}} */ -/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) Return all objects under the specified object id */ PHP_FUNCTION(snmpwalk) { @@ -1593,7 +1593,7 @@ PHP_FUNCTION(snmprealwalk) } /* }}} */ -/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) +/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) Set the value of a SNMP object */ PHP_FUNCTION(snmpset) { @@ -1640,7 +1640,7 @@ PHP_FUNCTION(snmp_set_enum_print) netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1); RETURN_TRUE; -} +} /* }}} */ /* {{{ proto bool snmp_set_oid_output_format(int oid_format) @@ -1668,10 +1668,10 @@ PHP_FUNCTION(snmp_set_oid_output_format) RETURN_FALSE; break; } -} +} /* }}} */ -/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) Fetch a SNMP object */ PHP_FUNCTION(snmp2_get) { @@ -1679,7 +1679,7 @@ PHP_FUNCTION(snmp2_get) } /* }}} */ -/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) Fetch a SNMP object */ PHP_FUNCTION(snmp2_getnext) { @@ -1687,7 +1687,7 @@ PHP_FUNCTION(snmp2_getnext) } /* }}} */ -/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) +/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) Return all objects under the specified object id */ PHP_FUNCTION(snmp2_walk) { @@ -1703,7 +1703,7 @@ PHP_FUNCTION(snmp2_real_walk) } /* }}} */ -/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) +/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) Set the value of a SNMP object */ PHP_FUNCTION(snmp2_set) { @@ -1819,7 +1819,7 @@ PHP_METHOD(snmp, __construct) snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC); zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); - + if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; @@ -1841,7 +1841,7 @@ PHP_METHOD(snmp, __construct) if (snmp_object->session) { netsnmp_session_free(&(snmp_object->session)); } - + if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) { return; } @@ -1855,7 +1855,7 @@ PHP_METHOD(snmp, __construct) } /* }}} */ -/* {{{ proto bool SNMP::close() +/* {{{ proto bool SNMP::close() Close SNMP session */ PHP_METHOD(snmp, close) { @@ -1898,7 +1898,7 @@ PHP_METHOD(snmp, walk) } /* }}} */ -/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value) +/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value) Set the value of a SNMP object */ PHP_METHOD(snmp, set) { @@ -1916,7 +1916,7 @@ PHP_METHOD(snmp, setSecurity) int argc = ZEND_NUM_ARGS(); snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC); - + if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) { RETURN_FALSE; @@ -1930,7 +1930,7 @@ PHP_METHOD(snmp, setSecurity) } /* }}} */ -/* {{{ proto long SNMP::getErrno() +/* {{{ proto long SNMP::getErrno() Get last error code number */ PHP_METHOD(snmp, getErrno) { @@ -1944,7 +1944,7 @@ PHP_METHOD(snmp, getErrno) } /* }}} */ -/* {{{ proto long SNMP::getError() +/* {{{ proto long SNMP::getError() Get last error message */ PHP_METHOD(snmp, getError) { @@ -2093,6 +2093,14 @@ static int php_snmp_has_property(zval *object, zval *member, int has_set_exists, } /* }}} */ +static HashTable *php_snmp_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */ +{ + *gc_data = NULL; + *gc_data_count = 0; + return zend_std_get_properties(object TSRMLS_CC); +} +/* }}} */ + /* {{{ php_snmp_get_properties(zval *object) Returns all object properties. Injects SNMP properties into object on first call */ static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC) @@ -2135,23 +2143,23 @@ static int php_snmp_read_info(php_snmp_object *snmp_object, zval **retval TSRMLS if (snmp_object->session == NULL) { return SUCCESS; } - + MAKE_STD_ZVAL(val); ZVAL_STRINGL(val, snmp_object->session->peername, strlen(snmp_object->session->peername), 1); add_assoc_zval(*retval, "hostname", val); - + MAKE_STD_ZVAL(val); ZVAL_LONG(val, snmp_object->session->remote_port); add_assoc_zval(*retval, "port", val); - + MAKE_STD_ZVAL(val); ZVAL_LONG(val, snmp_object->session->timeout); add_assoc_zval(*retval, "timeout", val); - + MAKE_STD_ZVAL(val); ZVAL_LONG(val, snmp_object->session->retries); add_assoc_zval(*retval, "retries", val); - + return SUCCESS; } /* }}} */ @@ -2224,7 +2232,7 @@ static int php_snmp_write_max_oids(php_snmp_object *snmp_object, zval *newval TS } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "max_oids should be positive integer or NULL, got %ld", Z_LVAL_P(newval)); } - + if (newval == &ztmp) { zval_dtor(newval); } @@ -2252,7 +2260,7 @@ static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *new php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", Z_LVAL_P(newval)); ret = FAILURE; } - + if (newval == &ztmp) { zval_dtor(newval); } @@ -2295,7 +2303,7 @@ static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval * convert_to_long(&ztmp); newval = &ztmp; } - + switch(Z_LVAL_P(newval)) { case NETSNMP_OID_OUTPUT_SUFFIX: case NETSNMP_OID_OUTPUT_MODULE: @@ -2330,7 +2338,7 @@ static int php_snmp_write_exceptions_enabled(php_snmp_object *snmp_object, zval newval = &ztmp; } - snmp_object->exceptions_enabled = Z_LVAL_P(newval); + snmp_object->exceptions_enabled = Z_LVAL_P(newval); if (newval == &ztmp) { zval_dtor(newval); @@ -2399,6 +2407,7 @@ PHP_MINIT_FUNCTION(snmp) php_snmp_object_handlers.write_property = php_snmp_write_property; php_snmp_object_handlers.has_property = php_snmp_has_property; php_snmp_object_handlers.get_properties = php_snmp_get_properties; + php_snmp_object_handlers.get_gc = php_snmp_get_gc; /* Register SNMP Class */ INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods); @@ -2465,7 +2474,7 @@ PHP_MINIT_FUNCTION(snmp) PHP_MSHUTDOWN_FUNCTION(snmp) { snmp_shutdown("snmpapp"); - + zend_hash_destroy(&php_snmp_properties); return SUCCESS; diff --git a/ext/snmp/tests/bug72479.phpt b/ext/snmp/tests/bug72479.phpt new file mode 100644 index 0000000000..0308754360 --- /dev/null +++ b/ext/snmp/tests/bug72479.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #72479: Use After Free Vulnerability in SNMP with GC and unserialize() +--SKIPIF-- +<?php +require_once(dirname(__FILE__).'/skipif.inc'); +?> +--FILE-- +<?php +$arr = [1, [1, 2, 3, 4, 5], 3, 4, 5]; +$poc = 'a:3:{i:1;N;i:2;O:4:"snmp":1:{s:11:"quick_print";'.serialize($arr).'}i:1;R:7;}'; +$out = unserialize($poc); +gc_collect_cycles(); +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; +for ($i = 0; $i < 5; $i++) { + $v[$i] = $fakezval.$i; +} +var_dump($out[1]); + +function ptr2str($ptr) +{ + $out = ''; + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + return $out; +} +?> +--EXPECT-- +int(1)
\ No newline at end of file diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 57de98b15d..f7776d6e5b 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3986,21 +3986,24 @@ PHP_FUNCTION(long2ip) * System Functions * ********************/ -/* {{{ proto string getenv(string varname) +/* {{{ proto string getenv(string varname[, bool local_only]) Get the value of an environment variable */ PHP_FUNCTION(getenv) { char *ptr, *str; int str_len; + zend_bool local_only = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &local_only) == FAILURE) { RETURN_FALSE; } - /* SAPI method returns an emalloc()'d string */ - ptr = sapi_getenv(str, str_len TSRMLS_CC); - if (ptr) { - RETURN_STRING(ptr, 0); + if (!local_only) { + /* SAPI method returns an emalloc()'d string */ + ptr = sapi_getenv(str, str_len TSRMLS_CC); + if (ptr) { + RETURN_STRING(ptr, 0); + } } #ifdef PHP_WIN32 { diff --git a/ext/xmlrpc/libxmlrpc/simplestring.c b/ext/xmlrpc/libxmlrpc/simplestring.c index a084d0e64f..c88754fb9a 100644 --- a/ext/xmlrpc/libxmlrpc/simplestring.c +++ b/ext/xmlrpc/libxmlrpc/simplestring.c @@ -5,28 +5,28 @@ Epinions.com may be contacted at feedback@epinions-inc.com */ -/* - Copyright 2000 Epinions, Inc. +/* + Copyright 2000 Epinions, Inc. - Subject to the following 3 conditions, Epinions, Inc. permits you, free - of charge, to (a) use, copy, distribute, modify, perform and display this - software and associated documentation files (the "Software"), and (b) - permit others to whom the Software is furnished to do so as well. + Subject to the following 3 conditions, Epinions, Inc. permits you, free + of charge, to (a) use, copy, distribute, modify, perform and display this + software and associated documentation files (the "Software"), and (b) + permit others to whom the Software is furnished to do so as well. - 1) The above copyright notice and this permission notice shall be included - without modification in all copies or substantial portions of the - Software. + 1) The above copyright notice and this permission notice shall be included + without modification in all copies or substantial portions of the + Software. - 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF - ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY - IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE OR NONINFRINGEMENT. + 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF + ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY + IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE OR NONINFRINGEMENT. - 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, - SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT - OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING - NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH - DAMAGES. + 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT + OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING + NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH + DAMAGES. */ @@ -71,7 +71,7 @@ static const char rcsid[] = "#(@) $Id$"; * * Oh, and it is also binary safe, ie it can handle strings with embedded NULLs, * so long as the real length is passed in. - * + * * And the masses rejoiced. * * BUGS @@ -136,7 +136,7 @@ static void simplestring_init_str(simplestring* string) { * NOTES * This function is very fast as it does not de-allocate any memory. * SEE ALSO - * + * * SOURCE */ void simplestring_clear(simplestring* string) { @@ -172,6 +172,9 @@ void simplestring_free(simplestring* string) { } /******/ +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif /****f* FUNC/simplestring_addn * NAME * simplestring_addn @@ -190,18 +193,31 @@ void simplestring_free(simplestring* string) { * simplestring_add () * SOURCE */ -void simplestring_addn(simplestring* target, const char* source, int add_len) { +void simplestring_addn(simplestring* target, const char* source, size_t add_len) { + size_t newsize = target->size, incr = 0; if(target && source) { if(!target->str) { simplestring_init_str(target); } + + if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) { + /* check for overflows, if there's a potential overflow do nothing */ + return; + } + if(target->len + add_len + 1 > target->size) { /* newsize is current length + new length */ - int newsize = target->len + add_len + 1; - int incr = target->size * 2; + newsize = target->len + add_len + 1; + incr = target->size * 2; /* align to SIMPLESTRING_INCR increments */ - newsize = newsize - (newsize % incr) + incr; + if (incr) { + newsize = newsize - (newsize % incr) + incr; + } + if(newsize < (target->len + add_len + 1)) { + /* some kind of overflow happened */ + return; + } target->str = (char*)realloc(target->str, newsize); target->size = target->str ? newsize : 0; diff --git a/ext/xmlrpc/libxmlrpc/simplestring.h b/ext/xmlrpc/libxmlrpc/simplestring.h index c5d98cf1d8..7e88cd0ef0 100644 --- a/ext/xmlrpc/libxmlrpc/simplestring.h +++ b/ext/xmlrpc/libxmlrpc/simplestring.h @@ -63,7 +63,7 @@ void simplestring_init(simplestring* string); void simplestring_clear(simplestring* string); void simplestring_free(simplestring* string); void simplestring_add(simplestring* string, const char* add); -void simplestring_addn(simplestring* string, const char* add, int add_len); +void simplestring_addn(simplestring* string, const char* add, size_t add_len); #ifdef __cplusplus } diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index 1cd134ecfb..2095ddf838 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -229,7 +229,7 @@ php_stream *php_stream_zip_open(const char *filename, const char *path, const ch self = emalloc(sizeof(*self)); self->za = stream_za; - self->zf = zf; + self->zf = zf; self->stream = NULL; self->cursor = 0; stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode); @@ -256,7 +256,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { - int path_len; + size_t path_len; char *file_basename; size_t file_basename_len; @@ -265,7 +265,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, struct zip *za; struct zip_file *zf = NULL; char *fragment; - int fragment_len; + size_t fragment_len; int err; php_stream *stream = NULL; @@ -308,7 +308,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, self = emalloc(sizeof(*self)); self->za = za; - self->zf = zf; + self->zf = zf; self->stream = NULL; self->cursor = 0; stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode); diff --git a/main/SAPI.c b/main/SAPI.c index eebf1f0757..49ffc1c9a4 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -128,7 +128,7 @@ PHP_FUNCTION(header_register_callback) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback_func) == FAILURE) { return; } - + if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) { efree(callback_name); RETURN_FALSE; @@ -156,10 +156,10 @@ static void sapi_run_header_callback(TSRMLS_D) char *callback_name = NULL; char *callback_error = NULL; zval *retval_ptr = NULL; - + if (zend_fcall_info_init(SG(callback_func), 0, &fci, &SG(fci_cache), &callback_name, &callback_error TSRMLS_CC) == SUCCESS) { fci.retval_ptr_ptr = &retval_ptr; - + error = zend_call_function(&fci, &SG(fci_cache) TSRMLS_CC); if (error == FAILURE) { goto callback_failed; @@ -170,13 +170,13 @@ static void sapi_run_header_callback(TSRMLS_D) callback_failed: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the sapi_header_callback"); } - + if (callback_name) { efree(callback_name); } if (callback_error) { efree(callback_error); - } + } } SAPI_API void sapi_handle_post(void *arg TSRMLS_DC) @@ -407,11 +407,11 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D) if (SG(request_info).headers_read == 1) return; SG(request_info).headers_read = 1; - zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), + zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0); SG(sapi_headers).send_default_content_type = 1; - /* SG(sapi_headers).http_response_code = 200; */ + /* SG(sapi_headers).http_response_code = 200; */ SG(sapi_headers).http_status_line = NULL; SG(sapi_headers).mimetype = NULL; SG(read_post_bytes) = 0; @@ -423,7 +423,7 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D) SG(global_request_time) = 0; /* - * It's possible to override this general case in the activate() callback, + * It's possible to override this general case in the activate() callback, * if necessary. */ if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) { @@ -509,7 +509,7 @@ static void sapi_send_headers_free(TSRMLS_D) SG(sapi_headers).http_status_line = NULL; } } - + SAPI_API void sapi_deactivate(TSRMLS_D) { zend_llist_destroy(&SG(sapi_headers).headers); @@ -583,7 +583,7 @@ static int sapi_extract_response_code(const char *header_line) break; } } - + return code; } @@ -603,7 +603,7 @@ static void sapi_update_response_code(int ncode TSRMLS_DC) SG(sapi_headers).http_response_code = ncode; } -/* +/* * since zend_llist_del_element only remove one matched item once, * we should remove them by ourself */ @@ -639,7 +639,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo { sapi_header_line ctr = {0}; int r; - + ctr.line = header_line; ctr.line_len = header_line_len; @@ -733,7 +733,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC) } while(header_line_len && isspace(header_line[header_line_len-1])); header_line[header_line_len]='\0'; } - + if (op == SAPI_HEADER_DELETE) { if (strchr(header_line, ':')) { efree(header_line); @@ -771,7 +771,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC) sapi_header.header_len = header_line_len; /* Check the header for a few cases that we have special support for in SAPI */ - if (header_line_len>=5 + if (header_line_len>=5 && !strncasecmp(header_line, "HTTP/", 5)) { /* filter out the response code */ sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC); @@ -830,8 +830,8 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC) /* Return a Found Redirect if one is not already specified */ if (http_response_code) { /* user specified redirect code */ sapi_update_response_code(http_response_code TSRMLS_CC); - } else if (SG(request_info).proto_num > 1000 && - SG(request_info).request_method && + } else if (SG(request_info).proto_num > 1000 && + SG(request_info).request_method && strcmp(SG(request_info).request_method, "HEAD") && strcmp(SG(request_info).request_method, "GET")) { sapi_update_response_code(303 TSRMLS_CC); @@ -1020,7 +1020,11 @@ SAPI_API struct stat *sapi_get_stat(TSRMLS_D) SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC) { - if (sapi_module.getenv) { + if (!strncasecmp(name, "HTTP_PROXY", name_len)) { + /* Ugly fix for HTTP_PROXY issue, see bug #72573 */ + return NULL; + } + if (sapi_module.getenv) { char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC); if (tmp) { value = estrdup(tmp); diff --git a/main/php_variables.c b/main/php_variables.c index 58f1c7c945..018e906582 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -47,7 +47,7 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zva { zval new_entry; assert(strval != NULL); - + /* Prepare value */ Z_STRLEN(new_entry) = str_len; Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry)); @@ -85,7 +85,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars while (*var_name && *var_name==' ') { var_name++; } - + /* * Prepare variable name */ @@ -171,7 +171,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars return; } *ip = 0; - new_idx_len = strlen(index_s); + new_idx_len = strlen(index_s); } if (!index) { @@ -214,7 +214,7 @@ plain_var: zval_ptr_dtor(&gpc_element); } } else { - /* + /* * According to rfc2965, more specific paths are listed above the less specific ones. * If we encounter a duplicate cookie name, we should skip it, since it is not possible * to have the same (plain text) cookie name for the same path and we should not overwrite @@ -367,7 +367,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) int free_buffer = 0; char *strtok_buf = NULL; long count = 0; - + switch (arg) { case PARSE_POST: case PARSE_GET: @@ -440,9 +440,9 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) separator = ";\0"; break; } - + var = php_strtok_r(res, separator, &strtok_buf); - + while (var) { val = strchr(var, '='); @@ -537,11 +537,11 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC) zval *arr, *argc, *tmp; int count = 0; char *ss, *space; - + if (!(SG(request_info).argc || track_vars_array)) { return; } - + ALLOC_INIT_ZVAL(arr); array_init(arr); @@ -602,7 +602,7 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC) Z_ADDREF_P(argc); zend_hash_update(&EG(symbol_table), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL); zend_hash_update(&EG(symbol_table), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL); - } + } if (track_vars_array) { Z_ADDREF_P(arr); Z_ADDREF_P(argc); @@ -732,7 +732,7 @@ static zend_bool php_auto_globals_create_get(const char *name, uint name_len TSR zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); Z_ADDREF_P(vars); - + return 0; /* don't rearm */ } @@ -758,7 +758,7 @@ static zend_bool php_auto_globals_create_post(const char *name, uint name_len TS zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); Z_ADDREF_P(vars); - + return 0; /* don't rearm */ } @@ -781,7 +781,7 @@ static zend_bool php_auto_globals_create_cookie(const char *name, uint name_len zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); Z_ADDREF_P(vars); - + return 0; /* don't rearm */ } @@ -800,10 +800,27 @@ static zend_bool php_auto_globals_create_files(const char *name, uint name_len T zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); Z_ADDREF_P(vars); - + return 0; /* don't rearm */ } +/* Upgly hack to fix HTTP_PROXY issue, see bug #72573 */ +static void check_http_proxy(HashTable *var_table) +{ + if (zend_hash_exists(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"))) { + char *local_proxy = getenv("HTTP_PROXY"); + + if (!local_proxy) { + zend_hash_del(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY")); + } else { + zval *local_zval; + ALLOC_INIT_ZVAL(local_zval); + ZVAL_STRING(local_zval, local_proxy, 1); + zend_hash_update(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"), &local_zval, sizeof(zval **), NULL); + } + } +} + static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC) { if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) { @@ -812,7 +829,7 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len if (PG(register_argc_argv)) { if (SG(request_info).argc) { zval **argc, **argv; - + if (zend_hash_find(&EG(symbol_table), "argc", sizeof("argc"), (void**)&argc) == SUCCESS && zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) { Z_ADDREF_PP(argc); @@ -824,7 +841,7 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC); } } - + } else { zval *server_vars=NULL; ALLOC_ZVAL(server_vars); @@ -836,9 +853,10 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len PG(http_globals)[TRACK_VARS_SERVER] = server_vars; } + check_http_proxy(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])); zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL); Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]); - + return 0; /* don't rearm */ } @@ -852,11 +870,12 @@ static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSR zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]); } PG(http_globals)[TRACK_VARS_ENV] = env_vars; - + if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) { php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC); } + check_http_proxy(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])); zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL); Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]); |