Inventory: software matching can silently attach new versions/installations to a trashed duplicate - #25456
Open
Megachip wants to merge 12 commits into
Conversation
#BUG On location view, I can assign documents to a location, on document view there is no option to choose a location
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewPowered by Qodo |
trasher
reviewed
Sep 10, 2026
trasher
left a comment
Contributor
There was a problem hiding this comment.
Fix seem correct to me - waiting for tests suite to ends.
You'll have few CS issues to fix.
Fix duplicated-software test to seed the active entry via inventory
trasher
approved these changes
Sep 18, 2026
stonebuzz
suggested changes
Sep 18, 2026
| $this->assertCount( | ||
| 1, | ||
| $on_active, | ||
| 'the new version/installation must attach to the active software, not the deleted duplicate' |
Contributor
There was a problem hiding this comment.
The assertions only look at glpi_softwareversions; the message claims "version/installation" but no Item_SoftwareVersion row is checked. Adding one assertion on the installation would cover the part of the bug that actually affects the asset sheet.
$installs = (new Item_SoftwareVersion())->find(['softwareversions_id' => (int) current($on_active)['id']]);
$this->assertCount(1, $installs);| $soft = new \Software(); | ||
| $version = new SoftwareVersion(); | ||
|
|
||
| $computers_id = $computer->add([ |
Contributor
There was a problem hiding this comment.
The computer is pre-created by hand, but the first inventory would create it anyway and nothing asserts that the inventory matched this row rather than creating a second one. Dropping the manual Computer::add() would make the fixture leaner without weakening the test.
Rom1-B
approved these changes
Sep 18, 2026
Removed unused computer instantiation and related assertions.
Add assertions to verify installation links to active software version.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug description
When two
glpi_softwaresrows exist with identical name + manufacturerafter a manual merge),
Glpi\Inventory\Asset\Software::populateSoftware()can resolve future inventory imports to the trashed row instead of
the active one, so new SoftwareVersion/Item_SoftwareVersion entries
keep landing on a deleted item.
Root cause: the existing-software lookup has no
ORDER BYand nois_deletedfilter, and the surroundingwhile ($row = ...)loopoverwrites the cached id on every row instead of taking the first
match — so the last row returned by MySQL wins, which is undefined
without an explicit order and in practice tends to be the highest id.
Steps to reproduce
glpi_softwaresrow with the exact samename/manufacturer/entities_id/is_recursive, then move it to the
trashbin (
is_deleted = 1), so it has a higher id than the activeone.
to the trashed (higher-id) software, not the active one.
Fix
ORDER BY is_deleted ASC, id ASC LIMIT 1on the lookup, single fetchinstead of the loop. Active software is always preferred; among rows
with the same is_deleted status, the lowest id wins deterministically.
If only a deleted duplicate matches, it is still reused (unchanged
behavior) — this PR only fixes the priority between active and
deleted, not whether deleted rows are eligible at all.
Test plan
Added
testDuplicatedSoftPrefersActiveOverDeleted()inSoftwareTest.php: creates an active software (lower id) and atrashed duplicate (higher id), runs an inventory, asserts the new
version/installation lands on the active one only.