Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpFoundation] unset Request properties within initialize() will cause issue on any extended Request implementing __isset() and __get() #51792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
crynobone opened this issue Oct 1, 2023 · 8 comments · Fixed by #51812 or #51887

Comments

@crynobone
Copy link
Contributor

crynobone commented Oct 1, 2023

Symfony version(s) affected

7.0.0

Description

Laravel Framework is preparing support for Symfony 7 for the upcoming Laravel 11 (target release Q1 2024) and based on our existing tests the usage such as protected string $baseUrl and using unset($this->baseUrl) will cause issues for Illuminate\Http\Request as this class extends Symfony\Component\HttpFoundation\Request and also implements __isset() and __get().

How to reproduce

The issue can be seen via our GitHub Actions: https://github.com/laravel/framework/actions/runs/6361912914/job/17276631512

To make it easier to understand, here is a simplified version of the usage:

class SymfonyRequest 
{
  protected string $baseUrl;

  public function __construct() 
  {
    unset($this->baseUrl);
  }

  public function getPathInfo()
  {
    if (null === ($baseUrl = $this->getBaseUrlReal())) {
      return 'http://localhost';
    }
    
    assert($baseUrl === 'foo', 'BaseURL should be `foo` from `prepareBaseUrl()` but instead is `'.$baseUrl.'`');

    return 'http://laravel.com';
  }

  private function getBaseUrlReal(): string
  {

    return $this->baseUrl ??= $this->prepareBaseUrl();
  }

  protected function prepareBaseUrl(): string
  {
    return 'foo';
  }
}

class LaravelRequest extends SymfonyRequest
{
    public function path() {
      return $this->getPathInfo();
    }

    public function __isset($key)
    {
      return ! is_null($this->__get($key));
    }
    
    public function __get($key)
    {
      if ($key === 'baseUrl') {
        return 'bar';
      }

      return null;
    }
}

$a = new LaravelRequest();

$a->path();

CleanShot 2023-10-01 at 11 00 07

Possible Solution

One possible solution is to opt for the following:

- protected string $baseUrl;
+protected ?string $baseUrl;

and set to null instead of unset.

-unset($this->baseUrl);
+$this->baseUrl = null;

Additional Context

Without the above change, any extended Request class similar to Laravel would need to look into exposing Symfony Request via __isset() and __get() which might not be ideal.

@crynobone crynobone added the Bug label Oct 1, 2023
@crynobone crynobone changed the title [HttpFoundation] unset Request properties within initialise() will cause issue on any extended Request implementing __isset() and __get() [HttpFoundation] unset Request properties within initialize() will cause issue on any extended Request implementing __isset() and __get() Oct 1, 2023
@derrabus
Copy link
Member

derrabus commented Oct 2, 2023

Please send a PR.

@stof
Copy link
Member

stof commented Oct 2, 2023

The unset variable is there to lazy-load that variable on reading. Making that nullable will actually break things entirely because the lazy-loading won't happen.

@stof
Copy link
Member

stof commented Oct 2, 2023

The child class needs to properly call the parent methods for __isset and __get

@crynobone
Copy link
Contributor Author

The child class needs to properly call the parent methods for __isset and __get

But wouldn't that expose Symfony's Request protected properties within child Request via __isset and __get?

For example:

$symfonyRequest = Request::create();

$laravelRequest = LaravelRequest::create();

$symfonyRequest->baseUrl // is not possible since it's protected property.
$laravelRequest->baseUrl // is possible since it's accessed via `__get()`

@stof
Copy link
Member

stof commented Oct 2, 2023

hmm, looking at those, it seems like those properties are not actually lazy-loaded on reads on them.

@nicolas-grekas I think unsetting them (in #51121) instead of making them nullable was a mistake given that in 6.4, a child class would see them as null before the getter is called and as uninitialized in 7.0. Or maybe they should become private.

@nicolas-grekas
Copy link
Member

Should be fixed by #51812

@driesvints
Copy link
Contributor

Thanks for the swift response/action here all! 🙂

@crynobone
Copy link
Contributor Author

Submit an additional PR: #51887

Failing Tests:

CleanShot 2023-10-08 at 09 50 15

fabpot added a commit that referenced this issue Oct 10, 2023
…crynobone)

This PR was merged into the 6.4 branch.

Discussion
----------

[HttpFoundation] Fix type of properties in Request class

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix #51792 <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead -->
| License       | MIT

Additional fixes to #51812

`static::$formats` can be `null` to allow lazy-loading:

https://github.com/symfony/symfony/blob/33fedcee2814947c59df2570952f8c800dfdb23e/src/Symfony/Component/HttpFoundation/Request.php#L1252-L1254

<!--
Replace this notice by a description of your feature/bugfix.
This will help reviewers and should be a good start for the documentation.

Additionally (see https://symfony.com/releases):
 - Always add tests and ensure they pass.
 - Bug fixes must be submitted against the lowest maintained branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against the latest branch.
 - For new features, provide some code snippets to help understand usage.
 - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry
 - Never break backward compatibility (see https://symfony.com/bc).
-->

Commits
-------

136044e [HttpFoundation] Fix type of properties in Request class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants