You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

156 lines
6.3 KiB

From: Markus Koschany <apo@debian.org>
Date: Tue, 21 Mar 2017 16:55:58 +0100
Subject: CVE-2016-7478
Backported the zend_unset_property function.
Origin: https://git.php.net/?p=php-src.git;a=commit;h=40e7baab3c90001beee4c8f0ed0ef79ad18ee0d6
---
Zend/zend_API.c | 25 +++++++++++++++++++++++++
Zend/zend_API.h | 1 +
Zend/zend_exceptions.c | 32 ++++++++++++++++++++++++--------
ext/bcmath/libbcmath/src/init.c | 5 ++++-
ext/bcmath/libbcmath/src/outofmem.c | 3 +--
5 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 1a661d7..22b5f5f 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3658,6 +3658,31 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const
}
/* }}} */
+ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
+{
+ zval *property;
+ zend_class_entry *old_scope = EG(scope);
+
+ EG(scope) = scope;
+
+ if (!Z_OBJ_HT_P(object)->unset_property) {
+ const char *class_name;
+ zend_uint class_name_len;
+
+ zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
+
+ zend_error(E_CORE_ERROR, "Property %s of class %s cannot be unset", name, class_name);
+ }
+ MAKE_STD_ZVAL(property);
+ ZVAL_STRINGL(property, name, name_length, 1);
+ Z_OBJ_HT_P(object)->unset_property(object, property, 0 TSRMLS_CC);
+ zval_ptr_dtor(&property);
+
+ EG(scope) = old_scope;
+}
+
+/* }}} */
+
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
{
zval *tmp;
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 84acfca..9cfb1fa 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -325,6 +325,7 @@ ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, c
ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
+ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC);
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index da32ee9..4545c9a 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -221,13 +221,9 @@ ZEND_METHOD(exception, __construct)
/* {{{ proto Exception::__wakeup()
Exception unserialize checks */
#define CHECK_EXC_TYPE(name, type) \
- value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 0 TSRMLS_CC); \
+ value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 1 TSRMLS_CC); \
if(value && Z_TYPE_P(value) != type) { \
- zval *tmp; \
- MAKE_STD_ZVAL(tmp); \
- ZVAL_STRINGL(tmp, name, sizeof(name)-1, 1); \
- Z_OBJ_HANDLER_P(object, unset_property)(object, tmp, 0 TSRMLS_CC); \
- zval_ptr_dtor(&tmp); \
+ zend_unset_property(default_exception_ce, object, name, sizeof(name)-1 TSRMLS_CC); \
}
ZEND_METHOD(exception, __wakeup)
@@ -241,7 +237,12 @@ ZEND_METHOD(exception, __wakeup)
CHECK_EXC_TYPE("file", IS_STRING);
CHECK_EXC_TYPE("line", IS_LONG);
CHECK_EXC_TYPE("trace", IS_ARRAY);
- CHECK_EXC_TYPE("previous", IS_OBJECT);
+ value = zend_read_property(default_exception_ce, object, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
+ if (value && Z_TYPE_P(value) != IS_NULL && (Z_TYPE_P(value) != IS_OBJECT ||
+ !instanceof_function(Z_OBJCE_P(value), default_exception_ce TSRMLS_CC) ||
+ value == object)) {
+ zend_unset_property(default_exception_ce, object, "previous", sizeof("previous")-1 TSRMLS_CC);
+ }
}
/* }}} */
@@ -719,7 +720,11 @@ ZEND_METHOD(exception, __toString)
zval_dtor(&file);
zval_dtor(&line);
- exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 0 TSRMLS_CC);
+ Z_OBJPROP_P(exception)->nApplyCount++;
+ exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
+ if (exception && Z_TYPE_P(exception) == IS_OBJECT && Z_OBJPROP_P(exception)->nApplyCount > 0) {
+ exception = NULL;
+ }
if (trace) {
zval_ptr_dtor(&trace);
@@ -728,6 +733,17 @@ ZEND_METHOD(exception, __toString)
}
zval_dtor(&fname);
+ /* Reset apply counts */
+ exception = getThis();
+ while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), default_exception_ce TSRMLS_CC)) {
+ if(Z_OBJPROP_P(exception)->nApplyCount) {
+ Z_OBJPROP_P(exception)->nApplyCount--;
+ } else {
+ break;
+ }
+ exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
+ }
+
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */
zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
diff --git a/ext/bcmath/libbcmath/src/init.c b/ext/bcmath/libbcmath/src/init.c
index 986ad1d..c51133b 100644
--- a/ext/bcmath/libbcmath/src/init.c
+++ b/ext/bcmath/libbcmath/src/init.c
@@ -49,7 +49,10 @@ _bc_new_num_ex (length, scale, persistent)
int length, scale, persistent;
{
bc_num temp;
-
+ /* PHP Change: add length check */
+ if ((size_t)length+(size_t)scale > INT_MAX) {
+ zend_error(E_ERROR, "Result too long, max is %d", INT_MAX);
+ }
/* PHP Change: malloc() -> pemalloc(), removed free_list code */
temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent);
#if 0
diff --git a/ext/bcmath/libbcmath/src/outofmem.c b/ext/bcmath/libbcmath/src/outofmem.c
index 799a32d..05fa484 100644
--- a/ext/bcmath/libbcmath/src/outofmem.c
+++ b/ext/bcmath/libbcmath/src/outofmem.c
@@ -41,6 +41,5 @@
void bc_out_of_memory (void)
{
- (void) fprintf (stderr, "bcmath: out of memory!\n");
- exit (1);
+ zend_error(E_ERROR, "bcmath: out of memory!");
}