summaryrefslogtreecommitdiffstats
path: root/win/tclWinPipe.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2018-08-20 16:15:37 (GMT)
committersebres <sebres@users.sourceforge.net>2018-08-20 16:15:37 (GMT)
commitcb6f9495b2f5e17442abbdc3ace9c3d16920e044 (patch)
tree0ea5bc3dc5529ee8bd182a81eb5649700769658d /win/tclWinPipe.c
parentbb777b2a7453d7457b8b0198a39fd075acb0a4c0 (diff)
downloadtcl-cb6f9495b2f5e17442abbdc3ace9c3d16920e044.zip
tcl-cb6f9495b2f5e17442abbdc3ace9c3d16920e044.tar.gz
tcl-cb6f9495b2f5e17442abbdc3ace9c3d16920e044.tar.bz2
small amend: avoid reset of unpaired quote flag between arguments (previous affects next) + test cases extended with several injection checks.
Diffstat (limited to 'win/tclWinPipe.c')
-rw-r--r--win/tclWinPipe.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 496e35b..cdbf467 100644
--- a/win/tclWinPipe.c
+++ b/win/tclWinPipe.c
@@ -1537,7 +1537,7 @@ BuildCommandLine(
* command line (TCHAR). */
{
const char *arg, *start, *special;
- int quote, i;
+ int quote = 0, i;
Tcl_DString ds;
const static char *specMetaChars = "&|^<>!%()";
@@ -1561,7 +1561,11 @@ BuildCommandLine(
Tcl_DStringAppend(&ds, " ", 1);
}
- quote = 0;
+ /* Quote flags:
+ * 1 - escape argument;
+ * 2 - previous arguments chain contains unpaired quote-char;
+ */
+ quote &= ~1; /* reset escape flag */
if (arg[0] == '\0') {
quote = 1;
} else {
@@ -1572,31 +1576,36 @@ BuildCommandLine(
if (Tcl_UniCharIsSpace(ch) ||
(count == 1 && (*start=='"' || strchr(specMetaChars, *start)))
) {
- /* must be quoted */
- quote = 1;
+ quote |= 1; /* set escape flag - must be quoted */
break;
}
}
}
- if (!quote) {
+ if (!(quote & 1)) {
+ /* nothing to escape */
Tcl_DStringAppend(&ds, arg, -1);
} else {
+ /* start of argument (open quote-char) */
Tcl_DStringAppend(&ds, "\"", 1);
start = arg;
for (special = arg; *special != '\0'; ) {
+ /* `\\` or `\"` or `\` at end (so equal `\"` because quoted) */
if (*special == '\\' && (special[1] == '\\' || special[1] == '"' || special[1] == '\0')) {
if (special > start) {
Tcl_DStringAppend(&ds, start, (int) (special - start));
}
+ /* escape using backslash */
Tcl_DStringAppend(&ds, "\\\\", 2);
start = ++special;
continue;
}
+ /* ["] */
if (*special == '"') {
- quote ^= 2; /* observe unpaired quotes */
+ quote ^= 2; /* invert unpaired flag - observe unpaired quotes */
if (special > start) {
Tcl_DStringAppend(&ds, start, (int) (special - start));
}
+ /* escape using backslash */
Tcl_DStringAppend(&ds, "\\\"", 2);
start = ++special;
continue;
@@ -1606,7 +1615,7 @@ BuildCommandLine(
if (special > start) {
Tcl_DStringAppend(&ds, start, (int) (special - start));
}
- /* unpaired - escape all special chars inside quotes "..." */
+ /* unpaired - escape all special chars inside quotes like `"..."` */
Tcl_DStringAppend(&ds, "\"", 1);
start = special;
do {
@@ -1619,9 +1628,11 @@ BuildCommandLine(
}
special++;
}
+ /* rest of argument (don't contain special chars) */
if (special > start) {
Tcl_DStringAppend(&ds, start, (int) (special - start));
}
+ /* end of argument (closed quote-char) */
Tcl_DStringAppend(&ds, "\"", 1);
}
}