diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ccfa626f90120..432b3b0e773bb 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3266,6 +3266,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( case ZEND_DECLARE_ANON_CLASS: break; /* return value is zend_class_entry pointer */ + case ZEND_CLONE: + break; + default: /* smart branch opcodes may not initialize result */ if (!zend_is_smart_branch(throw_op)) { diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 5818901a765e3..e6d8e4d51fdab 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -681,7 +681,7 @@ PHP_FUNCTION(hash_init) #define PHP_HASHCONTEXT_VERIFY(hash) { \ if (!hash->context) { \ - zend_argument_type_error(1, "must be a valid Hash Context resource"); \ + zend_argument_type_error(1, "must be a valid, non-finalized HashContext"); \ RETURN_THROWS(); \ } \ } @@ -838,11 +838,15 @@ PHP_FUNCTION(hash_final) PHP_FUNCTION(hash_copy) { zval *zhash; + php_hashcontext_object *context; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zhash, php_hashcontext_ce) == FAILURE) { RETURN_THROWS(); } + context = php_hashcontext_from_object(Z_OBJ_P(zhash)); + PHP_HASHCONTEXT_VERIFY(context); + RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(Z_OBJ_P(zhash))); if (php_hashcontext_from_object(Z_OBJ_P(return_value))->context == NULL) { @@ -1395,6 +1399,11 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) { zend_object *znew = php_hashcontext_create(zobj->ce); php_hashcontext_object *newobj = php_hashcontext_from_object(znew); + if (!oldobj->context) { + zend_throw_exception(zend_ce_value_error, "Cannot clone a finalized HashContext", 0); + return NULL; + } + zend_objects_clone_members(znew, zobj); newobj->ops = oldobj->ops; diff --git a/ext/hash/tests/gh12186_1.phpt b/ext/hash/tests/gh12186_1.phpt new file mode 100644 index 0000000000000..6c01ff28d4757 --- /dev/null +++ b/ext/hash/tests/gh12186_1.phpt @@ -0,0 +1,16 @@ +--TEST-- +Hash: bug #12186 - segfault in hash_copy() on a finalized context +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: hash_copy(): Argument #1 ($context) must be a valid, non-finalized HashContext in %s:5 +Stack trace: +#0 %s(5): hash_copy(Object(HashContext)) +#1 {main} + thrown in %s on line 5 \ No newline at end of file diff --git a/ext/hash/tests/gh12186_2.phpt b/ext/hash/tests/gh12186_2.phpt new file mode 100644 index 0000000000000..a50d9eadcaad1 --- /dev/null +++ b/ext/hash/tests/gh12186_2.phpt @@ -0,0 +1,15 @@ +--TEST-- +Hash: bug #12186 - segfault when cloning a finalized context +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught ValueError: Cannot clone a finalized HashContext in %s +Stack trace: +#0 {main} + thrown in %s on line 5 \ No newline at end of file diff --git a/ext/hash/tests/reuse.phpt b/ext/hash/tests/reuse.phpt index 229236dd71335..b5cfc79c162dd 100644 --- a/ext/hash/tests/reuse.phpt +++ b/ext/hash/tests/reuse.phpt @@ -14,4 +14,4 @@ catch (\Error $e) { ?> --EXPECT-- -hash_update(): Argument #1 ($context) must be a valid Hash Context resource +hash_update(): Argument #1 ($context) must be a valid, non-finalized HashContext