Skip to content

Commit 8989c91

Browse files
committed
fix(java_opts): use string-split to restore JAVA_OPTS placeholder
bash 4.x and 5.x treat backslash in ${//} replacement strings differently: bash 5.x collapses '\\' to '\', bash 4.x leaves it as '\\'. A JAVA_OPTS value containing a single backslash (e.g. -Dpattern=foo\|bar) was therefore doubled on CI workers running bash 4.x, causing the unit test 'preserves backslashes in JAVA_OPTS values' to fail remotely while passing locally on bash 5.x. Replace the pre-escaped ${//} substitution with string-split using ${%%} and ${#} — pure string operations that never interpret backslash or '&', identical across bash 3/4/5.
1 parent 7dc3b71 commit 8989c91

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

src/java/frameworks/java_opts_writer.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,13 @@ case "$USER_JAVA_OPTS" in
141141
esac
142142
143143
# Escape replacement-special chars once; these values are loop-invariant.
144+
# USER_JAVA_OPTS is injected via string-split below (not ${//}) — bash 4.x and 5.x
145+
# treat '\\' in replacement strings differently, corrupting backslashes.
144146
_escaped_deps_dir="${DEPS_DIR//\\/\\\\}"
145147
_escaped_deps_dir="${_escaped_deps_dir//&/\\&}"
146148
_escaped_home="${HOME//\\/\\\\}"
147149
_escaped_home="${_escaped_home//&/\\&}"
148150
_user_java_opts_placeholder='__JAVA_OPTS_BUILDPACK_PLACEHOLDER__'
149-
_escaped_user_java_opts="${USER_JAVA_OPTS//\\/\\\\}"
150-
_escaped_user_java_opts="${_escaped_user_java_opts//&/\\&}"
151151
152152
if [ -d "$DEPS_DIR/%s/java_opts" ]; then
153153
for opts_file in "$DEPS_DIR/%s/java_opts"/*.opts; do
@@ -194,8 +194,16 @@ if [ -d "$DEPS_DIR/%s/java_opts" ]; then
194194
;;
195195
esac
196196
197-
# Now safely substitute JAVA_OPTS after expansion (preserves quotes, backslashes, and ampersands)
198-
opts_content="${opts_content//$_user_java_opts_placeholder/$_escaped_user_java_opts}"
197+
# Restore USER_JAVA_OPTS via string-split, not ${//}: bash 4.x and 5.x
198+
# treat '\\' in replacement strings differently, corrupting backslashes.
199+
# %% / # are pure string ops — no special-char interpretation, any bash.
200+
# Guard required: without placeholder present, %% and # return the full
201+
# string, so omitting the guard duplicates opts_content.
202+
if [[ "$opts_content" == *"$_user_java_opts_placeholder"* ]]; then
203+
_before="${opts_content%%"$_user_java_opts_placeholder"*}"
204+
_after="${opts_content#*"$_user_java_opts_placeholder"}"
205+
opts_content="${_before}${USER_JAVA_OPTS}${_after}"
206+
fi
199207
200208
if [ -n "$opts_content" ]; then
201209
JAVA_OPTS="$JAVA_OPTS $opts_content"

0 commit comments

Comments
 (0)