diff --git a/platform/platform-impl/src/com/intellij/execution/wsl/WSLDistribution.java b/platform/platform-impl/src/com/intellij/execution/wsl/WSLDistribution.java index 6cefdb04e4c4..8cc7462e75d4 100644 --- a/platform/platform-impl/src/com/intellij/execution/wsl/WSLDistribution.java +++ b/platform/platform-impl/src/com/intellij/execution/wsl/WSLDistribution.java @@ -3,6 +3,7 @@ package com.intellij.execution.wsl; import com.intellij.credentialStore.CredentialAttributes; import com.intellij.credentialStore.CredentialPromptDialog; +import com.intellij.execution.CommandLineUtil; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.ParametersList; @@ -17,6 +18,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase; import com.intellij.util.ArrayUtilRt; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -203,7 +205,8 @@ public class WSLDistribution { commandLineString.append(realParamsList.get(1)); } else { - commandLineString.append(commandLine.getCommandLineString()); + List bashParameters = ContainerUtil.prepend(realParamsList, commandLine.getExePath()); + commandLineString.append(StringUtil.join(bashParameters, CommandLineUtil::posixQuote, " ")); } if (askForSudo) { // fixme shouldn't we sudo for every chunk? also, preserve-env, login? diff --git a/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLCommandEscapingTest.java b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLCommandEscapingTest.java new file mode 100644 index 000000000000..f432a8ed3322 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLCommandEscapingTest.java @@ -0,0 +1,67 @@ +// Copyright 2000-2017 JetBrains s.r.o. +// Use of this source code is governed by the Apache 2.0 license that can be +// found in the LICENSE file. +package com.intellij.execution.wsl; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.CapturingProcessHandler; +import com.intellij.execution.process.ProcessOutput; +import com.intellij.testFramework.HeavyPlatformTestCase; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static org.junit.Assume.assumeTrue; + +public class WSLCommandEscapingTest extends HeavyPlatformTestCase { + + @Nullable + private WSLDistribution myWSL; + + @Override + public void setUp() throws Exception { + super.setUp(); + myWSL = ContainerUtil.getFirstItem(WSLUtil.getAvailableDistributions()); + } + + private void assumeWSLAvailable() { + assumeTrue("WSL unavailable", myWSL != null); + } + + public void testCommandLineEscaping() { + assumeWSLAvailable(); + + assertWslCommandOutput("\n", "echo"); + assertWslCommandOutput("asd\n", "echo", "asd"); + assertWslCommandOutput("\"test\"\n", "echo", "\"test\""); + assertWslCommandOutput("'test'\n", "echo", "'test'"); + assertWslCommandOutput("(asd)\n", "echo", "(asd)"); + assertWslCommandOutput("&& exit && exit\n", "echo", "&& exit", "&&", "exit"); + assertWslCommandOutput(".*\n", "echo", ".*"); + assertWslCommandOutput("*\n", "echo", "*"); + assertWslCommandOutput("\\\\\\\"\n", "echo", "\\\\\\\""); + assertWslCommandOutput("_ \" ' ) \\\n", "echo", "_", "\"", "", "'", ")", "\\"); + assertWslCommandOutput("' ''' '' '\n", "echo", "'", "'''", "''", "'"); + } + + private void assertWslCommandOutput(@NotNull String expectedOut, String command, String... parameters) { + final GeneralCommandLine commandLine = new GeneralCommandLine(); + commandLine.setExePath(command); + commandLine.addParameters(parameters); + + try { + final GeneralCommandLine cmd = myWSL.patchCommandLine(commandLine, null, null, false); + final CapturingProcessHandler process = new CapturingProcessHandler(cmd); + ProcessOutput output = process.runProcess(10_000); + + assertFalse(output.isTimeout()); + assertEquals(0, output.getExitCode()); + assertEquals(expectedOut, output.getStdout()); + assertEquals("", output.getStderr()); + } + catch (ExecutionException e) { + fail(e.getMessage()); + } + } +} \ No newline at end of file