-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Affected version
3.9.10, 3.9.11, 4.0.0-rc-4
Bug description
Environment: Windows Server 2019
Maven: 3.9.10, invoked via mvnw.cmd wrapper
Minimal example (3.9.10):
$env:MAVEN_OPTS='"-Dfoo=bar|baz"'
mvn
On 4.0.0-rc-4, this requires an additional .mvn/jvm.config file to exist in the project directory or the --yjp arg. Same fundamental issue, different trigger in the script.
Consider this MAVEN_OPTS environment variable (used on a CI server with restricted network access):
-Dhttps.proxyHost=192.0.2.4 -Dhttps.proxyPort=8080 "-Dhttps.nonProxyHosts=*.example.com|*.example.net" -Dhttp.proxyHost=192.0.2.4 -Dhttp.proxyPort=8080 "-Dhttps.nonProxyHosts=*.example.com|*.example.net"
Here we have a few values that require the pipe | as a separator. This requires quoting to correctly process as a value and not a command line pipe. This works in 3.9.9.
MNG-8248 (#10391) made a change that causes the mvnw.cmd script to attempt to prepend a value to MAVEN_OPTS:
set "MAVEN_OPTS=--enable-native-access=ALL-UNNAMED %MAVEN_OPTS%"
Unfortunately, the style used here wraps %MAVEN_OPTS% in further quotes, and due to the nature of Windows batch processing the %% variable is substituted very early, before the quotes are processed. Effectively, this transforms the above example so that the pipes are now outside the quotes, which results in the error:
'*.example.net' is not recognized as an internal or external command,
operable program or batch file.
Specifically, this seems to be the responsible section:
maven/apache-maven/src/bin/mvn.cmd
Lines 175 to 179 in d9f0a48
| @REM MNG-8248 | |
| "%JAVACMD%" --enable-native-access=ALL-UNNAMED -version >nul 2>&1 | |
| if ERRORLEVEL 1 goto skipEnableNativeAccess | |
| set "MAVEN_OPTS=--enable-native-access=ALL-UNNAMED %MAVEN_OPTS%" | |
| :skipEnableNativeAccess |
I can think of a few potential ways to fix this. I'm unsure which one would be most suitable for this project, so I'll list them here:
-
Don't quote the
setarguments. Simply usingset MAVEN_OPTS=--enable-native-access=ALL-UNNAMED %MAVEN_OPTS%instead seems to work, though I can't guarantee that the lack of quoting won't cause other issues. Also, the othersets in the same file seem to use the same quoted style so perhaps this is in some style guide somewhere..? -
Introduce a new variable and don't manipulate
MAVEN_OPTS. e.g.set "USE_NATIVE_ACCESS=--enable-native-access=ALL-UNNAMED"and later insert%USE_NATIVE_ACCESS%into the same command ahead ofMAVEN_OPTS, which would result in the same final command. Alternatively, introduce some kind ofEXTRA_OPTSvariable that is internal to the file -- the key here is to not do anything that would parseMAVEN_OPTS(or other external variables) before they are used. -
Use delayed expansion instead.
setlocal EnableDelayedExpansionand then useset "MAVEN_OPTS=--enable-native-access=ALL-UNNAMED !MAVEN_OPTS!"is fine, because it expands the innerMAVEN_OPTSafter parse where|has special meaning.