[agent] Found by the scheduled Maven bug-hunt routine (ledger #318).
Summary
The reactor planner reads user properties from an existing .mvn/maven.config so that a -Dct.version=1.11.0 override beats a pom's <ct.version>1.10.0</ct.version>. With the compact -Dk=v spelling, that works: the planner emits conflicting_literal_version and doesn't pin. But cli_properties only recognises tokens that start with -D and contain =:
|
fn cli_properties(config: &str) -> BTreeMap<String, String> { |
|
config |
|
.split_whitespace() |
|
.filter_map(|t| t.strip_prefix("-D")?.split_once('=')) |
|
.map(|(k, v)| (k.to_string(), v.to_string())) |
|
.collect() |
|
} |
Two other spellings that Maven itself honours are therefore missed:
--define=ct.version=1.11.0 (the long option). Maven 3.6.3, 3.8.8, 3.9.11 and 4.0.0-rc-7 all apply it.
-D ct.version=1.11.0 (option and value as separate tokens). Maven 3.6.3, 3.8.8 and 3.9.11 apply it; 4.0.0-rc-7 ignores it.
The planner then interpolates ${ct.version} from the pom's <properties> (1.10.0), rewrites the dependency version to the literal 1.10.0-socket.<hex>, and reports applied: 1 with no warning. The build that resolved 1.11.0 before vendoring now resolves 1.10.0-socket.*: a silent downgrade.
This is the same failure family as #459 (profile <properties>) and #488 (BOM / external parent), but the trigger here is different: the planner misparses the user-property source it already tries to honour.
Impact
- A project that pins a newer, already fixed version through
.mvn/maven.config is silently downgraded to the older base plus the patch. Every fix in 1.11.0 that's outside the patch is lost.
vendor exits 0 with applied: 1 and no conflicting_literal_version warning, so nothing tells the user.
- The rewritten literal replaces
${ct.version} in the pom, so a later bump of the property in maven.config no longer takes effect either.
Repro
A reactor with an aggregator root, corp-parent/ and modules a and b (the e2e_vendor_jvm_build::maven_reactor fixture). Module a:
<properties><ct.version>1.10.0</ct.version></properties>
<dependencies><dependency>
<groupId>org.apache.commons</groupId><artifactId>commons-text</artifactId>
<version>${ct.version}</version>
</dependency></dependencies>
printf -- '--define=ct.version=1.11.0\n' > .mvn/maven.config
mvn -B package org.apache.maven.plugins:maven-dependency-plugin:3.5.0:build-classpath -Dmdep.outputFile=target/cp.txt
# a/target/cp.txt → commons-text-1.11.0.jar
# stage the commons-text 1.10.0 patch manifest (as the capstone does), then
socket-patch vendor --json --offline
# applied: 1; warnings: only maven_f_outside_root / maven_mirror_of_all (no conflicting_literal_version)
# a/pom.xml: <version>${ct.version}</version> → <version>1.10.0-socket.1d3c1fd2</version>
# .mvn/maven.config keeps --define=ct.version=1.11.0 and gains the two socket-patch lines
mvn -B package ...build-classpath...
# a/target/cp.txt → .socket/vendor/maven2/.../commons-text-1.10.0-socket.1d3c1fd2.jar ← downgraded
Control: the same project with -Dct.version=1.11.0 gives conflicting_literal_version, no pin, and the build stays on 1.11.0 (3.6.3 / 3.8.8 / 3.9.11 / 4.0.0-rc-7).
Expected vs actual
- Expected:
docs/design/maven-vendoring.md: "Range selectors, unresolved properties, … conflicting explicit versions … produce specific warnings; the backend does not silently claim those unsupported declarations are patched." The planner's own rule ("User properties win over model properties, as in Maven", lookup) should hold for every user-property spelling that Maven accepts in maven.config. Failing that, it should warn when a maven.config token it can't parse could define a property.
- Actual:
--define= and -D k=v are skipped, and the module's resolved version is silently replaced by the patched base.
Matrix (Linux, JDK 21, main 61cfb9b)
| Maven |
--define=ct.version=1.11.0 |
-D ct.version=1.11.0 |
-Dct.version=1.11.0 (control) |
| 3.6.3 |
fail: 1.11.0 → 1.10.0-socket.* |
fail: 1.11.0 → 1.10.0-socket.* |
pass (warned, stays 1.11.0) |
| 3.8.8 |
fail |
fail |
pass |
| 3.9.11 |
fail (reproduced 2×) |
fail |
pass |
| 4.0.0-rc-7 |
fail (reproduced 2×) |
n/a: Maven 4 itself ignores this form (pre-vendor build is already 1.10.0) |
pass |
macOS and Windows weren't probed. The parsing is OS-independent.
Related: --define ct.version=1.11.0 on one line is rejected by 3.9.11 and 4.0.0-rc-7 themselves ("Unrecognized option"), so it isn't part of this bug. A quoted -Dct.version="1.11.0" makes every Maven line fail to build.
First bad commit
2463257 (#277, the v5 consolidation that added the reactor planner and cli_properties). It isn't in any release yet (latest release 4.0.0).
[agent] Found by the scheduled Maven bug-hunt routine (ledger #318).
Summary
The reactor planner reads user properties from an existing
.mvn/maven.configso that a-Dct.version=1.11.0override beats a pom's<ct.version>1.10.0</ct.version>. With the compact-Dk=vspelling, that works: the planner emitsconflicting_literal_versionand doesn't pin. Butcli_propertiesonly recognises tokens that start with-Dand contain=:socket-patch/crates/socket-patch-core/src/vendor/jvm/maven_reactor.rs
Lines 1250 to 1256 in 61cfb9b
Two other spellings that Maven itself honours are therefore missed:
--define=ct.version=1.11.0(the long option). Maven 3.6.3, 3.8.8, 3.9.11 and 4.0.0-rc-7 all apply it.-D ct.version=1.11.0(option and value as separate tokens). Maven 3.6.3, 3.8.8 and 3.9.11 apply it; 4.0.0-rc-7 ignores it.The planner then interpolates
${ct.version}from the pom's<properties>(1.10.0), rewrites the dependency version to the literal1.10.0-socket.<hex>, and reportsapplied: 1with no warning. The build that resolved 1.11.0 before vendoring now resolves 1.10.0-socket.*: a silent downgrade.This is the same failure family as #459 (profile
<properties>) and #488 (BOM / external parent), but the trigger here is different: the planner misparses the user-property source it already tries to honour.Impact
.mvn/maven.configis silently downgraded to the older base plus the patch. Every fix in 1.11.0 that's outside the patch is lost.vendorexits 0 withapplied: 1and noconflicting_literal_versionwarning, so nothing tells the user.${ct.version}in the pom, so a later bump of the property inmaven.configno longer takes effect either.Repro
A reactor with an aggregator root,
corp-parent/and modulesaandb(thee2e_vendor_jvm_build::maven_reactorfixture). Modulea:Control: the same project with
-Dct.version=1.11.0givesconflicting_literal_version, no pin, and the build stays on 1.11.0 (3.6.3 / 3.8.8 / 3.9.11 / 4.0.0-rc-7).Expected vs actual
docs/design/maven-vendoring.md: "Range selectors, unresolved properties, … conflicting explicit versions … produce specific warnings; the backend does not silently claim those unsupported declarations are patched." The planner's own rule ("User properties win over model properties, as in Maven",lookup) should hold for every user-property spelling that Maven accepts inmaven.config. Failing that, it should warn when amaven.configtoken it can't parse could define a property.--define=and-D k=vare skipped, and the module's resolved version is silently replaced by the patched base.Matrix (Linux, JDK 21, main
61cfb9b)--define=ct.version=1.11.0-D ct.version=1.11.0-Dct.version=1.11.0(control)macOS and Windows weren't probed. The parsing is OS-independent.
Related:
--define ct.version=1.11.0on one line is rejected by 3.9.11 and 4.0.0-rc-7 themselves ("Unrecognized option"), so it isn't part of this bug. A quoted-Dct.version="1.11.0"makes every Maven line fail to build.First bad commit
2463257(#277, the v5 consolidation that added the reactor planner andcli_properties). It isn't in any release yet (latest release 4.0.0).