php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80634 write_property handler of internal classes is skipped on preloaded JITted code
Submitted: 2021-01-15 23:13 UTC Modified: 2021-01-19 14:58 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: dktapps at pmmp dot io Assigned: dmitry (profile)
Status: Closed Package: JIT
PHP Version: 8.0.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: dktapps at pmmp dot io
New email:
PHP Version: OS:

 

 [2021-01-15 23:13 UTC] dktapps at pmmp dot io
Description:
------------
When a class which extends an internal class is preloaded and JIT-compiled, the internal class' write_property handler doesn't get executed. Without preloading it works correctly.

This requires quite an exotic test case to reproduce. While the test case itself doesn't make any sense, it's a case that I've encountered while updating an extension with real code, and I spent some time to create a reproducing test case only using PHP's own builtin classes to ensure that it wasn't some crazy bug in my extension.

Command line is `php -dopcache.enable_cli=1 -dopcache.jit=1205 -dopcache.preload=preload.php test.php`



Test script:
---------------
preload.php:
<?php

class SomeClass extends \DatePeriod{
	public $interval;

	public function __construct(int $v){
		parent::__construct(new \DateTime('2020-12-31'), new \DateInterval("P1Y"), 1);
		$this->interval = $v;
		var_dump($this->interval);
	}
}

test.php:
<?php

$v = new SomeClass(5);

Expected result:
----------------
(this output is produced without preloading or JIT)

PHP Fatal error:  Uncaught Error: Writing to DatePeriod->interval is unsupported in /home/user/pocketmine-mp/preload.php:8
Stack trace:
#0 /home/user/pocketmine-mp/test.php(3): SomeClass->__construct()
#1 {main}
  thrown in /home/user/pocketmine-mp/preload.php on line 8



Actual result:
--------------
int(5)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-01-19 14:58 UTC] nikic@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: dmitry
 [2021-01-19 14:58 UTC] nikic@php.net
Confirm the behavior. I believe the problem is that under preloading we have a prop_info available here and will generate code based on that and end up ignoring the write_property handler (under needs_slow_path) entirely. Without preloading we only inherit the class at runtime and the problem doesn't occur (but I think as tracing also collects classes at runtime, there is probably some way for it to occur without preloading as well).

Unfortunately, we don't have static information on whether a class of an object has overwritten write_property -- this is determined by the create_object handler and not stored in the class entry.

I think the correct thing to do here is to conservatively not use any prop_info from internal classes (or classes with internal parents).

@dmitry What do you think about this?
 [2021-01-20 08:04 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=6288228b566db29637e041ffd6392d9895d4d223
Log: Fixed bug #80634 (write_property handler of internal classes is skipped on preloaded JITted code)
 [2021-01-20 08:04 UTC] dmitry@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC