From 0fb6190243d6101f96283e487cd4911142a05483 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Tue, 24 May 2016 17:14:48 +0200 Subject: [PATCH] Fix escape-keys by preserving input if invalid Currently, using a custom detach key with an invalid sequence, eats a part of the sequence, making it weird and difficult to enter some key sequence. This fixes by keeping the input read when trying to see if it's the key sequence or not, and "writing" then is the key sequence is not the right one, preserving the initial input. Signed-off-by: Vincent Demeester --- container/container.go | 13 +++++- integration-cli/docker_cli_run_unix_test.go | 49 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/container/container.go b/container/container.go index 42fdfd0a1b..6547a4ea0b 100644 --- a/container/container.go +++ b/container/container.go @@ -484,7 +484,9 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64 nr, er := src.Read(buf) if nr > 0 { // ---- Docker addition + preservBuf := []byte{} for i, key := range keys { + preservBuf = append(preservBuf, buf[0:nr]...) if nr != 1 || buf[0] != key { break } @@ -496,8 +498,15 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64 } nr, er = src.Read(buf) } - // ---- End of docker - nw, ew := dst.Write(buf[0:nr]) + var nw int + var ew error + if len(preservBuf) > 0 { + nw, ew = dst.Write(preservBuf) + nr = len(preservBuf) + } else { + // ---- End of docker + nw, ew = dst.Write(buf[0:nr]) + } if nw > 0 { written += int64(nw) } diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 4872c2b909..9e03e3aa98 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -396,6 +396,55 @@ func (s *DockerSuite) TestRunAttachDetachKeysOverrideConfig(c *check.C) { c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running")) } +func (s *DockerSuite) TestRunAttachInvalidDetachKeySequencePreserved(c *check.C) { + name := "attach-detach" + keyA := []byte{97} + keyB := []byte{98} + + dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") + + cmd := exec.Command(dockerBinary, "attach", "--detach-keys='a,b,c'", name) + stdout, err := cmd.StdoutPipe() + if err != nil { + c.Fatal(err) + } + cpty, tty, err := pty.Open() + if err != nil { + c.Fatal(err) + } + defer cpty.Close() + cmd.Stdin = tty + if err := cmd.Start(); err != nil { + c.Fatal(err) + } + c.Assert(waitRun(name), check.IsNil) + + // Invalid escape sequence aba, should print aba in output + if _, err := cpty.Write(keyA); err != nil { + c.Fatal(err) + } + time.Sleep(100 * time.Millisecond) + if _, err := cpty.Write(keyB); err != nil { + c.Fatal(err) + } + time.Sleep(100 * time.Millisecond) + if _, err := cpty.Write(keyA); err != nil { + c.Fatal(err) + } + time.Sleep(100 * time.Millisecond) + if _, err := cpty.Write([]byte("\n")); err != nil { + c.Fatal(err) + } + + out, err := bufio.NewReader(stdout).ReadString('\n') + if err != nil { + c.Fatal(err) + } + if strings.TrimSpace(out) != "aba" { + c.Fatalf("expected 'aba', got %q", out) + } +} + // "test" should be printed func (s *DockerSuite) TestRunWithCPUQuota(c *check.C) { testRequires(c, cpuCfsQuota)