My Alpine packages repository.
https://dryabzhinsky.noip.me/packages/en/alpinelinux-support/
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.
193 lines
6.5 KiB
193 lines
6.5 KiB
From 6045de69c7dedcba3eadf7c4bba424b19c81d00d Mon Sep 17 00:00:00 2001 |
|
From: Stanislav Malyshev <stas@php.net> |
|
Date: Sun, 23 Oct 2016 20:07:47 -0700 |
|
Subject: [PATCH] CVE-2016-9934 |
|
|
|
Fix bug #73331 - do not try to serialize/unserialize objects wddx can not handle |
|
|
|
Proper soltion would be to call serialize/unserialize and deal with the result, |
|
but this requires more work that should be done by wddx maintainer (not me). |
|
|
|
[roberto@debian.org: backported to 5.4.45] |
|
|
|
Bug: https://bugs.php.net/bug.php?id=73331 |
|
Origin: backport, http://git.php.net/?p=php-src.git;a=commitdiff;h=6045de69c7dedcba3eadf7c4bba424b19c81d00d |
|
--- |
|
ext/pdo/pdo_stmt.c | 1 + |
|
ext/wddx/tests/bug45901.phpt | 4 ++- |
|
ext/wddx/tests/bug72790.phpt | 2 +- |
|
ext/wddx/tests/bug73331.phpt | 15 ++++++++++ |
|
ext/wddx/wddx.c | 67 +++++++++++++++++++++++--------------------- |
|
5 files changed, 55 insertions(+), 34 deletions(-) |
|
create mode 100644 ext/wddx/tests/bug73331.phpt |
|
|
|
--- php5.git.orig/ext/pdo/pdo_stmt.c |
|
+++ php5.git/ext/pdo/pdo_stmt.c |
|
@@ -2364,6 +2364,7 @@ |
|
pdo_row_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; /* when removing this a lot of handlers need to be redone */ |
|
pdo_row_ce->create_object = pdo_row_new; |
|
pdo_row_ce->serialize = pdo_row_serialize; |
|
+ pdo_row_ce->unserialize = zend_class_unserialize_deny; |
|
} |
|
|
|
static void free_statement(pdo_stmt_t *stmt TSRMLS_DC) |
|
--- php5.git.orig/ext/wddx/tests/bug45901.phpt |
|
+++ php5.git/ext/wddx/tests/bug45901.phpt |
|
@@ -14,5 +14,7 @@ |
|
echo "DONE"; |
|
?> |
|
--EXPECTF-- |
|
-<wddxPacket version='1.0'><header><comment>Variables</comment></header><data><struct><var name='php_class_name'><string>SimpleXMLElement</string></var><var name='test'><struct><var name='php_class_name'><string>SimpleXMLElement</string></var></struct></var></struct></data></wddxPacket> |
|
+ |
|
+Warning: wddx_serialize_value(): Class SimpleXMLElement can not be serialized in %sbug45901.php on line %d |
|
+<wddxPacket version='1.0'><header><comment>Variables</comment></header><data></data></wddxPacket> |
|
DONE |
|
\ No newline at end of file |
|
--- php5.git.orig/ext/wddx/tests/bug72790.phpt |
|
+++ php5.git/ext/wddx/tests/bug72790.phpt |
|
@@ -1,5 +1,5 @@ |
|
--TEST-- |
|
-Bug 72790: wddx_deserialize null dereference with invalid xml |
|
+Bug #72790: wddx_deserialize null dereference with invalid xml |
|
--SKIPIF-- |
|
<?php |
|
if (!extension_loaded('wddx')) { |
|
--- /dev/null |
|
+++ php5.git/ext/wddx/tests/bug73331.phpt |
|
@@ -0,0 +1,15 @@ |
|
+--TEST-- |
|
+Bug #73331 (NULL Pointer Dereference in WDDX Packet Deserialization with PDORow) |
|
+--SKIPIF-- |
|
+<?php if (!extension_loaded("wddx") || !extension_loaded("pdo")) print "skip"; ?> |
|
+--FILE-- |
|
+<?php |
|
+ |
|
+$wddx = "<wddxPacket version='1.0'><header/><data><struct><var name='php_class_name'><string>PDORow</string></var></struct></data></wddxPacket>"; |
|
+var_dump(wddx_deserialize($wddx)); |
|
+?> |
|
+--EXPECTF-- |
|
+ |
|
+Warning: wddx_deserialize(): Class pdorow can not be unserialized in %s73331.php on line %d |
|
+NULL |
|
+ |
|
--- php5.git.orig/ext/wddx/wddx.c |
|
+++ php5.git/ext/wddx/wddx.c |
|
@@ -465,21 +465,26 @@ |
|
ulong idx; |
|
char tmp_buf[WDDX_BUF_LEN]; |
|
HashTable *objhash, *sleephash; |
|
+ zend_class_entry *ce; |
|
+ PHP_CLASS_ATTRIBUTES; |
|
TSRMLS_FETCH(); |
|
|
|
+ PHP_SET_CLASS_ATTRIBUTES(obj); |
|
+ ce = Z_OBJCE_P(obj); |
|
+ if (!ce || ce->serialize || ce->unserialize) { |
|
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s can not be serialized", class_name); |
|
+ PHP_CLEANUP_CLASS_ATTRIBUTES(); |
|
+ return; |
|
+ } |
|
+ |
|
MAKE_STD_ZVAL(fname); |
|
ZVAL_STRING(fname, "__sleep", 1); |
|
- |
|
/* |
|
* We try to call __sleep() method on object. It's supposed to return an |
|
* array of property names to be serialized. |
|
*/ |
|
if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) { |
|
if (retval && (sleephash = HASH_OF(retval))) { |
|
- PHP_CLASS_ATTRIBUTES; |
|
- |
|
- PHP_SET_CLASS_ATTRIBUTES(obj); |
|
- |
|
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S); |
|
snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR); |
|
php_wddx_add_chunk(packet, tmp_buf); |
|
@@ -488,8 +493,6 @@ |
|
php_wddx_add_chunk_static(packet, WDDX_STRING_E); |
|
php_wddx_add_chunk_static(packet, WDDX_VAR_E); |
|
|
|
- PHP_CLEANUP_CLASS_ATTRIBUTES(); |
|
- |
|
objhash = HASH_OF(obj); |
|
|
|
for (zend_hash_internal_pointer_reset(sleephash); |
|
@@ -510,10 +513,6 @@ |
|
} else { |
|
uint key_len; |
|
|
|
- PHP_CLASS_ATTRIBUTES; |
|
- |
|
- PHP_SET_CLASS_ATTRIBUTES(obj); |
|
- |
|
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S); |
|
snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR); |
|
php_wddx_add_chunk(packet, tmp_buf); |
|
@@ -522,8 +521,6 @@ |
|
php_wddx_add_chunk_static(packet, WDDX_STRING_E); |
|
php_wddx_add_chunk_static(packet, WDDX_VAR_E); |
|
|
|
- PHP_CLEANUP_CLASS_ATTRIBUTES(); |
|
- |
|
objhash = HASH_OF(obj); |
|
for (zend_hash_internal_pointer_reset(objhash); |
|
zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS; |
|
@@ -545,6 +542,8 @@ |
|
php_wddx_add_chunk_static(packet, WDDX_STRUCT_E); |
|
} |
|
|
|
+ PHP_CLEANUP_CLASS_ATTRIBUTES(); |
|
+ |
|
zval_dtor(fname); |
|
FREE_ZVAL(fname); |
|
|
|
@@ -1004,26 +1003,30 @@ |
|
pce = &PHP_IC_ENTRY; |
|
} |
|
|
|
- /* Initialize target object */ |
|
- MAKE_STD_ZVAL(obj); |
|
- object_init_ex(obj, *pce); |
|
- |
|
- /* Merge current hashtable with object's default properties */ |
|
- zend_hash_merge(Z_OBJPROP_P(obj), |
|
- Z_ARRVAL_P(ent2->data), |
|
- (void (*)(void *)) zval_add_ref, |
|
- (void *) &tmp, sizeof(zval *), 0); |
|
+ if (pce != &PHP_IC_ENTRY && ((*pce)->serialize || (*pce)->unserialize)) { |
|
+ ent2->data = NULL; |
|
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s can not be unserialized", Z_STRVAL_P(ent1->data)); |
|
+ } else { |
|
+ /* Initialize target object */ |
|
+ MAKE_STD_ZVAL(obj); |
|
+ object_init_ex(obj, *pce); |
|
+ |
|
+ /* Merge current hashtable with object's default properties */ |
|
+ zend_hash_merge(Z_OBJPROP_P(obj), |
|
+ Z_ARRVAL_P(ent2->data), |
|
+ (void (*)(void *)) zval_add_ref, |
|
+ (void *) &tmp, sizeof(zval *), 0); |
|
+ |
|
+ if (incomplete_class) { |
|
+ php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data)); |
|
+ } |
|
|
|
- if (incomplete_class) { |
|
- php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data)); |
|
- } |
|
- |
|
- /* Clean up old array entry */ |
|
- zval_ptr_dtor(&ent2->data); |
|
- |
|
- /* Set stack entry to point to the newly created object */ |
|
- ent2->data = obj; |
|
+ /* Clean up old array entry */ |
|
+ zval_ptr_dtor(&ent2->data); |
|
|
|
+ /* Set stack entry to point to the newly created object */ |
|
+ ent2->data = obj; |
|
+ } |
|
/* Clean up class name var entry */ |
|
zval_ptr_dtor(&ent1->data); |
|
} else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {
|
|
|