summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemi Collet <fedora@famillecollet.com>2016-04-27 09:04:26 +0200
committerRemi Collet <fedora@famillecollet.com>2016-04-27 09:04:26 +0200
commit42bb2c9221ab019a8d42a11644eceaf7b05d39d9 (patch)
treebebe4fa519a02a5192efb9f8ce0c276ee97642ba
parente3c0a2ba77c93252efd1c70ffab1b2ade30c9d14 (diff)
php 5.4 add security patches, backported from 5.5.35
-rw-r--r--bug71912.patch60
-rw-r--r--bug72061.patch99
-rw-r--r--bug72093.patch249
-rw-r--r--bug72094.patch75
-rw-r--r--bug72099.patch455
-rw-r--r--php54.spec18
6 files changed, 956 insertions, 0 deletions
diff --git a/bug71912.patch b/bug71912.patch
new file mode 100644
index 0000000..9e2247b
--- /dev/null
+++ b/bug71912.patch
@@ -0,0 +1,60 @@
+Backported for 5.4 from 5.5.35 by Remi Collet
+Binary diff removed
+
+From b15f0ecc0f34364fd7ce924b4164be4e8198ff93 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 18 Apr 2016 22:20:22 -0700
+Subject: [PATCH] Fix for bug #71912 (libgd: signedness vulnerability)
+
+---
+ ext/gd/libgd/gd_gd2.c | 3 +++
+ ext/gd/tests/bug71912.phpt | 16 ++++++++++++++++
+ ext/gd/tests/invalid_neg_size.gd2 | Bin 0 -> 1676 bytes
+ 3 files changed, 19 insertions(+)
+ create mode 100644 ext/gd/tests/bug71912.phpt
+ create mode 100644 ext/gd/tests/invalid_neg_size.gd2
+
+diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c
+index efc6ef4..1794ca9 100644
+--- a/ext/gd/libgd/gd_gd2.c
++++ b/ext/gd/libgd/gd_gd2.c
+@@ -150,6 +150,9 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in
+ if (gdGetInt(&cidx[i].size, in) != 1) {
+ goto fail1;
+ }
++ if (cidx[i].offset < 0 || cidx[i].size < 0) {
++ goto fail1;
++ }
+ }
+ *chunkIdx = cidx;
+ }
+
+From 61c7a06e7c19d9b408db1129efa0959a0acbf0b1 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 26 Apr 2016 22:54:58 -0700
+Subject: [PATCH] Fix memory leak
+
+---
+ ext/gd/libgd/gd_gd2.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c
+index 1794ca9..6726fee 100644
+--- a/ext/gd/libgd/gd_gd2.c
++++ b/ext/gd/libgd/gd_gd2.c
+@@ -145,12 +145,15 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in
+ cidx = gdCalloc(sidx, 1);
+ for (i = 0; i < nc; i++) {
+ if (gdGetInt(&cidx[i].offset, in) != 1) {
++ gdFree(cidx);
+ goto fail1;
+ }
+ if (gdGetInt(&cidx[i].size, in) != 1) {
++ gdFree(cidx);
+ goto fail1;
+ }
+ if (cidx[i].offset < 0 || cidx[i].size < 0) {
++ gdFree(cidx);
+ goto fail1;
+ }
+ }
diff --git a/bug72061.patch b/bug72061.patch
new file mode 100644
index 0000000..8319a75
--- /dev/null
+++ b/bug72061.patch
@@ -0,0 +1,99 @@
+Backported for 5.4 from 5.5.35 by Remi Collet
+
+From fd9689745c44341b1bd6af4756f324be8abba2fb Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 24 Apr 2016 12:49:01 -0700
+Subject: [PATCH] Fix bug #72061 - Out-of-bounds reads in zif_grapheme_stripos
+ with negative offset
+
+---
+ ext/intl/grapheme/grapheme_string.c | 12 +++++++-----
+ ext/intl/tests/bug72061.phpt | 15 +++++++++++++++
+ 2 files changed, 22 insertions(+), 5 deletions(-)
+ create mode 100644 ext/intl/tests/bug72061.phpt
+
+diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c
+index 8a094e0..3ba9b51 100644
+--- a/ext/intl/grapheme/grapheme_string.c
++++ b/ext/intl/grapheme/grapheme_string.c
+@@ -112,7 +112,7 @@ PHP_FUNCTION(grapheme_strpos)
+ int haystack_len, needle_len;
+ unsigned char *found;
+ long loffset = 0;
+- int32_t offset = 0;
++ int32_t offset = 0, noffset = 0;
+ int ret_pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) {
+@@ -132,6 +132,7 @@ PHP_FUNCTION(grapheme_strpos)
+
+ /* we checked that it will fit: */
+ offset = (int32_t) loffset;
++ noffset = offset >= 0 ? offset : haystack_len + offset;
+
+ /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
+
+@@ -146,7 +147,7 @@ PHP_FUNCTION(grapheme_strpos)
+ /* quick check to see if the string might be there
+ * I realize that 'offset' is 'grapheme count offset' but will work in spite of that
+ */
+- found = (unsigned char *)php_memnstr((char *)haystack + offset, (char *)needle, needle_len, (char *)haystack + haystack_len);
++ found = (unsigned char *)php_memnstr((char *)haystack + noffset, (char *)needle, needle_len, (char *)haystack + haystack_len);
+
+ /* if it isn't there the we are done */
+ if (!found) {
+@@ -214,12 +215,13 @@ PHP_FUNCTION(grapheme_stripos)
+ is_ascii = ( grapheme_ascii_check(haystack, haystack_len) >= 0 );
+
+ if ( is_ascii ) {
++ int32_t noffset = offset >= 0 ? offset : haystack_len + offset;
+ needle_dup = (unsigned char *)estrndup((char *)needle, needle_len);
+ php_strtolower((char *)needle_dup, needle_len);
+ haystack_dup = (unsigned char *)estrndup((char *)haystack, haystack_len);
+ php_strtolower((char *)haystack_dup, haystack_len);
+
+- found = (unsigned char*) php_memnstr((char *)haystack_dup + offset, (char *)needle_dup, needle_len, (char *)haystack_dup + haystack_len);
++ found = (unsigned char*) php_memnstr((char *)haystack_dup + noffset, (char *)needle_dup, needle_len, (char *)haystack_dup + haystack_len);
+
+ efree(haystack_dup);
+ efree(needle_dup);
+@@ -537,7 +539,7 @@ PHP_FUNCTION(grapheme_substr)
+ efree(ustr);
+ }
+ ubrk_close(bi);
+- RETURN_EMPTY_STRING();
++ RETURN_EMPTY_STRING();
+ }
+
+ /* find the end point of the string to return */
+@@ -576,7 +578,7 @@ PHP_FUNCTION(grapheme_substr)
+ sub_str_end_pos = ustr_len;
+ }
+ }
+-
++
+ if(sub_str_start_pos > sub_str_end_pos) {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: length is beyond start", 1 TSRMLS_CC );
+
+diff --git a/ext/intl/tests/bug72061.phpt b/ext/intl/tests/bug72061.phpt
+new file mode 100644
+index 0000000..782c32c
+--- /dev/null
++++ b/ext/intl/tests/bug72061.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #72061: Out-of-bounds reads in zif_grapheme_stripos with negative offset
++--SKIPIF--
++<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
++--FILE--
++<?php
++
++var_dump(grapheme_stripos(str_repeat("ABCD", 16384), "A", -201));
++var_dump(grapheme_strpos(str_repeat("ABCD", 16384), "A", -201));
++?>
++DONE
++--EXPECT--
++int(65336)
++int(65336)
++DONE
+\ No newline at end of file
diff --git a/bug72093.patch b/bug72093.patch
new file mode 100644
index 0000000..e675e37
--- /dev/null
+++ b/bug72093.patch
@@ -0,0 +1,249 @@
+Backported for 5.4 from 5.5.35 by Remi Collet
+
+From d650063a0457aec56364e4005a636dc6c401f9cd Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 24 Apr 2016 18:33:32 -0700
+Subject: [PATCH] Fix bug #72093: bcpowmod accepts negative scale and corrupts
+ _one_ definition
+
+We can not modify result since it can be copy of _zero_ or _one_, etc. and
+"copy" in bcmath is just bumping the refcount.
+---
+ ext/bcmath/bcmath.c | 60 +++++++++++++++++++++++++++++-------------
+ ext/bcmath/tests/bug72093.phpt | 13 +++++++++
+ main/php_version.h | 6 ++---
+ 3 files changed, 57 insertions(+), 22 deletions(-)
+ create mode 100644 ext/bcmath/tests/bug72093.phpt
+
+diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c
+index 02177e4..dd69115 100644
+--- a/ext/bcmath/bcmath.c
++++ b/ext/bcmath/bcmath.c
+@@ -201,6 +201,21 @@ static void php_str2num(bc_num *num, char *str TSRMLS_DC)
+ }
+ /* }}} */
+
++/* {{{ split_bc_num
++ Convert to bc_num detecting scale */
++static bc_num split_bc_num(bc_num num) {
++ bc_num newnum;
++ if (num->n_refs >= 1) {
++ return num;
++ }
++ newnum = _bc_new_num_ex(0, 0, 0);
++ *newnum = *num;
++ newnum->n_refs = 1;
++ num->n_refs--;
++ return newnum;
++}
++/* }}} */
++
+ /* {{{ proto string bcadd(string left_operand, string right_operand [, int scale])
+ Returns the sum of two arbitrary precision numbers */
+ PHP_FUNCTION(bcadd)
+@@ -214,7 +229,7 @@ PHP_FUNCTION(bcadd)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+@@ -225,11 +240,12 @@ PHP_FUNCTION(bcadd)
+ php_str2num(&first, left TSRMLS_CC);
+ php_str2num(&second, right TSRMLS_CC);
+ bc_add (first, second, &result, scale);
+-
++
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+-
++
+ Z_STRVAL_P(return_value) = bc_num2str(result);
+ Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
+ Z_TYPE_P(return_value) = IS_STRING;
+@@ -253,7 +269,7 @@ PHP_FUNCTION(bcsub)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+@@ -266,6 +282,7 @@ PHP_FUNCTION(bcsub)
+ bc_sub (first, second, &result, scale);
+
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+
+@@ -292,11 +309,11 @@ PHP_FUNCTION(bcmul)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+-
++
+ bc_init_num(&first TSRMLS_CC);
+ bc_init_num(&second TSRMLS_CC);
+ bc_init_num(&result TSRMLS_CC);
+@@ -305,6 +322,7 @@ PHP_FUNCTION(bcmul)
+ bc_multiply (first, second, &result, scale TSRMLS_CC);
+
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+
+@@ -331,11 +349,11 @@ PHP_FUNCTION(bcdiv)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+-
++
+ bc_init_num(&first TSRMLS_CC);
+ bc_init_num(&second TSRMLS_CC);
+ bc_init_num(&result TSRMLS_CC);
+@@ -345,6 +363,7 @@ PHP_FUNCTION(bcdiv)
+ switch (bc_divide(first, second, &result, scale TSRMLS_CC)) {
+ case 0: /* OK */
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+ Z_STRVAL_P(return_value) = bc_num2str(result);
+@@ -374,13 +393,13 @@ PHP_FUNCTION(bcmod)
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &left, &left_len, &right, &right_len) == FAILURE) {
+ return;
+ }
+-
++
+ bc_init_num(&first TSRMLS_CC);
+ bc_init_num(&second TSRMLS_CC);
+ bc_init_num(&result TSRMLS_CC);
+ bc_str2num(&first, left, 0 TSRMLS_CC);
+ bc_str2num(&second, right, 0 TSRMLS_CC);
+-
++
+ switch (bc_modulo(first, second, &result, 0 TSRMLS_CC)) {
+ case 0:
+ Z_STRVAL_P(return_value) = bc_num2str(result);
+@@ -391,7 +410,7 @@ PHP_FUNCTION(bcmod)
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
+ break;
+ }
+-
++
+ bc_free_num(&first);
+ bc_free_num(&second);
+ bc_free_num(&result);
+@@ -424,8 +443,9 @@ PHP_FUNCTION(bcpowmod)
+ scale_int = (int) ((int)scale < 0) ? 0 : scale;
+
+ if (bc_raisemod(first, second, mod, &result, scale_int TSRMLS_CC) != -1) {
+- if (result->n_scale > scale) {
+- result->n_scale = scale;
++ if (result->n_scale > scale_int) {
++ result = split_bc_num(result);
++ result->n_scale = scale_int;
+ }
+ Z_STRVAL_P(return_value) = bc_num2str(result);
+ Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
+@@ -433,7 +453,7 @@ PHP_FUNCTION(bcpowmod)
+ } else {
+ RETVAL_FALSE;
+ }
+-
++
+ bc_free_num(&first);
+ bc_free_num(&second);
+ bc_free_num(&mod);
+@@ -455,7 +475,7 @@ PHP_FUNCTION(bcpow)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+@@ -468,6 +488,7 @@ PHP_FUNCTION(bcpow)
+ bc_raise (first, second, &result, scale TSRMLS_CC);
+
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+
+@@ -494,16 +515,17 @@ PHP_FUNCTION(bcsqrt)
+ if (zend_parse_parameters(argc TSRMLS_CC, "s|l", &left, &left_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 2) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+
+ bc_init_num(&result TSRMLS_CC);
+ php_str2num(&result, left TSRMLS_CC);
+-
++
+ if (bc_sqrt (&result, scale TSRMLS_CC) != 0) {
+ if (result->n_scale > scale) {
++ result = split_bc_num(result);
+ result->n_scale = scale;
+ }
+ Z_STRVAL_P(return_value) = bc_num2str(result);
+@@ -531,7 +553,7 @@ PHP_FUNCTION(bccomp)
+ if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
+ return;
+ }
+-
++
+ if (argc == 3) {
+ scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
+ }
+@@ -555,7 +577,7 @@ PHP_FUNCTION(bccomp)
+ PHP_FUNCTION(bcscale)
+ {
+ long new_scale;
+-
++
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &new_scale) == FAILURE) {
+ return;
+ }
+diff --git a/ext/bcmath/tests/bug72093.phpt b/ext/bcmath/tests/bug72093.phpt
+new file mode 100644
+index 0000000..be664b811
+--- /dev/null
++++ b/ext/bcmath/tests/bug72093.phpt
+@@ -0,0 +1,13 @@
++--TEST--
++Bug 72093: bcpowmod accepts negative scale and corrupts _one_ definition
++--SKIPIF--
++<?php if(!extension_loaded("bcmath")) print "skip"; ?>
++--FILE--
++<?php
++var_dump(bcpowmod(1, "A", 128, -200));
++var_dump(bcpowmod(1, 1.2, 1, 1));
++?>
++--EXPECTF--
++string(1) "1"
++bc math warning: non-zero scale in exponent
++string(3) "0.0"
+
diff --git a/bug72094.patch b/bug72094.patch
new file mode 100644
index 0000000..2fa4df7
--- /dev/null
+++ b/bug72094.patch
@@ -0,0 +1,75 @@
+Backported for 5.4 from 5.5.35 by Remi Collet
+Binary diff removed
+
+From 082aecfc3a753ad03be82cf14f03ac065723ec92 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 24 Apr 2016 19:33:52 -0700
+Subject: [PATCH] Fix bug #72094 - Out of bounds heap read access in exif
+ header processing
+
+---
+ ext/exif/exif.c | 17 ++++++++++--
+ ext/exif/tests/bug72094.phpt | 61 ++++++++++++++++++++++++++++++++++++++++++
+ ext/exif/tests/bug72094_1.jpg | Bin 0 -> 140 bytes
+ ext/exif/tests/bug72094_2.jpg | Bin 0 -> 140 bytes
+ ext/exif/tests/bug72094_3.jpg | Bin 0 -> 112 bytes
+ ext/exif/tests/bug72094_4.jpg | Bin 0 -> 32 bytes
+ 6 files changed, 76 insertions(+), 2 deletions(-)
+ create mode 100644 ext/exif/tests/bug72094.phpt
+ create mode 100644 ext/exif/tests/bug72094_1.jpg
+ create mode 100644 ext/exif/tests/bug72094_2.jpg
+ create mode 100644 ext/exif/tests/bug72094_3.jpg
+ create mode 100644 ext/exif/tests/bug72094_4.jpg
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index ff29fdd..f366acc 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2965,7 +2965,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
+ /* When there are any characters after the first NUL */
+ ImageInfo->CopyrightPhotographer = estrdup(value_ptr);
+ ImageInfo->CopyrightEditor = estrndup(value_ptr+length+1, byte_count-length-1);
+- spprintf(&ImageInfo->Copyright, 0, "%s, %s", value_ptr, value_ptr+length+1);
++ spprintf(&ImageInfo->Copyright, 0, "%s, %s", ImageInfo->CopyrightPhotographer, ImageInfo->CopyrightEditor);
+ /* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
+ /* but we are not supposed to change this */
+ /* keep in mind that image_info does not store editor value */
+@@ -3134,6 +3134,11 @@ static int exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *dir_start,
+
+ ImageInfo->sections_found |= FOUND_IFD0;
+
++ if ((dir_start + 2) >= (offset_base+IFDlength)) {
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size");
++ return FALSE;
++ }
++
+ NumDirEntries = php_ifd_get16u(dir_start, ImageInfo->motorola_intel);
+
+ if ((dir_start+2+NumDirEntries*12) > (offset_base+IFDlength)) {
+@@ -3157,6 +3162,10 @@ static int exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *dir_start,
+ * Hack to make it process IDF1 I hope
+ * There are 2 IDFs, the second one holds the keys (0x0201 and 0x0202) to the thumbnail
+ */
++ if ((dir_start+2+12*de + 4) >= (offset_base+IFDlength)) {
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size");
++ return FALSE;
++ }
+ NextDirOffset = php_ifd_get32u(dir_start+2+12*de, ImageInfo->motorola_intel);
+ if (NextDirOffset) {
+ /* the next line seems false but here IFDlength means length of all IFDs */
+@@ -3206,9 +3215,13 @@ static void exif_process_TIFF_in_JPEG(image_info_type *ImageInfo, char *CharBuf,
+ }
+
+ /* Check the next two values for correctness. */
++ if (length < 8) {
++ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF start (1)");
++ return;
++ }
+ exif_value_2a = php_ifd_get16u(CharBuf+2, ImageInfo->motorola_intel);
+ offset_of_ifd = php_ifd_get32u(CharBuf+4, ImageInfo->motorola_intel);
+- if ( exif_value_2a != 0x2a || offset_of_ifd < 0x08) {
++ if (exif_value_2a != 0x2a || offset_of_ifd < 0x08) {
+ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF start (1)");
+ return;
+ }
+
diff --git a/bug72099.patch b/bug72099.patch
new file mode 100644
index 0000000..59042c7
--- /dev/null
+++ b/bug72099.patch
@@ -0,0 +1,455 @@
+Backported for 5.4 from 5.5.35 by Remi Collet
+
+From dccda88f27a084bcbbb30198ace12b4e7ae961cc Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 24 Apr 2016 23:50:57 -0700
+Subject: [PATCH] Fix bug #72099: xml_parse_into_struct segmentation fault
+
+---
+ ext/xml/tests/bug72099.phpt | 17 +++++++
+ ext/xml/xml.c | 106 ++++++++++++++++++++++----------------------
+ 2 files changed, 70 insertions(+), 53 deletions(-)
+ create mode 100644 ext/xml/tests/bug72099.phpt
+
+diff --git a/ext/xml/tests/bug72099.phpt b/ext/xml/tests/bug72099.phpt
+new file mode 100644
+index 0000000..50173a6
+--- /dev/null
++++ b/ext/xml/tests/bug72099.phpt
+@@ -0,0 +1,17 @@
++--TEST--
++Bug #72099: xml_parse_into_struct segmentation fault
++--SKIPIF--
++<?php
++require_once("skipif.inc");
++?>
++--FILE--
++<?php
++$var1=xml_parser_create_ns();
++$var2=str_repeat("a", 10);
++$var3=[];
++$var4=[];
++xml_parse_into_struct($var1, $var2, $var3, $var4);
++var_dump($var3);
++--EXPECT--
++array(0) {
++}
+\ No newline at end of file
+diff --git a/ext/xml/xml.c b/ext/xml/xml.c
+index 84d4253..5277588 100644
+--- a/ext/xml/xml.c
++++ b/ext/xml/xml.c
+@@ -283,7 +283,7 @@ xml_encoding xml_encodings[] = {
+ static XML_Memory_Handling_Suite php_xml_mem_hdlrs;
+
+ /* True globals, no need for thread safety */
+-static int le_xml_parser;
++static int le_xml_parser;
+
+ /* }}} */
+
+@@ -343,7 +343,7 @@ PHP_MINIT_FUNCTION(xml)
+ REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_WHITE", PHP_XML_OPTION_SKIP_WHITE, CONST_CS|CONST_PERSISTENT);
+
+ /* this object should not be pre-initialised at compile time,
+- as the order of members may vary */
++ as the order of members may vary */
+
+ php_xml_mem_hdlrs.malloc_fcn = php_xml_malloc_wrapper;
+ php_xml_mem_hdlrs.realloc_fcn = php_xml_realloc_wrapper;
+@@ -404,7 +404,7 @@ static zval *_xml_xmlchar_zval(const XML_Char *s, int len, const XML_Char *encod
+ {
+ zval *ret;
+ MAKE_STD_ZVAL(ret);
+-
++
+ if (s == NULL) {
+ ZVAL_FALSE(ret);
+ return ret;
+@@ -422,7 +422,7 @@ static zval *_xml_xmlchar_zval(const XML_Char *s, int len, const XML_Char *encod
+ static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+ {
+ xml_parser *parser = (xml_parser *)rsrc->ptr;
+-
++
+ if (parser->parser) {
+ XML_ParserFree(parser->parser);
+ }
+@@ -503,7 +503,7 @@ static void xml_set_handler(zval **handler, zval **data)
+ /* {{{ xml_call_handler() */
+ static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *function_ptr, int argc, zval **argv)
+ {
+- int i;
++ int i;
+ TSRMLS_FETCH();
+
+ if (parser && handler && !EG(exception)) {
+@@ -516,7 +516,7 @@ static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *
+ for (i = 0; i < argc; i++) {
+ args[i] = &argv[i];
+ }
+-
++
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.function_name = handler;
+@@ -540,7 +540,7 @@ static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *
+ Z_TYPE_PP(obj) == IS_OBJECT &&
+ Z_TYPE_PP(method) == IS_STRING) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s::%s()", Z_OBJCE_PP(obj)->name, Z_STRVAL_PP(method));
+- } else
++ } else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler");
+ }
+
+@@ -739,14 +739,14 @@ static void _xml_add_to_info(xml_parser *parser,char *name)
+
+ if (zend_hash_find(Z_ARRVAL_P(parser->info),name,strlen(name) + 1,(void **) &element) == FAILURE) {
+ MAKE_STD_ZVAL(values);
+-
++
+ array_init(values);
+-
++
+ zend_hash_update(Z_ARRVAL_P(parser->info), name, strlen(name)+1, (void *) &values, sizeof(zval*), (void **) &element);
+- }
+-
++ }
++
+ add_next_index_long(*element,parser->curtag);
+-
++
+ parser->curtag++;
+ }
+ /* }}} */
+@@ -798,11 +798,11 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch
+
+ efree(att);
+ }
+-
++
+ if ((retval = xml_call_handler(parser, parser->startElementHandler, parser->startElementPtr, 3, args))) {
+ zval_ptr_dtor(&retval);
+ }
+- }
++ }
+
+ if (parser->data) {
+ if (parser->level <= XML_MAXLEVEL) {
+@@ -874,7 +874,7 @@ void _xml_endElementHandler(void *userData, const XML_Char *name)
+ if ((retval = xml_call_handler(parser, parser->endElementHandler, parser->endElementPtr, 2, args))) {
+ zval_ptr_dtor(&retval);
+ }
+- }
++ }
+
+ if (parser->data) {
+ zval *tag;
+@@ -885,13 +885,13 @@ void _xml_endElementHandler(void *userData, const XML_Char *name)
+ MAKE_STD_ZVAL(tag);
+
+ array_init(tag);
+-
++
+ _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
+
+ add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
+ add_assoc_string(tag,"type","close",1);
+ add_assoc_long(tag,"level",parser->level);
+-
++
+ zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
+ }
+
+@@ -923,7 +923,7 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+ if ((retval = xml_call_handler(parser, parser->characterDataHandler, parser->characterDataPtr, 2, args))) {
+ zval_ptr_dtor(&retval);
+ }
+- }
++ }
+
+ if (parser->data) {
+ int i;
+@@ -931,7 +931,7 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+
+ char *decoded_value;
+ int decoded_len;
+-
++
+ decoded_value = xml_utf8_decode(s,len,&decoded_len,parser->target_encoding);
+ for (i = 0; i < decoded_len; i++) {
+ switch (decoded_value[i]) {
+@@ -950,7 +950,7 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+ if (doprint || (! parser->skipwhite)) {
+ if (parser->lastwasopen) {
+ zval **myval;
+-
++
+ /* check if the current tag already has a value - if yes append to that! */
+ if (zend_hash_find(Z_ARRVAL_PP(parser->ctag),"value",sizeof("value"),(void **) &myval) == SUCCESS) {
+ int newlen = Z_STRLEN_PP(myval) + decoded_len;
+@@ -961,7 +961,7 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+ } else {
+ add_assoc_string(*(parser->ctag),"value",decoded_value,0);
+ }
+-
++
+ } else {
+ zval *tag;
+ zval **curtag, **mytype, **myval;
+@@ -984,7 +984,7 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+ }
+ }
+
+- if (parser->level <= XML_MAXLEVEL) {
++ if (parser->level <= XML_MAXLEVEL && parser->level > 0) {
+ MAKE_STD_ZVAL(tag);
+
+ array_init(tag);
+@@ -1046,8 +1046,8 @@ void _xml_defaultHandler(void *userData, const XML_Char *s, int len)
+ /* }}} */
+
+ /* {{{ _xml_unparsedEntityDeclHandler() */
+-void _xml_unparsedEntityDeclHandler(void *userData,
+- const XML_Char *entityName,
++void _xml_unparsedEntityDeclHandler(void *userData,
++ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+@@ -1172,9 +1172,9 @@ static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_supp
+
+ char *ns_param = NULL;
+ int ns_param_len = 0;
+-
++
+ XML_Char *encoding;
+-
++
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, (ns_support ? "|ss": "|s"), &encoding_param, &encoding_param_len, &ns_param, &ns_param_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+@@ -1220,15 +1220,15 @@ static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_supp
+ }
+ /* }}} */
+
+-/* {{{ proto resource xml_parser_create([string encoding])
++/* {{{ proto resource xml_parser_create([string encoding])
+ Create an XML parser */
+ PHP_FUNCTION(xml_parser_create)
+ {
+- php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
++ php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ }
+ /* }}} */
+
+-/* {{{ proto resource xml_parser_create_ns([string encoding [, string sep]])
++/* {{{ proto resource xml_parser_create_ns([string encoding [, string sep]])
+ Create an XML parser */
+ PHP_FUNCTION(xml_parser_create_ns)
+ {
+@@ -1236,7 +1236,7 @@ PHP_FUNCTION(xml_parser_create_ns)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_object(resource parser, object &obj)
++/* {{{ proto int xml_set_object(resource parser, object &obj)
+ Set up object which should be used for callbacks */
+ PHP_FUNCTION(xml_set_object)
+ {
+@@ -1256,7 +1256,7 @@ PHP_FUNCTION(xml_set_object)
+
+ /* please leave this commented - or ask thies@thieso.net before doing it (again) */
+ /* #ifdef ZEND_ENGINE_2
+- zval_add_ref(&parser->object);
++ zval_add_ref(&parser->object);
+ #endif */
+
+ ALLOC_ZVAL(parser->object);
+@@ -1266,7 +1266,7 @@ PHP_FUNCTION(xml_set_object)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_element_handler(resource parser, string shdl, string ehdl)
++/* {{{ proto int xml_set_element_handler(resource parser, string shdl, string ehdl)
+ Set up start and end element handlers */
+ PHP_FUNCTION(xml_set_element_handler)
+ {
+@@ -1286,7 +1286,7 @@ PHP_FUNCTION(xml_set_element_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_character_data_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_character_data_handler(resource parser, string hdl)
+ Set up character data handler */
+ PHP_FUNCTION(xml_set_character_data_handler)
+ {
+@@ -1305,7 +1305,7 @@ PHP_FUNCTION(xml_set_character_data_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_processing_instruction_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_processing_instruction_handler(resource parser, string hdl)
+ Set up processing instruction (PI) handler */
+ PHP_FUNCTION(xml_set_processing_instruction_handler)
+ {
+@@ -1324,7 +1324,7 @@ PHP_FUNCTION(xml_set_processing_instruction_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_default_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_default_handler(resource parser, string hdl)
+ Set up default handler */
+ PHP_FUNCTION(xml_set_default_handler)
+ {
+@@ -1342,7 +1342,7 @@ PHP_FUNCTION(xml_set_default_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_unparsed_entity_decl_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_unparsed_entity_decl_handler(resource parser, string hdl)
+ Set up unparsed entity declaration handler */
+ PHP_FUNCTION(xml_set_unparsed_entity_decl_handler)
+ {
+@@ -1361,7 +1361,7 @@ PHP_FUNCTION(xml_set_unparsed_entity_decl_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_notation_decl_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_notation_decl_handler(resource parser, string hdl)
+ Set up notation declaration handler */
+ PHP_FUNCTION(xml_set_notation_decl_handler)
+ {
+@@ -1379,7 +1379,7 @@ PHP_FUNCTION(xml_set_notation_decl_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_external_entity_ref_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_external_entity_ref_handler(resource parser, string hdl)
+ Set up external entity reference handler */
+ PHP_FUNCTION(xml_set_external_entity_ref_handler)
+ {
+@@ -1397,7 +1397,7 @@ PHP_FUNCTION(xml_set_external_entity_ref_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_start_namespace_decl_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_start_namespace_decl_handler(resource parser, string hdl)
+ Set up character data handler */
+ PHP_FUNCTION(xml_set_start_namespace_decl_handler)
+ {
+@@ -1416,7 +1416,7 @@ PHP_FUNCTION(xml_set_start_namespace_decl_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_set_end_namespace_decl_handler(resource parser, string hdl)
++/* {{{ proto int xml_set_end_namespace_decl_handler(resource parser, string hdl)
+ Set up character data handler */
+ PHP_FUNCTION(xml_set_end_namespace_decl_handler)
+ {
+@@ -1435,7 +1435,7 @@ PHP_FUNCTION(xml_set_end_namespace_decl_handler)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_parse(resource parser, string data [, int isFinal])
++/* {{{ proto int xml_parse(resource parser, string data [, int isFinal])
+ Start parsing an XML document */
+ PHP_FUNCTION(xml_parse)
+ {
+@@ -1471,8 +1471,8 @@ PHP_FUNCTION(xml_parse_into_struct)
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ|Z", &pind, &data, &data_len, &xdata, &info) == FAILURE) {
+ return;
+ }
+-
+- if (info) {
++
++ if (info) {
+ zval_dtor(*info);
+ array_init(*info);
+ }
+@@ -1483,11 +1483,11 @@ PHP_FUNCTION(xml_parse_into_struct)
+ array_init(*xdata);
+
+ parser->data = *xdata;
+-
++
+ if (info) {
+ parser->info = *info;
+ }
+-
++
+ parser->level = 0;
+ parser->ltags = safe_emalloc(XML_MAXLEVEL, sizeof(char *), 0);
+
+@@ -1503,7 +1503,7 @@ PHP_FUNCTION(xml_parse_into_struct)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_get_error_code(resource parser)
++/* {{{ proto int xml_get_error_code(resource parser)
+ Get XML parser error code */
+ PHP_FUNCTION(xml_get_error_code)
+ {
+@@ -1537,7 +1537,7 @@ PHP_FUNCTION(xml_error_string)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_get_current_line_number(resource parser)
++/* {{{ proto int xml_get_current_line_number(resource parser)
+ Get current line number for an XML parser */
+ PHP_FUNCTION(xml_get_current_line_number)
+ {
+@@ -1569,7 +1569,7 @@ PHP_FUNCTION(xml_get_current_column_number)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_get_current_byte_index(resource parser)
++/* {{{ proto int xml_get_current_byte_index(resource parser)
+ Get current byte index for an XML parser */
+ PHP_FUNCTION(xml_get_current_byte_index)
+ {
+@@ -1585,7 +1585,7 @@ PHP_FUNCTION(xml_get_current_byte_index)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_parser_free(resource parser)
++/* {{{ proto int xml_parser_free(resource parser)
+ Free an XML parser */
+ PHP_FUNCTION(xml_parser_free)
+ {
+@@ -1611,7 +1611,7 @@ PHP_FUNCTION(xml_parser_free)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_parser_set_option(resource parser, int option, mixed value)
++/* {{{ proto int xml_parser_set_option(resource parser, int option, mixed value)
+ Set options in an XML parser */
+ PHP_FUNCTION(xml_parser_set_option)
+ {
+@@ -1657,7 +1657,7 @@ PHP_FUNCTION(xml_parser_set_option)
+ }
+ /* }}} */
+
+-/* {{{ proto int xml_parser_get_option(resource parser, int option)
++/* {{{ proto int xml_parser_get_option(resource parser, int option)
+ Get options from an XML parser */
+ PHP_FUNCTION(xml_parser_get_option)
+ {
+@@ -1687,7 +1687,7 @@ PHP_FUNCTION(xml_parser_get_option)
+ }
+ /* }}} */
+
+-/* {{{ proto string utf8_encode(string data)
++/* {{{ proto string utf8_encode(string data)
+ Encodes an ISO-8859-1 string to UTF-8 */
+ PHP_FUNCTION(utf8_encode)
+ {
+@@ -1707,7 +1707,7 @@ PHP_FUNCTION(utf8_encode)
+ }
+ /* }}} */
+
+-/* {{{ proto string utf8_decode(string data)
++/* {{{ proto string utf8_decode(string data)
+ Converts a UTF-8 encoded string to ISO-8859-1 */
+ PHP_FUNCTION(utf8_decode)
+ {
diff --git a/php54.spec b/php54.spec
index 2cd459a..eb3c529 100644
--- a/php54.spec
+++ b/php54.spec
@@ -178,6 +178,11 @@ Patch218: bug71798.patch
Patch219: bug71704.patch
Patch220: bug71527.patch
Patch221: bug64938.patch
+Patch222: bug71912.patch
+Patch223: bug72061.patch
+Patch224: bug72093.patch
+Patch225: bug72094.patch
+Patch226: bug72099.patch
# Fixes for tests
# no_NO issue
@@ -907,6 +912,11 @@ rm -f ext/json/utf8_to_utf16.*
%patch219 -p1 -b .bug71704
%patch220 -p1 -b .bug71527
%patch221 -p1 -b .bug64938
+%patch222 -p1 -b .bug71912
+%patch223 -p1 -b .bug72061
+%patch224 -p1 -b .bug72093
+%patch225 -p1 -b .bug72094
+%patch226 -p1 -b .bug72099
# Fixes for tests
%patch301 -p1 -b .datetests2
@@ -1799,6 +1809,14 @@ fi
* Tue Apr 26 2016 Remi Collet <remi@fedoraproject.org> 5.4.45-8
- Fix #64938: libxml_disable_entity_loader setting is shared
between threads CVE-2015-8866
+- Fix #71912: libgd signedness vulnerability
+- Fix #72061: Out-of-bounds reads in zif_grapheme_stripos
+ with negative offset
+- Fix #72093: bcpowmod accepts negative scale and corrupts
+ _one_ definition
+- Fix #72094: Out of bounds heap read access in exif
+ header processing
+- Fix #72099: xml_parse_into_struct segmentation fault
* Tue Mar 29 2016 Remi Collet <remi@fedoraproject.org> 5.4.45-7
- Fix #71860: Require valid paths for phar filenames