diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 2d29ff61fa03f..984b7335780e6 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -680,7 +680,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(); \ } \ } @@ -837,11 +837,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) { @@ -1405,6 +1409,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 &newobj->std; + } + 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..5e34b1dd78e8f --- /dev/null +++ b/ext/hash/tests/gh12186_1.phpt @@ -0,0 +1,17 @@ +--TEST-- +Hash: bug #12186 - segfault in hash_copy() on a finalized context +--FILE-- +getMessage() . "\n"; +} + +?> +--EXPECTF-- +hash_copy(): Argument #1 ($context) must be a valid, non-finalized HashContext diff --git a/ext/hash/tests/gh12186_2.phpt b/ext/hash/tests/gh12186_2.phpt new file mode 100644 index 0000000000000..64a12b15c391c --- /dev/null +++ b/ext/hash/tests/gh12186_2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Hash: bug #12186 - segfault when cloning a finalized context +--FILE-- +getMessage() . "\n"; +} + +?> +--EXPECTF-- +Cannot clone a finalized HashContext 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