Skip to content

Detect cyclic property references instead of StackOverflowError#7396

Merged
sambsnyd merged 1 commit intomainfrom
kmccarp/maven-property-cycle
Apr 16, 2026
Merged

Detect cyclic property references instead of StackOverflowError#7396
sambsnyd merged 1 commit intomainfrom
kmccarp/maven-property-cycle

Conversation

@kmccarp
Copy link
Copy Markdown
Contributor

@kmccarp kmccarp commented Apr 16, 2026

Background / problem

When Maven properties form a cycle (e.g. <revision>${revision}</revision>, or a two-hop cycle like <revision>${project.build.version}</revision> with <project.build.version>${revision}</project.build.version>), PropertyPlaceholderHelper.parseStringValue() produces a StackOverflowError. This crashes the Moderne CLI during its POM pre-parsing step before Maven is even invoked.

The existing visited-placeholder tracking only guarded key resolution (nested placeholder keys like ${${foo}}), but not value resolution. When a resolved value contained a placeholder already being resolved, the value-resolution path re-entered parseStringValue without any cycle check, creating infinite recursion.

Solution

When a placeholder is already in the visited set, skip its resolution entirely and leave it unresolved in the output. This matches the existing cycle-detection intent while covering the value-resolution path that was previously unguarded.

Test plan

  • PropertyPlaceholderHelperTest.selfReferencingPropertyDoesNotStackOverflow -- direct self-reference
  • PropertyPlaceholderHelperTest.cyclicPropertyReferenceDoesNotStackOverflow -- two-hop cycle
  • MavenParserTest.selfReferencingPropertyDoesNotStackOverflow -- full Maven parse
  • MavenParserTest.cyclicPropertyReferenceDoesNotStackOverflow -- multi-module POM cycle
  • All existing circular reference tests pass (circularMavenProperty, circularProjectVersionReference, etc.)
  • End-to-end: published to Maven local, built CLI fat jar, confirmed mod build no longer StackOverflows on reproducer repos

When Maven properties form a cycle (e.g. <revision>${revision}</revision>,
or <revision>${project.build.version}</revision> with
<project.build.version>${revision}</project.build.version>),
PropertyPlaceholderHelper.parseStringValue() recursed infinitely on
line 150, producing a StackOverflowError.

The existing visited-placeholder tracking only guarded key resolution
(nested placeholder keys like ${${foo}}), but not value resolution.
When a resolved value contained a placeholder already being resolved,
the value-resolution path on line 150 re-entered parseStringValue
without any cycle check, creating infinite recursion.

When a placeholder is already in the visited set, skip its resolution
entirely and leave it unresolved in the output. This matches the
existing cycle-detection intent while covering the value-resolution
path that was previously unguarded.
@github-project-automation github-project-automation bot moved this from In Progress to Ready to Review in OpenRewrite Apr 16, 2026
@sambsnyd sambsnyd merged commit 5d5edfd into main Apr 16, 2026
1 check failed
@sambsnyd sambsnyd deleted the kmccarp/maven-property-cycle branch April 16, 2026 21:19
@github-project-automation github-project-automation bot moved this from Ready to Review to Done in OpenRewrite Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants