codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.4k stars 1.9k forks source link

Bug: [Toolbar] Segmentation fault if View data has an Time objects #7780

Closed neznaika0 closed 1 year ago

neznaika0 commented 1 year ago

PHP Version

8.2

CodeIgniter4 Version

4.3.7

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

cli-server (PHP built-in webserver)

Database

No response

What happened?

Toolbar filter breaks if View Render $data contains objects. I suppose it is intended to output an array of values that are contained in the view('home', ['title' => 'Home']). I have passed objects (+ nested ones) to the render. The debugger breaks down, wanting to get a simple array. See screenshot debugger

https://github.com/codeigniter4/CodeIgniter4/blob/892f4041b358c9a93be863b798caa34158b450cc/system/Debug/Toolbar.php#L317 this code break down, run

    public function getVarData(): array
    {
        $this->initViewer();

        return [
            'View Data' => $this->viewer->getData(), // many objects

        ];
    }

Steps to Reproduce

  1. Pass some complex object (Entity) to the template, including date and time, nested objects.
  2. Enable the Toolbar filter
  3. Open page, see crash

Expected Output

Normal job of the toolbar is expected

Anything else?

It might be worth talking to the developers of kint-php. Dump ($this->collector's) in vendor/codeigniter4/framework/system/Debug/Toolbar.php cannot fully display the output - raising the limit on recursion to 7 does not work (crash)

neznaika0 commented 1 year ago

May be convert objects (not stdClass) to simple FQCN? Without data

kenjis commented 1 year ago

Can you show the minimum code to reproduce the crash? If Kint crashes, it is not a bug in CodeIgniter. Please send a bug report to Kint.

neznaika0 commented 1 year ago

It is difficult to single out an example from my project. There are dependencies. But it seems to me that the problem is again in DateTime. We have discussed this issue before

neznaika0 commented 1 year ago

@kenjis , run test

// deleted, serialize worked

My objects contains Time classes

EDITED: I replace Time to Datetimeimmutable. Its work! See screenshot no crash

kenjis commented 1 year ago

Ah, to begin with, the fact that the segmentation fault occurred means it is a PHP bug, not in PHP script.

Is it the same as #7362 ?

neznaika0 commented 1 year ago

Yeah, but replacing with the native \DateTimeImmutable solves the problem. Although Time extends it, it causes a crash.

neznaika0 commented 1 year ago

Is it the same as https://github.com/codeigniter4/CodeIgniter4/issues/7362 ?

I think so. Will there be any suggestions? After all, the standard date works

kenjis commented 1 year ago

It is better to report the segmentation fault to php.net.

I tried, but I was not able to make the simple code to reproduce it in the past.

neznaika0 commented 1 year ago

@kenjis, I found a bug in serialization. You can congratulate me. It is necessary to override the serialize() and unserialize() method. Can you check code and do a PR?

Need tests for the DateTimeZone is null and is set via the string 2023-08-15T15:52:01.000+00:00. Variants +00:00 = 1, eest = 2, Europe/Moscow = 3. I haven't found how to define it. See https://www.php.net/manual/en/datetimezone.getname.php

Toolbar stopped crashing.

I think it's a problem setting properties in the constructor and in __unserialize(). It is worth transferring this to a separate private method.

public function __serialize(): array
{
    /**
     * Note: "timezone_type" set hard coded. An error may occur if the timezone is not set via the constructor
     */
    return [
        'date'           => $this->format('Y-m-d H:i:s.u'),
        'timezone_type'  => 3,
        'timezone'       => $this->timezone->getName(),
        'locale'         => $this->locale,
        'toStringFormat' => $this->toStringFormat,
    ];
}

public function __unserialize(array $data): void
{
    $timezone = new DateTimeZone($data['timezone']);
    parent::__construct($data['date'], $timezone);
    $this->locale = $data['locale'];
    $this->timezone = $timezone;
}

Bug: prepared array for serialization is incorrect. You cannot create an object from it

array(6) {
  ["date"]=>
  string(26) "2023-08-05 21:30:50.032450"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Moscow"
  ["*timezone"]=>
  object(DateTimeZone)#81 (2) {
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(13) "Europe/Moscow"
  }
  ["*locale"]=>
  string(2) "ru"
  ["*toStringFormat"]=>
  string(19) "yyyy-MM-dd HH:mm:ss"
}
kenjis commented 1 year ago

@neznaika0 I do not understand what you are saying. Are you saying that there is a bug in Time? Could you send a PR?

neznaika0 commented 1 year ago

Sorry, i translate message( Yes, in my opinion a bug in Time The PR will be incorrect because the code is incomplete

kenjis commented 1 year ago

@neznaika0 I checked PHP 8.2.8, and the test passed. See https://github.com/codeigniter4/CodeIgniter4/issues/7362#issuecomment-1666742204

Does the segfault still happen on PHP 8.2.8?

kenjis commented 1 year ago

This PHP bug has been fixed in PHP 8.2.8. https://github.com/php/php-src/commit/93becab506ac05a7bddce1ceaacb53d6657180ce Try 8.2.8.

paulbalandan commented 1 year ago

Can this be closed?

neznaika0 commented 1 year ago

@paulbalandan I can't check yet, there is no official package for debian. Theoretically, yes, I think that the problem is in serialization and should be fixed

neznaika0 commented 1 year ago

I install PHP 8.2.8. Solved