CPP-5040: Separate macro expansion for parameters and for files/dirs

This fixes "quoted strings" sneaking into input redirection file and
working directory values when a macro used there expands to a value
requiring quoting, for example, a path containing spaces.

GitOrigin-RevId: 125f3e3436e8c6982fa7ddccac23f4300b2b11ea
This commit is contained in:
Eldar Abusalimov
2020-03-03 21:33:03 +00:00
committed by intellij-monorepo-bot
parent c495a9a9e5
commit ebda994e59
3 changed files with 44 additions and 23 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2018 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.
// Copyright 2000-2020 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.util;
import com.intellij.execution.CantRunException;
@@ -56,10 +56,9 @@ public class JavaParametersUtil {
for (Map.Entry<String, String> each : parameters.getEnv().entrySet()) {
vmParameters = StringUtil.replace(vmParameters, "$" + each.getKey() + "$", each.getValue(), false); //replace env usages
}
vmParameters = ProgramParametersConfigurator.expandMacros(vmParameters);
List<String> vmParametersList = ProgramParametersConfigurator.expandMacrosAndParseParameters(vmParameters);
parameters.getVMParametersList().addAll(vmParametersList);
}
parameters.getVMParametersList().addParametersString(vmParameters);
}
@MagicConstant(valuesFromClass = JavaParameters.class)
@@ -25,13 +25,16 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.execution.ParametersListUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.SystemIndependent;
import org.jetbrains.jps.model.serialization.PathMacroUtil;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ProgramParametersConfigurator {
@@ -60,10 +63,11 @@ public class ProgramParametersConfigurator {
parameters.setPassParentEnvs(configuration.isPassParentEnvs());
}
@Nullable
public String expandPathAndMacros(String s, Module module, Project project) {
return expandMacros(expandPath(s, module, project),
projectContext(project, module));
@Contract("!null, _, _ -> !null")
public @Nullable String expandPathAndMacros(String s, Module module, Project project) {
final String path = expandPath(s, module, project);
if (path == null) return null;
return expandMacros(path, projectContext(project, module), false);
}
private static @NotNull DataContext projectContext(Project project, Module module) {
@@ -74,12 +78,30 @@ public class ProgramParametersConfigurator {
};
}
/**
* Unless expanding macros in a generic value that doesn't represent a path of some kind, or a parameter string,
* consider using the following specialized methods instead:
*
* @see #expandMacrosAndParseParameters For values representing parameters: program arguments, VM options
* @see #expandPathAndMacros For paths: working directory, input file, etc.
*/
public static String expandMacros(@Nullable String path) {
return expandMacros(path, DataContext.EMPTY_CONTEXT);
if (StringUtil.isEmpty(path)) {
return path;
}
return expandMacros(path, DataContext.EMPTY_CONTEXT, false);
}
protected static String expandMacros(@Nullable String path, @NotNull DataContext dataContext) {
if (path == null || !Registry.is("allow.macros.for.run.configurations")) {
public static @NotNull List<String> expandMacrosAndParseParameters(@Nullable String parametersStringWithMacros) {
if (StringUtil.isEmpty(parametersStringWithMacros)) {
return Collections.emptyList();
}
final String expandedParametersString = expandMacros(parametersStringWithMacros, DataContext.EMPTY_CONTEXT, true);
return ParametersListUtil.parse(expandedParametersString);
}
private static @NotNull String expandMacros(@NotNull String path, @NotNull DataContext dataContext, boolean applyParameterEscaping) {
if (!Registry.is("allow.macros.for.run.configurations")) {
return path;
}
@@ -89,7 +111,9 @@ public class ProgramParametersConfigurator {
index != -1 && index < path.length() + template.length();
index = path.indexOf(template, index)) {
String value = StringUtil.notNullize(previewOrExpandMacro(macro, dataContext));
value = ParametersListUtil.escape(value);
if (applyParameterEscaping) {
value = ParametersListUtil.escape(value);
}
path = path.substring(0, index) + value + path.substring(index + template.length());
//noinspection AssignmentToForLoopParameter
index += value.length();
@@ -1,4 +1,4 @@
// Copyright 2000-2019 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.
// Copyright 2000-2020 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.jetbrains.python.run;
import com.intellij.execution.DefaultExecutionResult;
@@ -41,6 +41,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
import java.util.Map;
/**
@@ -226,8 +227,7 @@ public class PythonScriptCommandLineState extends PythonCommandLineState {
}
}
final String scriptOptionsString = getExpandedScriptParameters();
if (scriptOptionsString != null) scriptParameters.addParametersString(scriptOptionsString);
scriptParameters.addParameters(getExpandedScriptParameters());
if (!StringUtil.isEmptyOrSpaces(myConfig.getWorkingDirectory())) {
commandLine.setWorkDirectory(myConfig.getWorkingDirectory());
@@ -238,10 +238,9 @@ public class PythonScriptCommandLineState extends PythonCommandLineState {
}
}
@Nullable
private String getExpandedScriptParameters() {
private @NotNull List<String> getExpandedScriptParameters() {
final String parameters = myConfig.getScriptParameters();
return ProgramParametersConfigurator.expandMacros(parameters);
return ProgramParametersConfigurator.expandMacrosAndParseParameters(parameters);
}
private static String escape(String s) {
@@ -273,15 +272,14 @@ public class PythonScriptCommandLineState extends PythonCommandLineState {
sb.append("runfile('").append(escape(scriptPath)).append("'");
final String parametersString = getExpandedScriptParameters();
final String[] scriptParameters = parametersString != null ? ParametersList.parse(parametersString) : ArrayUtil.EMPTY_STRING_ARRAY;
if (scriptParameters.length != 0) {
final List<String> scriptParameters = getExpandedScriptParameters();
if (scriptParameters.size() != 0) {
sb.append(", args=[");
for (int i = 0; i < scriptParameters.length; i++) {
for (int i = 0; i < scriptParameters.size(); i++) {
if (i != 0) {
sb.append(", ");
}
sb.append("'").append(escape(scriptParameters[i])).append("'");
sb.append("'").append(escape(scriptParameters.get(i))).append("'");
}
sb.append("]");
}