mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-08 16:55:38 +02:00
Bug 474648 - Wrong arguments are passed to a program in debug mode
Change-Id: Ie9ab74e0142c10ad43891febf910e2fb49b2ec61 Signed-off-by: Sergey Grant <sergey.grant@me.com>
This commit is contained in:
parent
8d898be364
commit
8360f715eb
2 changed files with 113 additions and 44 deletions
|
@ -7,12 +7,13 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Ericsson - Initial API and implementation
|
* Ericsson - Initial API and implementation
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
* Marc Khouzam (Ericsson) - Support empty arguments (bug 412471)
|
* Marc Khouzam (Ericsson) - Support empty arguments (bug 412471)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,25 +24,55 @@ import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
*/
|
*/
|
||||||
public class MIGDBSetArgs extends MIGDBSet {
|
public class MIGDBSetArgs extends MIGDBSet {
|
||||||
|
|
||||||
/** @since 4.0 */
|
/** @since 4.0 */
|
||||||
public MIGDBSetArgs(IMIContainerDMContext dmc) {
|
public MIGDBSetArgs(IMIContainerDMContext dmc) {
|
||||||
this(dmc, new String[0]);
|
this(dmc, new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 4.0 */
|
/** @since 4.0 */
|
||||||
public MIGDBSetArgs(IMIContainerDMContext dmc, String[] arguments) {
|
public MIGDBSetArgs(IMIContainerDMContext dmc, String[] arguments) {
|
||||||
super(dmc, null);
|
super(dmc, null);
|
||||||
|
fParameters = new ArrayList<Adjustable>();
|
||||||
|
fParameters.add(new MIStandardParameterAdjustable("args")); //$NON-NLS-1$
|
||||||
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
|
fParameters.add(new MIArgumentAdjustable(arguments[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String[] cmdArray = new String[arguments.length + 1];
|
private static class MIArgumentAdjustable extends MICommandAdjustable {
|
||||||
cmdArray[0] = "args"; //$NON-NLS-1$
|
|
||||||
for (int i = 0; i < arguments.length; i++) {
|
public MIArgumentAdjustable(String value) {
|
||||||
if (arguments[i].isEmpty()) {
|
super(value);
|
||||||
// An empty parameter can be passed with two single quotes
|
}
|
||||||
cmdArray[i + 1] = "''"; //$NON-NLS-1$
|
|
||||||
} else {
|
@Override
|
||||||
cmdArray[i + 1] = arguments[i];
|
public String getAdjustedValue() {
|
||||||
}
|
// Replace and concatenate all occurrences of:
|
||||||
}
|
// ' with "'"
|
||||||
setParameters(cmdArray);
|
// (as ' is used to surround everything else
|
||||||
}
|
// it has to be quoted or escaped)
|
||||||
|
// newline character with $'\n'
|
||||||
|
// (\n is treated literally within quotes or
|
||||||
|
// as just 'n' otherwise, whilst supplying
|
||||||
|
// the newline character literally ends the command)
|
||||||
|
// Anything in between and around these occurrences
|
||||||
|
// is surrounded by single quotes.
|
||||||
|
// (to prevent bash from carrying out substitutions
|
||||||
|
// or running arbitrary code with backticks or $())
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append('\'');
|
||||||
|
for (int j = 0; j < value.length(); j++) {
|
||||||
|
char c = value.charAt(j);
|
||||||
|
if (c == '\'') {
|
||||||
|
builder.append("'\"'\"'"); //$NON-NLS-1$
|
||||||
|
} else if (c == '\n') {
|
||||||
|
builder.append("'$'\\n''"); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
builder.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append('\'');
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,20 +552,12 @@ public class LaunchConfigurationAndRestartTest extends BaseTestCase {
|
||||||
fExpService.getFormattedValueContext(argcDmc, MIExpressions.DETAILS_FORMAT), rm);
|
fExpService.getFormattedValueContext(argcDmc, MIExpressions.DETAILS_FORMAT), rm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
fExpService.getExecutor().execute(query);
|
||||||
fExpService.getExecutor().execute(query);
|
FormattedValueDMData value = query.get(500, TimeUnit.MILLISECONDS);
|
||||||
FormattedValueDMData value = query.get(500, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
// Argc should be 2: the program name and the one arguments
|
// Argc should be 2: the program name and the one arguments
|
||||||
assertTrue("Expected 2 but got " + value.getFormattedValue(),
|
assertTrue("Expected 2 but got " + value.getFormattedValue(),
|
||||||
value.getFormattedValue().trim().equals("2"));
|
value.getFormattedValue().trim().equals("2"));
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
fail(e.getCause().getMessage());
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that argv is also correct.
|
// Check that argv is also correct.
|
||||||
final IExpressionDMContext argvDmc = SyncUtil.createExpression(stoppedEvent.getDMContext(), "argv[argc-1]");
|
final IExpressionDMContext argvDmc = SyncUtil.createExpression(stoppedEvent.getDMContext(), "argv[argc-1]");
|
||||||
|
@ -576,18 +568,64 @@ public class LaunchConfigurationAndRestartTest extends BaseTestCase {
|
||||||
fExpService.getFormattedValueContext(argvDmc, MIExpressions.DETAILS_FORMAT), rm);
|
fExpService.getFormattedValueContext(argvDmc, MIExpressions.DETAILS_FORMAT), rm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
fExpService.getExecutor().execute(query2);
|
||||||
fExpService.getExecutor().execute(query2);
|
value = query2.get(500, TimeUnit.MILLISECONDS);
|
||||||
FormattedValueDMData value = query2.get(500, TimeUnit.MILLISECONDS);
|
assertTrue("Expected \"" + argumentUsedByGDB + "\" but got " + value.getFormattedValue(),
|
||||||
assertTrue("Expected \"" + argumentUsedByGDB + "\" but got " + value.getFormattedValue(),
|
value.getFormattedValue().trim().endsWith(argumentUsedByGDB));
|
||||||
value.getFormattedValue().trim().endsWith(argumentUsedByGDB));
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e.getMessage());
|
/**
|
||||||
} catch (ExecutionException e) {
|
* This test will tell the launch to set some more arguments for the program. We will
|
||||||
fail(e.getCause().getMessage());
|
* then check that the program has the same arguments.
|
||||||
} catch (TimeoutException e) {
|
* See bug 474648
|
||||||
fail(e.getMessage());
|
*/
|
||||||
}
|
@Test
|
||||||
|
public void testSettingArgumentsWithSpecialSymbols() throws Throwable {
|
||||||
|
// Test that arguments are parsed correctly:
|
||||||
|
// The string provided by the user is split into arguments on spaces
|
||||||
|
// except for those inside quotation marks, double or single.
|
||||||
|
// Any character within quotation marks or after the backslash character
|
||||||
|
// is treated literally, whilst these special characters have to be
|
||||||
|
// escaped explicitly to be recorded.
|
||||||
|
// All other characters including semicolons, backticks, pipes, dollars and newlines
|
||||||
|
// must be treated literally.
|
||||||
|
String argumentToPreserveSpaces = "--abc=\"x;y;z\nsecondline: \"`date`$PS1\"`date | wc`\"";
|
||||||
|
String argumentUsedByGDB = "\"--abc=x;y;z\\nsecondline: `date`$PS1`date | wc`\"";
|
||||||
|
|
||||||
|
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, argumentToPreserveSpaces);
|
||||||
|
doLaunch();
|
||||||
|
|
||||||
|
MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
|
||||||
|
|
||||||
|
// Check that argc is correct
|
||||||
|
final IExpressionDMContext argcDmc = SyncUtil.createExpression(stoppedEvent.getDMContext(), "argc");
|
||||||
|
Query<FormattedValueDMData> query = new Query<FormattedValueDMData>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
|
||||||
|
fExpService.getFormattedExpressionValue(
|
||||||
|
fExpService.getFormattedValueContext(argcDmc, MIExpressions.DETAILS_FORMAT), rm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fExpService.getExecutor().execute(query);
|
||||||
|
FormattedValueDMData value = query.get(500, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
// Argc should be 2: the program name and the four arguments.
|
||||||
|
assertTrue("Expected 2 but got " + value.getFormattedValue(),
|
||||||
|
value.getFormattedValue().trim().equals("2"));
|
||||||
|
|
||||||
|
// Check that argv is also correct.
|
||||||
|
final IExpressionDMContext argvDmc = SyncUtil.createExpression(stoppedEvent.getDMContext(), "argv[argc-1]");
|
||||||
|
Query<FormattedValueDMData> query2 = new Query<FormattedValueDMData>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
|
||||||
|
fExpService.getFormattedExpressionValue(
|
||||||
|
fExpService.getFormattedValueContext(argvDmc, MIExpressions.DETAILS_FORMAT), rm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fExpService.getExecutor().execute(query2);
|
||||||
|
value = query2.get(500, TimeUnit.MILLISECONDS);
|
||||||
|
assertTrue("Expected \"" + argumentUsedByGDB + "\" but got " + value.getFormattedValue(),
|
||||||
|
value.getFormattedValue().endsWith(argumentUsedByGDB));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue