php / php/php-src

ReflectionClass::isInstantiable() is wrong about internal classes that prevent instantiation

未关闭
#17,796 16 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Extension: reflection Status: Needs Triage
主要语言
C
星标
40.4k
派生
8.2k
平均合并
2 天 15 小时
30 天内合并 PR
103

描述

Test script:
<?php

$classes = get_declared_classes();

foreach ( $classes as $clazz ) {
    $r = new ReflectionClass( $clazz );
    if ( !$r->isInstantiable() ) {
        continue;
    }
    try {
        new $clazz();
    } catch ( ArgumentCountError|TypeError $e ) {
        // Nothing
    } catch ( Throwable $e ) {
        echo $clazz . ": ";
        echo get_class( $e ) . ': ' . $e->getMessage() . "\n";
    }
}
Failures

For each of the following classes, ReflectionClass::isInstantiable() returns true, but trying to create an instance of the class directly fails:

Generator: Error: The "Generator" class is reserved for internal use and cannot be manually instantiated
WeakReference: Error: Direct instantiation of WeakReference is not allowed, use WeakReference::create instead
FiberError: Error: The "FiberError" class is reserved for internal use and cannot be manually instantiated
InflateContext: Error: Cannot directly construct InflateContext, use inflate_init() instead
DeflateContext: Error: Cannot directly construct DeflateContext, use deflate_init() instead
CurlHandle: Error: Cannot directly construct CurlHandle, use curl_init() instead
CurlMultiHandle: Error: Cannot directly construct CurlMultiHandle, use curl_multi_init() instead
CurlShareHandle: Error: Cannot directly construct CurlShareHandle, use curl_share_init() instead
CurlSharePersistentHandle: Error: Cannot directly construct CurlSharePersistentHandle, use curl_share_init_persistent() instead
Dba\Connection: Error: Cannot directly construct Dba\Connection, use dba_open() or dba_popen() instead
FFI: Error: Instantiation of FFI is not allowed
FFI\CData: Error: Instantiation of FFI\CData is not allowed
FFI\CType: Error: Instantiation of FFI\CType is not allowed
FTP\Connection: Error: Cannot directly construct FTP\Connection, use ftp_connect() or ftp_ssl_connect() instead
LDAP\Connection: Error: Cannot directly construct LDAP\Connection, use ldap_connect() instead
LDAP\Result: Error: Cannot directly construct LDAP\Result, use the dedicated functions instead
LDAP\ResultEntry: Error: Cannot directly construct LDAP\ResultEntry, use the dedicated functions instead
Directory: Error: Cannot directly construct Directory, use dir() instead
Odbc\Connection: Error: Cannot directly construct Odbc\Connection, use odbc_connect() or odbc_pconnect() instead
Odbc\Result: Error: Cannot directly construct Odbc\Result, use an appropriate odbc_* function instead
PDORow: PDOException: You may not create a PDORow manually
PgSql\Connection: Error: Cannot directly construct PgSql\Connection, use pg_connect() or pg_pconnect() instead
PgSql\Result: Error: Cannot directly construct PgSql\Result, use a dedicated function instead
PgSql\Lob: Error: Cannot directly construct PgSql\Lob, use pg_lo_open() instead
Shmop: Error: Cannot directly construct Shmop, use shmop_open() instead
Soap\Url: Error: Cannot directly construct Soap\Url
Soap\Sdl: Error: Cannot directly construct Soap\Sdl
SysvMessageQueue: Error: Cannot directly construct SysvMessageQueue, use msg_get_queue() instead
SysvSemaphore: Error: Cannot directly construct SysvSemaphore, use sem_get() instead
SysvSharedMemory: Error: Cannot directly construct SysvSharedMemory, use shm_attach() instead
XMLParser: Error: Cannot directly construct XMLParser, use xml_parser_create() or xml_parser_create_ns() instead

Not all of these extensions are on 3v4l but those that are can be confirmed at https://3v4l.org/BmAkH

I didn't test all extensions, what I have enabled locally is:

root@c1c025bca24f:/usr/src/php# php -i | grep "Configure Command"
Configure Command =>  './configure'  '--enable-fpm' '--with-pdo-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-pgsql' '--with-pdo-pgsql' '--with-pdo-sqlite' '--enable-intl' '--without-pear' '--with-jpeg' '--with-webp' '--with-avif' '--with-freetype' '--with-xpm' '--enable-exif' '--with-zip' '--with-zlib' '--enable-soap' '--enable-xmlreader' '--with-xsl' '--with-tidy' '--enable-sysvsem' '--enable-sysvshm' '--enable-shmop' '--enable-pcntl' '--enable-mbstring' '--with-curl' '--with-gettext' '--with-bz2' '--with-gmp' '--enable-bcmath' '--enable-calendar' '--enable-ftp' '--with-enchant=/usr' '--enable-sysvmsg' '--with-ffi' '--enable-zend-test' '--enable-dl-test=shared' '--with-ldap' '--with-ldap-sasl' '--with-password-argon2' '--with-mhash' '--with-sodium' '--enable-dba' '--with-cdb' '--enable-flatfile' '--enable-inifile' '--with-tcadb' '--with-lmdb' '--with-qdbm' '--with-snmp' '--with-unixODBC' '--with-pdo-odbc=unixODBC,/usr' '--with-config-file-path=/etc' '--with-config-file-scan-dir=/etc/php.d' '--with-pdo-firebird' '--with-pdo-dblib' '--enable-debug' '--disable-zts'
Proposal

I propose that we add a new class flag, ZEND_ACC_NON_INSTANTIABLE, that classes can apply when they are registered.

PHP Version

65d433161a2179d7a69e857280c581d6f8df18cd

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从提供的 PHP 测试脚本和列出的内部类开始,重现 ReflectionClass::isInstantiable() 与直接构造之间的不一致。调查这些类是如何注册的,以及拟议的 ZEND_ACC_NON_INSTANTIABLE 标志如何覆盖它们;完成的标准是受影响的类报告 false,而普通的可实例化类保持不变。

由索引模型根据 Issue 内容生成。

评估

技术栈
c, php
领域
backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。