Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NetBeans launch failure on unix shell for arguments with quotes et al #314

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
patches/7724.diff
patches/7733.diff
patches/7750.diff
patches/7908-draft.diff
patches/7910.diff
patches/7921.diff
patches/7923_draft.diff
Expand Down
233 changes: 233 additions & 0 deletions patches/7908-draft.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
diff --git a/java/java.lsp.server/script/bin/nbcode b/java/java.lsp.server/script/bin/nbcode
index 326fe2d08a89..cea526130b6f 100755
--- a/java/java.lsp.server/script/bin/nbcode
+++ b/java/java.lsp.server/script/bin/nbcode
@@ -52,7 +52,20 @@ if [ -f "$progdir/../etc/$APPNAME".conf ] ; then
. "$progdir/../etc/$APPNAME".conf
fi

-# XXX does not correctly deal with spaces in non-userdir params
+doubleQuoteArg() {
+ # wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
+ printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
+}
+
+singleQuoteArg() {
+ # wrap all arguments as '' strings, escaping any internal single-quote characters
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
+ printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
+}
+
args=""

case "`uname`" in
@@ -69,9 +82,11 @@ case "`uname`" in
esac
while [ $# -gt 0 ] ; do
case "$1" in
+ --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
+ ;;
--userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi
;;
- *) args="$args \"$1\""
+ *) args="$args `doubleQuoteArg \"$1\" `"
;;
esac
shift
@@ -121,8 +136,8 @@ case "`uname`" in
Darwin*)
eval exec sh '"$nbexec"' \
--jdkhome '"$jdkhome"' \
- -J-Xdock:name='"$APPNAME"' \
- '"-J-Xdock:icon=$progdir/../../$APPNAME.icns"' \
+ '-J-Xdock:name="$APPNAME"' \
+ '-J-Xdock:icon="$progdir/../../$APPNAME.icns"' \
--clusters '"$clusters"' \
--userdir '"${userdir}"' \
${default_options} \
diff --git a/platform/o.n.bootstrap/launcher/unix/nbexec b/platform/o.n.bootstrap/launcher/unix/nbexec
index 1d6ad6e53019..abac07411d43 100755
--- a/platform/o.n.bootstrap/launcher/unix/nbexec
+++ b/platform/o.n.bootstrap/launcher/unix/nbexec
@@ -56,6 +56,20 @@ postfixcp=""

updater_class=org.netbeans.updater.UpdaterFrame

+doubleQuoteArg() {
+ # wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
+ printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
+}
+
+singleQuoteArg() {
+ # wrap all arguments as '' strings, escaping any internal single-quote characters
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
+ printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
+}
+
#
# parse arguments
#
@@ -85,7 +99,7 @@ EOF
nogui="nogui";
args="$args --nogui"
;;
- --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome=$1; fi
+ --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
;;
# this has to be here for purposes of updater.jar, but it should be
# better to handle this argument inside the java launcher part
@@ -117,8 +131,8 @@ EOF
-psn*)
shift;
;;
- -J*) jopt=`expr "X-$1" : 'X--J\(.*\)'`; jargs="$jargs '$jopt'";;
- *) args="$args \"$1\"" ;;
+ -J*) jopt=`expr "X-$1" : 'X--J\(.*\)'`; jargs="$jargs `singleQuoteArg \"$jopt\" `";;
+ *) args="$args `doubleQuoteArg \"$1\" `";;
esac
shift
done
@@ -187,27 +201,27 @@ fi

jargs="$jargs -XX:+HeapDumpOnOutOfMemoryError"
if [ -z "`echo $jargs | grep -- "-XX:HeapDumpPath="`" ] ; then
- jargs="$jargs -XX:HeapDumpPath=\"${userdir}/var/log/heapdump.hprof\""
+ jargs="$jargs -XX:HeapDumpPath=`doubleQuoteArg \"${userdir}/var/log/heapdump.hprof\" `"
fi
# rename old heap dump to .old
mv "${userdir}/var/log/heapdump.hprof" "${userdir}/var/log/heapdump.hprof.old" > /dev/null 2>&1

jargs_without_clusters="$jargs -Djava.security.manager=allow"
-jargs="-Dnetbeans.dirs=\"${clusters}\" $jargs_without_clusters"
+jargs="-Dnetbeans.dirs=`doubleQuoteArg \"${clusters}\" ` $jargs_without_clusters"

if [ -z "$cachedirspecified" ]; then
cachedir="${userdir}/var/cache"
fi

if [ `uname` != Darwin -a -z "$nosplash" -a -f "${cachedir}/splash.png" -a ! -f "${userdir}/lock" ]; then
- jargs="$jargs -splash:\"${cachedir}/splash.png\""
+ jargs="$jargs -splash:`doubleQuoteArg \"${cachedir}/splash.png\" `"
fi

jdkhome=`absolutize_path "$jdkhome"`

-args="--userdir \"${userdir}\" $args"
+args="--userdir `doubleQuoteArg \"${userdir}\"` $args"

-args="--cachedir \"${cachedir}\" $args"
+args="--cachedir `doubleQuoteArg \"${cachedir}\"` $args"

