mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix GH-17442: Engine UAF with reference assign and dtor
Closes GH-17443.
This commit is contained in:
parent
09791ed1d1
commit
b068c2ff94
9 changed files with 108 additions and 22 deletions
1
NEWS
1
NEWS
|
@ -17,6 +17,7 @@ PHP NEWS
|
||||||
. Implement GH-15680 (Enhance zend_dump_op_array to properly represent
|
. Implement GH-15680 (Enhance zend_dump_op_array to properly represent
|
||||||
non-printable characters in string literals). (nielsdos, WangYihang)
|
non-printable characters in string literals). (nielsdos, WangYihang)
|
||||||
. Add support for backtraces for fatal errors. (enorris)
|
. Add support for backtraces for fatal errors. (enorris)
|
||||||
|
. Fixed bug GH-17442 (Engine UAF with reference assign and dtor). (nielsdos)
|
||||||
|
|
||||||
- Curl:
|
- Curl:
|
||||||
. Added curl_multi_get_handles(). (timwolla)
|
. Added curl_multi_get_handles(). (timwolla)
|
||||||
|
|
|
@ -14,6 +14,12 @@ PHP 8.5 INTERNALS UPGRADE NOTES
|
||||||
1. Internal API changes
|
1. Internal API changes
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
- Zend
|
||||||
|
. Added zend_safe_assign_to_variable_noref() function to safely assign
|
||||||
|
a value to a non-reference zval.
|
||||||
|
. Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor
|
||||||
|
could interfere.
|
||||||
|
|
||||||
========================
|
========================
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
========================
|
========================
|
||||||
|
|
22
Zend/tests/weakrefs/gh17442_1.phpt
Normal file
22
Zend/tests/weakrefs/gh17442_1.phpt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
--TEST--
|
||||||
|
GH-17442 (Engine UAF with reference assign and dtor) - untyped
|
||||||
|
--CREDITS--
|
||||||
|
YuanchengJiang
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$map = new WeakMap;
|
||||||
|
$obj = new stdClass;
|
||||||
|
$map[$obj] = new class {
|
||||||
|
function __destruct() {
|
||||||
|
throw new Exception("Test");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
headers_sent($obj,$generator);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Uncaught Exception: Test in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: class@anonymous->__destruct()
|
||||||
|
#1 %s(%d): headers_sent(NULL, 0)
|
||||||
|
#2 {main}
|
||||||
|
thrown in %s on line %d
|
35
Zend/tests/weakrefs/gh17442_2.phpt
Normal file
35
Zend/tests/weakrefs/gh17442_2.phpt
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
--TEST--
|
||||||
|
GH-17442 (Engine UAF with reference assign and dtor) - typed
|
||||||
|
--CREDITS--
|
||||||
|
YuanchengJiang
|
||||||
|
nielsdos
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$map = new WeakMap;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public stdClass|string $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new Test;
|
||||||
|
$test->obj = new stdClass;
|
||||||
|
|
||||||
|
$map[$test->obj] = new class {
|
||||||
|
function __destruct() {
|
||||||
|
global $test;
|
||||||
|
var_dump($test->obj);
|
||||||
|
throw new Exception("Test");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
headers_sent($test->obj);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
string(0) ""
|
||||||
|
|
||||||
|
Fatal error: Uncaught Exception: Test in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: class@anonymous->__destruct()
|
||||||
|
#1 %s(%d): headers_sent('')
|
||||||
|
#2 {main}
|
||||||
|
thrown in %s on line %d
|
|
@ -4666,8 +4666,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val
|
||||||
zval_ptr_dtor(val);
|
zval_ptr_dtor(val);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
} else {
|
} else {
|
||||||
zval_ptr_dtor(&ref->val);
|
zend_safe_assign_to_variable_noref(&ref->val, val);
|
||||||
ZVAL_COPY_VALUE(&ref->val, val);
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1107,7 +1107,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_NULL(_zv); \
|
ZVAL_NULL(_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1129,7 +1129,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_FALSE(_zv); \
|
ZVAL_FALSE(_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1151,7 +1151,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_TRUE(_zv); \
|
ZVAL_TRUE(_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1173,7 +1173,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_BOOL(_zv, bval); \
|
ZVAL_BOOL(_zv, bval); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1195,7 +1195,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_LONG(_zv, lval); \
|
ZVAL_LONG(_zv, lval); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1217,7 +1217,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_DOUBLE(_zv, dval); \
|
ZVAL_DOUBLE(_zv, dval); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1239,7 +1239,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_EMPTY_STRING(_zv); \
|
ZVAL_EMPTY_STRING(_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1261,7 +1261,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_STR(_zv, str); \
|
ZVAL_STR(_zv, str); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1283,7 +1283,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_NEW_STR(_zv, str); \
|
ZVAL_NEW_STR(_zv, str); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1305,7 +1305,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_STRING(_zv, string); \
|
ZVAL_STRING(_zv, string); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1327,7 +1327,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_STRINGL(_zv, string, len); \
|
ZVAL_STRINGL(_zv, string, len); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1349,7 +1349,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_ARR(_zv, arr); \
|
ZVAL_ARR(_zv, arr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1371,7 +1371,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_RES(_zv, res); \
|
ZVAL_RES(_zv, res); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1393,7 +1393,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_COPY_VALUE(_zv, other_zv); \
|
ZVAL_COPY_VALUE(_zv, other_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1415,7 +1415,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_COPY_VALUE(_zv, other_zv); \
|
ZVAL_COPY_VALUE(_zv, other_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1447,7 +1447,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval
|
||||||
} \
|
} \
|
||||||
_zv = &ref->val; \
|
_zv = &ref->val; \
|
||||||
} \
|
} \
|
||||||
zval_ptr_dtor(_zv); \
|
zval_ptr_safe_dtor(_zv); \
|
||||||
ZVAL_COPY_VALUE(_zv, other_zv); \
|
ZVAL_COPY_VALUE(_zv, other_zv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1485,10 +1485,7 @@ static zend_always_inline zval *zend_try_array_init_size(zval *zv, uint32_t size
|
||||||
}
|
}
|
||||||
zv = &ref->val;
|
zv = &ref->val;
|
||||||
}
|
}
|
||||||
zval garbage;
|
zval_ptr_safe_dtor(zv);
|
||||||
ZVAL_COPY_VALUE(&garbage, zv);
|
|
||||||
ZVAL_NULL(zv);
|
|
||||||
zval_ptr_dtor(&garbage);
|
|
||||||
ZVAL_ARR(zv, arr);
|
ZVAL_ARR(zv, arr);
|
||||||
return zv;
|
return zv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,17 @@ static zend_always_inline zval* zend_assign_to_variable_ex(zval *variable_ptr, z
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static zend_always_inline void zend_safe_assign_to_variable_noref(zval *variable_ptr, zval *value) {
|
||||||
|
if (Z_REFCOUNTED_P(variable_ptr)) {
|
||||||
|
ZEND_ASSERT(Z_TYPE_P(variable_ptr) != IS_REFERENCE);
|
||||||
|
zend_refcounted *ref = Z_COUNTED_P(variable_ptr);
|
||||||
|
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||||
|
GC_DTOR_NO_REF(ref);
|
||||||
|
} else {
|
||||||
|
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp);
|
ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp);
|
||||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope);
|
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope);
|
||||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx);
|
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx);
|
||||||
|
|
|
@ -85,6 +85,20 @@ ZEND_API void zval_ptr_dtor(zval *zval_ptr) /* {{{ */
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
ZEND_API void zval_ptr_safe_dtor(zval *zval_ptr)
|
||||||
|
{
|
||||||
|
if (Z_REFCOUNTED_P(zval_ptr)) {
|
||||||
|
zend_refcounted *ref = Z_COUNTED_P(zval_ptr);
|
||||||
|
|
||||||
|
if (GC_DELREF(ref) == 0) {
|
||||||
|
ZVAL_NULL(zval_ptr);
|
||||||
|
rc_dtor_func(ref);
|
||||||
|
} else {
|
||||||
|
gc_check_possible_root(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API void zval_internal_ptr_dtor(zval *zval_ptr) /* {{{ */
|
ZEND_API void zval_internal_ptr_dtor(zval *zval_ptr) /* {{{ */
|
||||||
{
|
{
|
||||||
if (Z_REFCOUNTED_P(zval_ptr)) {
|
if (Z_REFCOUNTED_P(zval_ptr)) {
|
||||||
|
|
|
@ -78,6 +78,7 @@ static zend_always_inline void zval_ptr_dtor_str(zval *zval_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API void zval_ptr_dtor(zval *zval_ptr);
|
ZEND_API void zval_ptr_dtor(zval *zval_ptr);
|
||||||
|
ZEND_API void zval_ptr_safe_dtor(zval *zval_ptr);
|
||||||
ZEND_API void zval_internal_ptr_dtor(zval *zvalue);
|
ZEND_API void zval_internal_ptr_dtor(zval *zvalue);
|
||||||
|
|
||||||
/* Kept for compatibility */
|
/* Kept for compatibility */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue