Problem/Motivation

https://www.php.net/manual/en/splfileobject.fgets.php may return False so it brings errors in case no type defined

TypeError thrown in /var/www/html/vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php on line 380 while loading bootstrap file /var/www/html/vendor/mglaman/phpstan-drupal/drupal-autoloader.php: preg_match(): Argument #2 ($subject) must be of type string, null given

Steps to reproduce

https://www.drupal.org/pift-ci-job/2420734 which is using fork of core file https://github.com/mglaman/phpstan-drupal/pull/442

Proposed resolution

- don't call preg_match() when no string is read from file

Remaining tasks

- agree on fix
- review/commit

User interface changes

no

API changes

no

Data model changes

no

Release notes snippet

no

CommentFileSizeAuthor
#2 3294827-2.patch899 bytesandypost

Comments

andypost created an issue. See original summary.

andypost’s picture

Status: Active » Needs review
Issue tags: +Quick fix
StatusFileSize
new899 bytes

quick fix

dww’s picture

Issue tags: +Bug Smash Initiative
  1. Issue summary is clear, and proposed resolution makes sense.
  2. Patch is small and clean, changing nothing but what the summary says it should.
  3. Bot is happy.
  4. I don't think we need new tests for this (although I might be wrong on this point). 😅
  5. No chance of disruption to existing sites, no UI / string changes.
  6. No need for a CR, nor release note.

Tentatively moving to RTBC. A committer can tell us if they're going to require a new test for this. Seems a little yucky to write a test for, frankly. 😉 Hopefully it doesn't come to that. 🤞

Thanks!
-Derek

dww’s picture

Status: Needs review » Reviewed & tested by the community
catch’s picture

Status: Reviewed & tested by the community » Needs review

This feels like a silly question but I don't understand what's actually triggering this - i.e. is it a malformed .info.yml file? How would it be malformed to produce this?

I guess what I'm asking is - if the file opened OK, and it's not the end of the file, and fgets() returns false, then should there be some kind of error logged somewhere? Or is this purely an edge case that affects phpstan and we don't care about swallowing the error?

mmjvb’s picture

Consider it unprofessional to disregard things can go wrong. You should not trust things to be trouble free. So, the fix should go in.

Considering the nature of this function is to return valid extensions, ignoring those that are invalid, there is no need to pollute the log. It doesn't report invalid names, nor missing type key. Why would you report a low level error from the filesystem. Suspect it already to be reported at appropriate level.

In my opinion invalid names and missing type key are more in need of logging than the filesystem error. So, propose to swallow them all or log them all. For sure the filesystem error is beyond their control. The other two could be as well, but more likely to be something they could fix.

alexpott’s picture

Status: Needs review » Needs work

I would be great to know why the error is being triggered. To understand it in case it is pointing to an incorrect assumption somewhere else in the code.

andypost’s picture

In manual https://www.php.net/manual/en/function.fgets.php there's warning about how eof() works (depends on C library) but clearly the fgets() should not return null (false on eof) but somehow it's wrong

tedfordgif’s picture

It definitely looks like an error would have been thrown and logged: SplFileObject->fgets() calls spl_filesystem_file_read_ex() with silent == false, which will throw a PHP exception if the file can't be read.

That's the only place in the PHP source I see "Cannot read from file", so if we found that in logs it would be pretty clear.

As to how that can happen in ExtensionDiscovery::scanDirectory(), I'd look for race conditions if we're running tests in parallel, or some other filesystem failure (network filesystem, running out of disk space, ...).

@alexpott the assumption would seem to be that having a reference to an open SplFileObject (with a recent !eof check, no less) means you can read it without errors. That seems like a reasonable assumption to me, and matches most of the usage examples I've seen. However, perhaps we should consider adding a call to SplFileInfo->isReadable() before calling openFile(), and maybe logging our own error if not. There may be some minor performance implication if isReadable() and openFile() don't share a cache.

I also find the differences between SplFileObject::eof() and ::valid interesting, although the latter is billed as !eof.

Version: 10.0.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nicxvan’s picture

Component: base system » extension system

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.