authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-22 20:07:43-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-06-22 20:07:43-04:00
log78c6d39cd49225bdfd2de4da7b1730ba26a41ba4
tree9956a770d099291106cdbb754475b3c7e47c29f1
parent923c0feda1e42dcaf65ab80bafd7400996b39861
parent7cb41a415a6eca7d13980a62ee5727b4adcad8b0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5667 from cartr/windows-arguments-unclosed-quote

In std.process.ArgIteratorWindows, don't treat unclosed quotes like they're escaped

1 files changed, 7 insertions(+), 34 deletions(-)

lib/std/process.zig+7-34
...@@ -281,9 +281,6 @@ pub const ArgIteratorWasi = struct {...@@ -281,9 +281,6 @@ pub const ArgIteratorWasi = struct {
281pub const ArgIteratorWindows = struct {281pub const ArgIteratorWindows = struct {
282 index: usize,282 index: usize,
283 cmd_line: [*]const u8,283 cmd_line: [*]const u8,
284 in_quote: bool,
285 quote_count: usize,
286 seen_quote_count: usize,
287284
288 pub const NextError = error{OutOfMemory};285 pub const NextError = error{OutOfMemory};
289286
...@@ -295,9 +292,6 @@ pub const ArgIteratorWindows = struct {...@@ -295,9 +292,6 @@ pub const ArgIteratorWindows = struct {
295 return ArgIteratorWindows{292 return ArgIteratorWindows{
296 .index = 0,293 .index = 0,
297 .cmd_line = cmd_line,294 .cmd_line = cmd_line,
298 .in_quote = false,
299 .quote_count = countQuotes(cmd_line),
300 .seen_quote_count = 0,
301 };295 };
302 }296 }
303297
...@@ -328,6 +322,7 @@ pub const ArgIteratorWindows = struct {...@@ -328,6 +322,7 @@ pub const ArgIteratorWindows = struct {
328 }322 }
329323
330 var backslash_count: usize = 0;324 var backslash_count: usize = 0;
325 var in_quote = false;
331 while (true) : (self.index += 1) {326 while (true) : (self.index += 1) {
332 const byte = self.cmd_line[self.index];327 const byte = self.cmd_line[self.index];
333 switch (byte) {328 switch (byte) {
...@@ -335,14 +330,14 @@ pub const ArgIteratorWindows = struct {...@@ -335,14 +330,14 @@ pub const ArgIteratorWindows = struct {
335 '"' => {330 '"' => {
336 const quote_is_real = backslash_count % 2 == 0;331 const quote_is_real = backslash_count % 2 == 0;
337 if (quote_is_real) {332 if (quote_is_real) {
338 self.seen_quote_count += 1;333 in_quote = !in_quote;
339 }334 }
340 },335 },
341 '\\' => {336 '\\' => {
342 backslash_count += 1;337 backslash_count += 1;
343 },338 },
344 ' ', '\t' => {339 ' ', '\t' => {
345 if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) {340 if (!in_quote) {
346 return true;341 return true;
347 }342 }
348 backslash_count = 0;343 backslash_count = 0;
...@@ -360,6 +355,7 @@ pub const ArgIteratorWindows = struct {...@@ -360,6 +355,7 @@ pub const ArgIteratorWindows = struct {
360 defer buf.deinit();355 defer buf.deinit();
361356
362 var backslash_count: usize = 0;357 var backslash_count: usize = 0;
358 var in_quote = false;
363 while (true) : (self.index += 1) {359 while (true) : (self.index += 1) {
364 const byte = self.cmd_line[self.index];360 const byte = self.cmd_line[self.index];
365 switch (byte) {361 switch (byte) {
...@@ -370,10 +366,7 @@ pub const ArgIteratorWindows = struct {...@@ -370,10 +366,7 @@ pub const ArgIteratorWindows = struct {
370 backslash_count = 0;366 backslash_count = 0;
371367
372 if (quote_is_real) {368 if (quote_is_real) {
373 self.seen_quote_count += 1;369 in_quote = !in_quote;
374 if (self.seen_quote_count == self.quote_count and self.seen_quote_count % 2 == 1) {
375 try buf.append('"');
376 }
377 } else {370 } else {
378 try buf.append('"');371 try buf.append('"');
379 }372 }
...@@ -384,7 +377,7 @@ pub const ArgIteratorWindows = struct {...@@ -384,7 +377,7 @@ pub const ArgIteratorWindows = struct {
384 ' ', '\t' => {377 ' ', '\t' => {
385 try self.emitBackslashes(&buf, backslash_count);378 try self.emitBackslashes(&buf, backslash_count);
386 backslash_count = 0;379 backslash_count = 0;
387 if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) {380 if (in_quote) {
388 try buf.append(byte);381 try buf.append(byte);
389 } else {382 } else {
390 return buf.toOwnedSlice();383 return buf.toOwnedSlice();
...@@ -405,26 +398,6 @@ pub const ArgIteratorWindows = struct {...@@ -405,26 +398,6 @@ pub const ArgIteratorWindows = struct {
405 try buf.append('\\');398 try buf.append('\\');
406 }399 }
407 }400 }
408
409 fn countQuotes(cmd_line: [*]const u8) usize {
410 var result: usize = 0;
411 var backslash_count: usize = 0;
412 var index: usize = 0;
413 while (true) : (index += 1) {
414 const byte = cmd_line[index];
415 switch (byte) {
416 0 => return result,
417 '\\' => backslash_count += 1,
418 '"' => {
419 result += 1 - (backslash_count % 2);
420 backslash_count = 0;
421 },
422 else => {
423 backslash_count = 0;
424 },
425 }
426 }
427 }
428};401};
429402
430pub const ArgIterator = struct {403pub const ArgIterator = struct {
...@@ -578,7 +551,7 @@ test "windows arg parsing" {...@@ -578,7 +551,7 @@ test "windows arg parsing" {
578 testWindowsCmdLine("a\\\\\\b d\"e f\"g h", &[_][]const u8{ "a\\\\\\b", "de fg", "h" });551 testWindowsCmdLine("a\\\\\\b d\"e f\"g h", &[_][]const u8{ "a\\\\\\b", "de fg", "h" });
579 testWindowsCmdLine("a\\\\\\\"b c d", &[_][]const u8{ "a\\\"b", "c", "d" });552 testWindowsCmdLine("a\\\\\\\"b c d", &[_][]const u8{ "a\\\"b", "c", "d" });
580 testWindowsCmdLine("a\\\\\\\\\"b c\" d e", &[_][]const u8{ "a\\\\b c", "d", "e" });553 testWindowsCmdLine("a\\\\\\\\\"b c\" d e", &[_][]const u8{ "a\\\\b c", "d", "e" });
581 testWindowsCmdLine("a b\tc \"d f", &[_][]const u8{ "a", "b", "c", "\"d", "f" });554 testWindowsCmdLine("a b\tc \"d f", &[_][]const u8{ "a", "b", "c", "d f" });
582555
583 testWindowsCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", &[_][]const u8{556 testWindowsCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", &[_][]const u8{
584 ".\\..\\zig-cache\\build",557 ".\\..\\zig-cache\\build",