append_jars_to_cp() {
dir="$1"
@@ -279,7 +293,7 @@ build_cp() {
}

do_run_updater() {
- eval "\"$jdkhome/bin/java\"" -classpath "\"${updatercp}\"" "$jargs" "-Dnetbeans.user=\"$userdir\"" $updater_class "$args"
+ eval '"$jdkhome/bin/java"' -classpath '"${updatercp}"' "$jargs" '-Dnetbeans.user="$userdir"' $updater_class "$args"
construct_cp
}

@@ -360,7 +374,7 @@ else
fi

if [ ! -z "${DEFAULT_USERDIR_ROOT}" ] ; then
- jargs="-Dnetbeans.default_userdir_root=\"${DEFAULT_USERDIR_ROOT}\" $jargs"
+ jargs="-Dnetbeans.default_userdir_root=`doubleQuoteArg \"${DEFAULT_USERDIR_ROOT}\"` $jargs"
unset DEFAULT_USERDIR_ROOT
fi

@@ -427,7 +441,7 @@ while [ "$restart" ] ; do
#
delete_new_clusters_file
rm -f "${restart_file}"
- eval ${_NB_PROFILE_CMD} "\"${jdkhome}/bin/java\"" -Djdk.home="\"${jdkhome}\"" -classpath "\"$cp\"" \
+ eval ${_NB_PROFILE_CMD} '"${jdkhome}/bin/java"' '-Djdk.home="${jdkhome}"' -classpath '"$cp"' \
"$jargs" org.netbeans.Main "$args" '<&0' '&'
PID=$!
trap "kill $PID" EXIT
diff --git a/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java b/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
index 3ccd38505fed..91923d6e4118 100644
--- a/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
+++ b/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
@@ -22,9 +22,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Lookup;
import org.openide.util.Utilities;
@@ -77,7 +82,57 @@ public void testStartsArePassedInUnparsed() throws Exception {
fail(str + " should be there: " + a);
}
}
-
+
+ public void testJdkHomePassed() throws Exception {
+ File wd = new File(getWorkDir(), "jdk dir");
+ wd.mkdirs();
+ String origJdkHome = System.getProperty("java.home");
+ Path origJdk = new File(origJdkHome).toPath();
+ String[] linkNames = {
+ "openjdk's jdkhome",
+ "jdk \"latest\"",
+ "current$JAVA_HOME",
+ "link\"'d jdk"
+ };
+ Path[] links = new Path[linkNames.length];
+ for (int i = 0; i < linkNames.length; i++) {
+ links[i] = new File(wd, linkNames[i]).toPath();
+ }
+
+ String[] args = {
+ "1 * * * *",
+ "a b",
+ "c d",
+ "$1",
+ "$2",
+ "$3\"`$2`'$1"
+ };
+
+ for (Path link : links) {
+ try {
+ Path l = Files.createSymbolicLink(link, origJdk);
+ if (link.compareTo(l) != 0) {
+ fail("link creation mismatch: expected<" + link + "> != actual<" + l + ">");
+ }
+ System.setProperty("java.home", link.toString());
+ String[] nbArgs = {
+ "--jdkhome",
+ link.toString()
+ };
+ run(wd, Stream.concat(Arrays.stream(nbArgs), Arrays.stream(args)).collect(Collectors.toList()).toArray(new String[]{}));
+
+ String[] gotArgs = MainCallback.getArgs(getWorkDir());
+ assertNotNull("args passed in", gotArgs);
+ for (int in = args.length, jn = gotArgs.length, i = 0, j = Math.max(0, jn - in); i < in ; i++, j++) {
+ if (j >= jn || !Objects.equals(args[i], gotArgs[j]))
+ fail("args do not match: expected<" + Arrays.toString(args) + "> != actual<" + Arrays.toString(gotArgs) + ">");
+ }
+ } finally {
+ System.setProperty("java.home", origJdkHome);
+ Files.delete(link);
+ }
+ }
+ }

private void run(File workDir, String... args) throws Exception {
URL u = Lookup.class.getProtectionDomain().getCodeSource().getLocation();
23 changes: 19 additions & 4 deletions script/bin/nbcode
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,20 @@ if [ -f "$progdir/../etc/$APPNAME".conf ] ; then
. "$progdir/../etc/$APPNAME".conf
fi

# XXX does not correctly deal with spaces in non-userdir params
doubleQuoteArg() {
# wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
# use printf to avoid echo interpretation behaviors such as escapes and line continuation
# Mac bsd_sed does not support group-0, so pattern uses group-1
printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
}

singleQuoteArg() {
# wrap all arguments as '' strings, escaping any internal single-quote characters
# use printf to avoid echo interpretation behaviors such as escapes and line continuation
# Mac bsd_sed does not support group-0, so pattern uses group-1
printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
}

args=""

case "`uname`" in
Expand All @@ -69,9 +82,11 @@ case "`uname`" in
esac
while [ $# -gt 0 ] ; do
case "$1" in
--jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
;;
--userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi
;;
*) args="$args \"$1\""
*) args="$args `doubleQuoteArg \"$1\" `"
;;
esac
shift
Expand Down Expand Up @@ -121,8 +136,8 @@ case "`uname`" in
Darwin*)
eval exec sh '"$nbexec"' \
--jdkhome '"$jdkhome"' \
-J-Xdock:name='"$APPNAME"' \
'"-J-Xdock:icon=$progdir/../../$APPNAME.icns"' \
'-J-Xdock:name="$APPNAME"' \
'-J-Xdock:icon="$progdir/../../$APPNAME.icns"' \
--clusters '"$clusters"' \
--userdir '"${userdir}"' \
${default_options} \
Expand Down