php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79022 class_exists returns True for classes that are not ready to be used
Submitted: 2019-12-23 22:24 UTC Modified: -
From: mech at themech dot net Assigned:
Status: Closed Package: *General Issues
PHP Version: 7.4.1 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: mech at themech dot net
New email:
PHP Version: OS:

 

 [2019-12-23 22:24 UTC] mech at themech dot net
Description:
------------
I noticed this issue while debugging Koseven framework with PHP 7.4. It is related to class autoloading.
Imagine there is an autoloader function registered with the following code inside:
if (class_exists('B', False)) {
   new B();
}
If class B extends some other class A and autoloading function is called to load class A then class_exists('B', false) returns true even if B is not "fully loaded" as its parent class A is still to be loaded. So under PHP 7.4 the "new B()" is being executed and throws "Fatal error: Uncaught Error: Class 'B' not found".
The same code works with PHP 7.3


Test script:
---------------
<?php
// classes/Foo.php: class Foo extends Bar {}
// classes/Bar.php: class Bar {} 
function my_autoloader($class) {
    if (class_exists('Foo', False)) {
	new Foo();
    }
    if ($class == 'Foo' or $class == 'Bar') {
		include "classes/$class.php";
    }
}
spl_autoload_register('my_autoloader');
new Foo();
echo "end"

Expected result:
----------------
class_exists should not return true for the class that does not exist yet.atal

Actual result:
--------------
Fatal error, class not found.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-12-24 06:25 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=153c9cc346bae927394d3ce1378f77fb7c1e1be3
Log: Fixed bug #79022 (class_exists returns True for classes that are not ready to be used)
 [2019-12-24 06:25 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2019-12-24 06:27 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=153c9cc346bae927394d3ce1378f77fb7c1e1be3
Log: Fixed bug #79022 (class_exists returns True for classes that are not ready to be used)
 [2020-02-11 10:07 UTC] raj0chaturvedi at gmail dot com
> gc '.\test script.php'
<?php
function my_autoloader($class) {
    if (class_exists('Foo', False)) {
                new Foo();
    }
        if ($class == 'Foo' or $class == 'Bar') {
        include_once "classes/$class.php";
    }
}
spl_autoload_register('my_autoloader');
new Foo();
echo "end";
---
---


> gci | ft FullName                                                                      
FullName
--------
D:\repro bug 79022\classes
D:\repro bug 79022\test script.php

---
---

> gc .\classes\Bar.php
<?php
class Bar {}
> gc .\classes\Foo.php                                                                                
<?php
include_once "Bar.php";
class Foo extends Bar {}

---
---

works for me on Windows 10 1909. with above code and files.
tested by typing
>php.exe "test script.php"
and
>php.exe -f "test script.php"

> php -v
PHP 7.4.2 (cli) (built: Jan 21 2020 17:53:48) ( ZTS Visual C++ 2017 x86 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies


about comment formatting: I don't know how to format it. See https://pastebin.com/QHzw60Dg for colored output. the paste expires in 364 days. to see raw paste content https://pastebin.com/raw/QHzw60Dg

---
---

aside:

To repeat a message I thought was unexpected uncomment the include_once "Bar.php" line in Foo.php file. Then type
> php .\classes\Foo.php
PHP Fatal error:  Uncaught Error: Class 'Bar' not found in D:\repro bug 79022\classes\Foo.php:4
Stack trace:
#0 {main}
  thrown in D:\repro bug 79022\classes\Foo.php on line 4
Fatal error: Uncaught Error: Class 'Bar' not found in D:\repro bug 79022\classes\Foo.php:4
Stack trace:
#0 {main}
  thrown in D:\repro bug 79022\classes\Foo.php on line 4

It is a bit weird that the exact same error is printed twice. And now, more weird stuff, note the include-once line is commented.

> php -f '.\test script.php'
end
> php.exe -f .\classes\Bar.php
> php.exe -f .\classes\Bar.php

I think it's weird that the first command prints end and nothing else. When compared to how 'php -f Foo.php' is handled.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC