You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/15 13:46:40 UTC
(maven) branch master updated: Fix NPE on a recursive property reference in a list field
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new 0aaa578f13 Fix NPE on a recursive property reference in a list field
0aaa578f13 is described below
commit 0aaa578f13a3fb87bd54c2aa9f7652271c83a8b8
Author: renechoi <11...@users.noreply.github.com>
AuthorDate: Tue Sep 15 22:46:32 2026 +0900
Fix NPE on a recursive property reference in a list field
DefaultModelInterpolator records an ERROR and returns null when the
interpolator throws on a recursive variable reference. The generated
transformer stores that null in List<String> model fields such as
build/filters, whose Properties sibling branch already guards against
it, and the immutable model constructor then copies the list with
List.copyOf. The build fails with a bare NullPointerException instead
of the "recursive variable reference" error that was just collected.
Return the original text instead, which is what the Properties branch
and StringVisitorModelInterpolator (MNG-8174) already do. The returned
instance is identical, so the transformer's newVal != oldVal check
stays false and unaffected models are still returned unchanged.
---
.../maven/impl/model/DefaultModelInterpolator.java | 6 +++++-
.../impl/model/DefaultModelInterpolatorTest.java | 20 ++++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelInterpolator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelInterpolator.java
index da729b4af6..adc185cc2f 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelInterpolator.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelInterpolator.java
@@ -134,7 +134,11 @@ private InnerInterpolator createInterpolator(
return di.interpolate(value, null, cycleMap, cb, postprocessor, false);
} catch (InterpolatorException e) {
problems.add(BuilderProblem.Severity.ERROR, ModelProblem.Version.BASE, e.getMessage(), e);
- return null;
+ // Keep the original text rather than handing null back to the transformer. A null
+ // ends up as an element of a List<String> model field such as build/filters, and
+ // the immutable model constructor copies that list with List.copyOf, which fails
+ // with a bare NullPointerException that hides the problem just collected above.
+ return value;
}
};
}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelInterpolatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelInterpolatorTest.java
index 4ee3e14c59..c1c35ffd0f 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelInterpolatorTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelInterpolatorTest.java
@@ -632,6 +632,26 @@ public void testRecursiveExpressionCycleNPE() throws Exception {
assertTrue(collector.getErrors().get(0).contains("recursive variable reference"));
}
+ @Test
+ public void testRecursiveExpressionCycleInListField() throws Exception {
+ Map<String, String> props = new HashMap<>();
+ props.put("aa", "${bb}");
+ props.put("bb", "${aa}");
+
+ Model model = Model.newBuilder()
+ .properties(props)
+ .build(Build.newBuilder().filters(List.of("${aa}")).build())
+ .build();
+
+ SimpleProblemCollector collector = new SimpleProblemCollector();
+
+ ModelBuilderRequest request = createModelBuildingRequest(Map.of()).build();
+ Model out = interpolator.interpolateModel(model, null, request, collector);
+
+ assertEquals(List.of("${aa}"), out.getBuild().getFilters());
+ assertTrue(collector.getErrors().get(0).contains("recursive variable reference"));
+ }
+
@Disabled("per def cannot be recursive: ${basedir} is immediately going for project.basedir")
@Test
public void testRecursiveExpressionCycleBaseDir() throws Exception {