Skip to content

Fix JsonManipulator::addSubNode modifying a nested key with the same name - #13109

Merged
Seldaek merged 5 commits into
composer:mainfrom
kevin9327:fix-addsubnode-nested-key
Oct 8, 2026
Merged

Seldaek merged 5 commits into
composer:mainfrom
kevin9327:fix-addsubnode-nested-key

Conversation

@kevin9327

@kevin9327 kevin9327 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

JsonManipulator::addSubNode() (used by addConfigSetting(), addProperty() and so composer config) looks for the existing child with a regex that is not anchored to the node's top level. If the same key name appears deeper inside the node first, that nested value gets replaced instead, and the intended top-level key is never added.

Reproduction with a composer.json containing:

{
    "extra": {
        "symfony": {
            "allow-contrib": true
        }
    }
}

composer config extra.allow-contrib false --json turns extra.symfony.allow-contrib into false and does not add extra.allow-contrib. Likewise addConfigSetting('php', ...) on a file with config.platform.php set overwrites the platform version instead of adding config.php.

The fix anchors $childRegex at the opening brace of the node and only allows skipping over complete "key": value members before the target key, so only direct children match. Nested objects are consumed whole by (?&json), so keys inside them can no longer match.

Added tests for addConfigSetting, addSubNode and addProperty with a nested same-name key; they fail without the change. tests/Composer/Test/Json passes and PHPStan reports no errors for the file.

Targeting 2.10 since the code is identical there and it's a bug fix; happy to retarget to main if preferred.

@Seldaek Seldaek added this to the 2.11 milestone Oct 8, 2026
@Seldaek
Seldaek changed the base branch from 2.10 to main October 8, 2026 22:13
…Node

The lazy loop over sibling pairs backtracked through every pair when the
key was missing, and used a stack frame per sibling when it was present.
…ched

Existence now comes from the decoded JSON, so a regex miss no longer appends
a duplicate key and PCRE limit errors let callers fall back to a full rewrite.
@Seldaek

Seldaek commented Oct 8, 2026

Copy link
Copy Markdown
Member

Thanks

@Seldaek
Seldaek merged commit b187adb into composer:main Oct 8, 2026
20 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants