Skip to content

Preloading anonymous class inheriting from autoloaded unlinked class leads to return type error #10131

@tscni

Description

@tscni

Description

Issue

When using PHP-FPM that is, and only starting when the respective code is used the second time.

The following code:

// preload.php
<?php
require __DIR__ . '/Main.php';

// index.php
<?php
require __DIR__ . '/Main.php';
spl_autoload_register(function ($class) {
    if ($class === 'SomeType') require __DIR__ . '/SomeType.php';
});

var_dump((new Main)->create());

// Main.php
<?php
class Main {
    function create(): SomeType {
        return new class extends SomeType {};
    }
}

// SomeType.php
<?php
class SomeType {}
# php.ini
opcache.enable=1
opcache.optimization_level=-1
opcache.preload=/var/www/html/preload.php
opcache.preload_user=www-data

Where index.php is called twice

Resulted in this output:

# During preload
Warning: Can't preload unlinked class SomeType@anonymous: Unknown parent SomeType in /var/www/html/Main.php on line 4

# Call 1
object(SomeType@anonymous)#3 (0) { }

# Call 2
Fatal error: Uncaught TypeError: Main::create(): Return value must be of type SomeType, SomeType@anonymous returned in /var/www/html/Main.php:4
Stack trace:
#0 /var/www/html/index.php(7): Main->create()
#1 {main}
  thrown in /var/www/html/Main.php on line 4

But I expected this output instead:

# During preload
Warning: Can't preload unlinked class SomeType@anonymous: Unknown parent SomeType in /var/www/html/Main.php on line 4

# Call 1
object(SomeType@anonymous)#3 (0) { }

# Call 2
object(SomeType@anonymous)#3 (0) { }

Reproducing

This can be reproduced by additionally configuring these files

# php-fpm-www.conf
[www]
user=www-data
group=www-data
listen=127.0.0.1:9000
pm=static
pm.max_children=1
# nginx.conf
events {
    worker_connections  4096;
}
http {
    server {
        location ~ \.php$ {
            fastcgi_pass php-test:9000;
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
            include fastcgi_params;
        }
    }
}

and then running

docker run --rm -it --name php-test -v $(pwd):/var/www/html -v $(pwd)/php-fpm-www.conf:/usr/local/etc/php-fpm.d/www.conf -v $(pwd)/php.ini:/usr/local/etc/php/conf.d/php.ini php:8.1.13-fpm-bullseye bash -c "docker-php-ext-install opcache && php-fpm"
# separately / detached
docker run --rm -it -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf -p 8080:80 --link php-test nginx:1.23.3
curl http://localhost:8080/index.php
curl http://localhost:8080/index.php

Segfaults

Under certain circumstances, this leads to segfaults, but I haven't been able to setup a sharable reproducible case.
Occasionally between segfaults I get errors like these:

  • Uncaught exception: Class "" not found
  • Uncaught exception: Class "H?" not found

Backtrace from such a segfault:

Core was generated by `php-fpm: pool www      '.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00005564d172fe35 in zend_lookup_class_ex (name=0x800000017c9e55d4, key=0x42973350, flags=2560) at /usr/src/php/Zend/zend_execute_API.c:1050
1050    /usr/src/php/Zend/zend_execute_API.c: No such file or directory.
[Current thread is 1 (Thread 0x7f8a9adbe980 (LWP 263))]
(gdb) bt
#0  0x00005564d172fe35 in zend_lookup_class_ex (name=0x800000017c9e55d4, key=0x42973350, flags=2560) at /usr/src/php/Zend/zend_execute_API.c:1050
#1  0x00005564d1731092 in zend_fetch_class_by_name (class_name=0x800000017c9e55d4, key=0x42973350, fetch_type=2560) at /usr/src/php/Zend/zend_execute_API.c:1601
#2  0x00005564d184233d in zend_do_link_class (ce=0x7f8a96404338, lc_parent_name=0x42973350, key=0x42973000) at /usr/src/php/Zend/zend_inheritance.c:2715
#3  0x00005564d178bae1 in ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER () at /usr/src/php/Zend/zend_vm_execute.h:2955
#4  0x00005564d17fcd2c in execute_ex (ex=0x7f8a9aa14020) at /usr/src/php/Zend/zend_vm_execute.h:55863
#5  0x00005564d18014fa in zend_execute (op_array=0x7f8a9aa75140, return_value=0x0) at /usr/src/php/Zend/zend_vm_execute.h:60147
#6  0x00005564d17488dc in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/php/Zend/zend.c:1799
#7  0x00005564d169e08b in php_execute_script (primary_file=0x7fff379ad520) at /usr/src/php/main/main.c:2541
#8  0x00005564d18cf2d5 in main (argc=1, argv=0x7fff379ad9a8) at /usr/src/php/sapi/fpm/fpm/fpm_main.c:1914

PHP Version

8.1.13

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions