Skip to content

Commit 18f4cdc

Browse files
committed
Fix GH-12186: segfault copying/cloning a finalized HashContext
Closes #12186
1 parent 748adf1 commit 18f4cdc

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

ext/hash/hash.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ PHP_FUNCTION(hash_init)
680680

681681
#define PHP_HASHCONTEXT_VERIFY(hash) { \
682682
if (!hash->context) { \
683-
zend_argument_type_error(1, "must be a valid Hash Context resource"); \
683+
zend_argument_type_error(1, "must be a valid, non-finalized HashContext"); \
684684
RETURN_THROWS(); \
685685
} \
686686
}
@@ -837,11 +837,15 @@ PHP_FUNCTION(hash_final)
837837
PHP_FUNCTION(hash_copy)
838838
{
839839
zval *zhash;
840+
php_hashcontext_object *context;
840841

841842
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zhash, php_hashcontext_ce) == FAILURE) {
842843
RETURN_THROWS();
843844
}
844845

846+
context = php_hashcontext_from_object(Z_OBJ_P(zhash));
847+
PHP_HASHCONTEXT_VERIFY(context);
848+
845849
RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(Z_OBJ_P(zhash)));
846850

847851
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) {
14051409
zend_object *znew = php_hashcontext_create(zobj->ce);
14061410
php_hashcontext_object *newobj = php_hashcontext_from_object(znew);
14071411

1412+
if (!oldobj->context) {
1413+
zend_throw_exception(zend_ce_value_error, "Cannot clone a finalized HashContext", 0);
1414+
return &newobj->std;
1415+
}
1416+
14081417
zend_objects_clone_members(znew, zobj);
14091418

14101419
newobj->ops = oldobj->ops;

ext/hash/tests/gh12186_1.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Hash: bug #12186 - segfault in hash_copy() on a finalized context
3+
--FILE--
4+
<?php
5+
6+
$c = hash_init('sha1');
7+
hash_final($c);
8+
9+
try {
10+
hash_copy($c);
11+
} catch (Throwable $ex) {
12+
echo $ex->getMessage() . "\n";
13+
}
14+
15+
?>
16+
--EXPECTF--
17+
hash_copy(): Argument #1 ($context) must be a valid, non-finalized HashContext

ext/hash/tests/gh12186_2.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Hash: bug #12186 - segfault when cloning a finalized context
3+
--FILE--
4+
<?php
5+
6+
$c = hash_init('sha1');
7+
hash_final($c);
8+
9+
try {
10+
clone $c;
11+
} catch (Throwable $ex) {
12+
echo $ex->getMessage() . "\n";
13+
}
14+
15+
?>
16+
--EXPECTF--
17+
Cannot clone a finalized HashContext

ext/hash/tests/reuse.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ catch (\Error $e) {
1414

1515
?>
1616
--EXPECT--
17-
hash_update(): Argument #1 ($context) must be a valid Hash Context resource
17+
hash_update(): Argument #1 ($context) must be a valid, non-finalized HashContext

0 commit comments

Comments
 (0)