Browse code

Merge pull request #22943 from vdemeester/21769-fix-detach-keys

Fix escape-keys by preserving input if invalid

David Calavera authored on 2016/05/26 01:53:53
Showing 2 changed files
... ...
@@ -484,7 +484,9 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
484 484
 		nr, er := src.Read(buf)
485 485
 		if nr > 0 {
486 486
 			// ---- Docker addition
487
+			preservBuf := []byte{}
487 488
 			for i, key := range keys {
489
+				preservBuf = append(preservBuf, buf[0:nr]...)
488 490
 				if nr != 1 || buf[0] != key {
489 491
 					break
490 492
 				}
... ...
@@ -496,8 +498,15 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
496 496
 				}
497 497
 				nr, er = src.Read(buf)
498 498
 			}
499
-			// ---- End of docker
500
-			nw, ew := dst.Write(buf[0:nr])
499
+			var nw int
500
+			var ew error
501
+			if len(preservBuf) > 0 {
502
+				nw, ew = dst.Write(preservBuf)
503
+				nr = len(preservBuf)
504
+			} else {
505
+				// ---- End of docker
506
+				nw, ew = dst.Write(buf[0:nr])
507
+			}
501 508
 			if nw > 0 {
502 509
 				written += int64(nw)
503 510
 			}
... ...
@@ -396,6 +396,55 @@ func (s *DockerSuite) TestRunAttachDetachKeysOverrideConfig(c *check.C) {
396 396
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
397 397
 }
398 398
 
399
+func (s *DockerSuite) TestRunAttachInvalidDetachKeySequencePreserved(c *check.C) {
400
+	name := "attach-detach"
401
+	keyA := []byte{97}
402
+	keyB := []byte{98}
403
+
404
+	dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat")
405
+
406
+	cmd := exec.Command(dockerBinary, "attach", "--detach-keys='a,b,c'", name)
407
+	stdout, err := cmd.StdoutPipe()
408
+	if err != nil {
409
+		c.Fatal(err)
410
+	}
411
+	cpty, tty, err := pty.Open()
412
+	if err != nil {
413
+		c.Fatal(err)
414
+	}
415
+	defer cpty.Close()
416
+	cmd.Stdin = tty
417
+	if err := cmd.Start(); err != nil {
418
+		c.Fatal(err)
419
+	}
420
+	c.Assert(waitRun(name), check.IsNil)
421
+
422
+	// Invalid escape sequence aba, should print aba in output
423
+	if _, err := cpty.Write(keyA); err != nil {
424
+		c.Fatal(err)
425
+	}
426
+	time.Sleep(100 * time.Millisecond)
427
+	if _, err := cpty.Write(keyB); err != nil {
428
+		c.Fatal(err)
429
+	}
430
+	time.Sleep(100 * time.Millisecond)
431
+	if _, err := cpty.Write(keyA); err != nil {
432
+		c.Fatal(err)
433
+	}
434
+	time.Sleep(100 * time.Millisecond)
435
+	if _, err := cpty.Write([]byte("\n")); err != nil {
436
+		c.Fatal(err)
437
+	}
438
+
439
+	out, err := bufio.NewReader(stdout).ReadString('\n')
440
+	if err != nil {
441
+		c.Fatal(err)
442
+	}
443
+	if strings.TrimSpace(out) != "aba" {
444
+		c.Fatalf("expected 'aba', got %q", out)
445
+	}
446
+}
447
+
399 448
 // "test" should be printed
400 449
 func (s *DockerSuite) TestRunWithCPUQuota(c *check.C) {
401 450
 	testRequires(c, cpuCfsQuota)