Problem/Motivation

system_requirements() includes this:

        $version = str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $required_file->info['version']);
...
            'description' => t('@name requires this module and version. Currently using @required_name version @version', ['@name' => $name, '@required_name' => $required_name, '@version' => $version]),
\Drupal::CORE_COMPATIBILITY is "8.x".

So we str_replace() "8.x-" with an empty string.

However, we're not careful about doing so only at the beginning of the version string.

So, if you somehow are dealing with a version string that contains '8.x-' somewhere you don't expect, all hell breaks loose.

Reasons you might have a version string that will be wrongfully clobbered include:

  1. A contrib module is upto 8.x-8.x branch and you're using the -dev release.
  2. You applied #3093130: Between alpha1 and X.Y.0 official \Drupal::VERSION should not be "8.8.0-dev" since it doesn't work for Semver::satisfies() and core's version is 8.8.x-dev
  3. You're using git_deploy and a Git checkout of core, in which case core thinks its version is 8.8.x-dev (I think).
  4. ...

Proposed resolution

If we have to strip this off, make sure we only do it at the beginning of the version string.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

dww created an issue. See original summary.

dww’s picture

Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new901 bytes

Something like this.

tedbow’s picture

@dww good catch.

Looks like we also do this in \Drupal\system\Form\ModulesListForm::buildRow

if (!$dependency_object->isCompatible(str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $modules[$dependency]->info['version']))) {
dww’s picture

StatusFileSize
new3.01 KB

Wow, this is all kinds of broken. :/ I started trying to write a test for this, but it's just uncovering deeper problems. :( Here's a test that should pass, but fails. The fix in #2 isn't sufficient, since we also do similarly unsafe things in core/lib/Drupal/Component/Version/Constraint.php. That code assumes that '8.x-' is optional. So it ignores it. But callers (like system_requirements() and what you posted in #3) are already stripping it off. So if you start with a module at 8.x-8.x-dev, system_requirements() invokes isCompatible() with '8.x-dev', which the preg_match() inside parseConstraint() treats as 'dev'. :(

tl;dr woe be unto you if you reach minor version 8.x

dww’s picture

Issue tags: -Needs tests
StatusFileSize
new3.73 KB
new644 bytes

Based on my findings in #4, here's a different/better fix that gets the test from #4 to pass: stop stripping core compatibility *at all* in system_requirements(). ;) This has the side effect of fixing #3093453: [PP-1] system_requirements() prints out a bogus version string when checking newly added dependencies for free. ;)

Maybe still NW for #3, but that's perhaps out of scope and better handled in a separate issue.

The last submitted patch, 4: 3093789-4.test-only-will-fail.patch, failed testing. View results

lotyrin’s picture

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

I re-queued #5 for both 8.8.x and 9.0.x.

Also, spun off #3 to #3094979: ModulesListForm::buildRow() should more carefully strip core compatibility from version strings to keep the scope small and clear in each issue.

@lotyrin re: #7 thanks for the RTBC! However, for it to "count" I invite you to provide some reasons for changing the status. Did you review the code? Did you test it? Core committers care about why you think something is RTBC.

Thanks,
-Derek

dww’s picture

Status: Reviewed & tested by the community » Needs work

Ugh. #3094979-3: ModulesListForm::buildRow() should more carefully strip core compatibility from version strings wasn't supposed to fail, but it did. :(

Looking deeper, my investigation in #4 wasn't fully accurate.

While Drupal\Component\Version\Constraint::parseConstraint() handles the core compatibility optionally, Drupal\Component\Version\Constraint::isCompatible() does not. It looks like isCompatible() always expects the core compatibility to be stripped (although it's not really documented as such). It's extra confusing since the Constraint constructor takes a core compatibility param, but it only uses it for parseConstraint() and doesn't save it for later. But isCompatible() assumes whatever you're passing is the same core compatibility as the constraint you started with. Fun!

parseConstraint() has a comment that says:

    // Core version is always optional: 8.x-2.x and 2.x is treated the same.

But that doesn't always seem to be true.

I don't have time right now to dig deeper, but some initial manual tests instantiating various Constraint objects and calling isCompatible() on them isn't giving expected results when using version strings involving 8.x-8.x*.

We almost certainly want to add some more cases to core/tests/Drupal/Tests/Component/Version/ConstraintTest.php about this.

It's kinda sad, since we're trying to kill off "core compatibility" entirely. But our constraint/version handling code is definitely buggy around the edges with it, and we probably need to fix that before we can get rid of it.

Alas,
-Derek

berdir’s picture

Somewhat related #3124892: Error message Notice: Undefined index: version in system_requirements() for custom themes that do not define a version. Possibly we could check for an empty version as well here while changing things?

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.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

Title: system_requirements() strips core compatibility in really fragile and dangerous way when comparing versions » [pp-1] system_requirements() strips core compatibility in really fragile and dangerous way when comparing versions
Status: Needs work » Postponed
Related issues: +#3493718: Convert system_requirements() into OOP hooks and install time class
larowlan’s picture

Title: [pp-1] system_requirements() strips core compatibility in really fragile and dangerous way when comparing versions » system_requirements() strips core compatibility in really fragile and dangerous way when comparing versions
Status: Postponed » Active

Blocker is in

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.