Skip to content

Commit 3fe47a3

Browse files
committed
Fixes
1 parent f40b966 commit 3fe47a3

10 files changed

Lines changed: 38 additions & 25 deletions

File tree

Zend/zend_inheritance.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,11 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
195195
return;
196196
}
197197

198-
ce->constructor = parent->constructor;
198+
if (zend_is_non_instantiable_constructor(parent->constructor)) {
199+
ce->constructor = NULL;
200+
} else {
201+
ce->constructor = parent->constructor;
202+
}
199203
}
200204
/* }}} */
201205

ext/com_dotnet/com_extension.stub.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ public function __construct(string $assembly_name, string $datatype_name, int $c
370370
}
371371
#endif
372372

373+
#[\NonInstantiableClass("Cannot directly construct com_safeproxy_array; it is for internal usage only")]
373374
final class com_safearray_proxy
374375
{
375376
}

ext/com_dotnet/com_extension_arginfo.h

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/com_dotnet/com_saproxy.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,6 @@ static zend_function *saproxy_method_get(zend_object **object, zend_string *name
321321
return NULL;
322322
}
323323

324-
static zend_function *saproxy_constructor_get(zend_object *object)
325-
{
326-
zend_throw_error(NULL, "Cannot directly construct com_safeproxy_array; it is for internal usage only");
327-
return NULL;
328-
}
329-
330324
static zend_string* saproxy_class_name_get(const zend_object *object)
331325
{
332326
return zend_string_copy(php_com_saproxy_class_entry->name);
@@ -412,7 +406,6 @@ zend_object_handlers php_com_saproxy_handlers = {
412406
saproxy_dimension_delete,
413407
saproxy_properties_get,
414408
saproxy_method_get,
415-
saproxy_constructor_get,
416409
saproxy_class_name_get,
417410
saproxy_object_cast,
418411
saproxy_count_elements,

ext/dom/tests/modern/html/interactions/without_constructor.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ foreach (['Dom\HTMLDocument', 'Dom\XMLDocument'] as $class) {
1616

1717
?>
1818
--EXPECT--
19-
Class Dom\HTMLDocument is an internal class marked as final that cannot be instantiated without invoking its constructor
20-
Class Dom\XMLDocument is an internal class marked as final that cannot be instantiated without invoking its constructor
19+
Class Dom\HTMLDocument cannot be instantiated manually
20+
Class Dom\XMLDocument cannot be instantiated manually

ext/mysqli/tests/bug74968.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ require_once 'skipifconnectfailure.inc';
1818
?>
1919
==DONE==
2020
--EXPECTF--
21-
Fatal error: Uncaught Error: Class test cannot be instantiated in %sbug74968.php:%d
21+
Fatal error: Uncaught ValueError: mysqli_result::fetch_object(): Argument #1 ($class) Class "test" cannot be instantiated in %sbug74968.php:%d
2222
Stack trace:
2323
#0 %sbug74968.php(%d): mysqli_result->fetch_object('test')
2424
#1 {main}

ext/mysqli/tests/mysqli_fetch_object.phpt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,13 @@ require_once 'skipifconnectfailure.inc';
116116
$this->b = $b;
117117
}
118118
}
119-
/*
120-
TODO
121-
I think we should bail out here. The following line will give a Fatal error: Call to private ... from invalid context
122-
var_dump($obj = new mysqli_fetch_object_private_constructor(1, 2));
123-
This does not fail.
124-
*/
125-
mysqli_fetch_object($res, 'mysqli_fetch_object_private_constructor', array('a', 'b'));
126-
mysqli_free_result($res);
119+
120+
try {
121+
var_dump(mysqli_fetch_object($res, 'mysqli_fetch_object_private_constructor', ['a', 'b']));
122+
mysqli_free_result($res);
123+
} catch (Throwable $e) {
124+
echo $e::class, ': ', $e->getMessage(), "\n";
125+
}
127126

128127
try {
129128
var_dump(mysqli_fetch_object($res, 'this_class_does_not_exist'));

ext/pdo/pdo_dbh.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ PHP_METHOD(PDO, prepare)
626626
zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement");
627627
RETURN_THROWS();
628628
}
629-
if (UNEXPECTED(dbstmt_ce->constructor == NULL)) {
629+
if (UNEXPECTED(zend_is_non_instantiable_constructor(dbstmt_ce->constructor))) {
630630
zend_throw_error(
631631
NULL,
632632
"Class %s cannot be used as a user-supplied statement class as it cannot be instantiated",

ext/pdo/pdo_stmt.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,14 @@ static bool pdo_verify_fetch_mode(uint32_t default_mode_and_flags, zend_long mod
10261026
}
10271027
/* }}} */
10281028

1029+
/* Based on zend_is_class_instantiable() but doesn't check the visibility of the constructor */
1030+
static bool pdo_is_class_instantiable(const zend_class_entry *ce) {
1031+
return
1032+
!(ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM))
1033+
&& (!ce->constructor || !zend_is_non_instantiable_constructor(ce->constructor))
1034+
;
1035+
}
1036+
10291037
/* {{{ Fetches the next row and returns it, or false if there are no more rows */
10301038
PHP_METHOD(PDOStatement, fetch)
10311039
{
@@ -1088,7 +1096,7 @@ PHP_METHOD(PDOStatement, fetchObject)
10881096
ce = zend_standard_class_def;
10891097
}
10901098

1091-
if (UNEXPECTED(!zend_is_class_instantiable(ce))) {
1099+
if (UNEXPECTED(!pdo_is_class_instantiable(ce))) {
10921100
zend_argument_value_error(1, "Class \"%s\" cannot be instantiated", ZSTR_VAL(ce->name));
10931101
RETURN_THROWS();
10941102
}
@@ -1196,7 +1204,7 @@ PHP_METHOD(PDOStatement, fetchAll)
11961204
} else {
11971205
fetch_class = zend_standard_class_def;
11981206
}
1199-
if (UNEXPECTED(!zend_is_class_instantiable(fetch_class))) {
1207+
if (UNEXPECTED(!pdo_is_class_instantiable(fetch_class))) {
12001208
zend_throw_error(NULL, "Cannot instantiate an object of class %s", ZSTR_VAL(fetch_class->name));
12011209
RETURN_THROWS();
12021210
}
@@ -1716,7 +1724,7 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
17161724
zend_argument_type_error(arg1_arg_num, "must be a valid class");
17171725
return false;
17181726
}
1719-
if (UNEXPECTED(cep->constructor == NULL)) {
1727+
if (UNEXPECTED(!pdo_is_class_instantiable(cep))) {
17201728
zend_throw_error(NULL, "Cannot instantiate an object of class %s", ZSTR_VAL(cep->name));
17211729
return false;
17221730
}

ext/pgsql/pgsql.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,7 @@ PHP_FUNCTION(pg_fetch_object)
21162116
RETURN_THROWS();
21172117
}
21182118

2119-
if (UNEXPECTED(!constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0)) {
2119+
if (UNEXPECTED(!ce->constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0)) {
21202120
zend_argument_value_error(4,
21212121
"must be empty when the specified class (%s) does not have a constructor",
21222122
ZSTR_VAL(ce->name)

0 commit comments

Comments
 (0)