github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/cmd/dockerd/hack/malformed_host_override_test.go (about)

     1  // +build !windows
     2  
     3  package hack
     4  
     5  import (
     6  	"bytes"
     7  	"io"
     8  	"net"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  type bufConn struct {
    14  	net.Conn
    15  	buf *bytes.Buffer
    16  }
    17  
    18  func (bc *bufConn) Read(b []byte) (int, error) {
    19  	return bc.buf.Read(b)
    20  }
    21  
    22  func TestHeaderOverrideHack(t *testing.T) {
    23  	tests := [][2][]byte{
    24  		{
    25  			[]byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\r\n\r\n"),
    26  			[]byte("GET /foo\nHost: \r\nConnection: close\r\nUser-Agent: Docker\r\n\r\n"),
    27  		},
    28  		{
    29  			[]byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\nFoo: Bar\r\n"),
    30  			[]byte("GET /foo\nHost: \r\nConnection: close\r\nUser-Agent: Docker\nFoo: Bar\r\n"),
    31  		},
    32  		{
    33  			[]byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\r\n\r\ntest something!"),
    34  			[]byte("GET /foo\nHost: \r\nConnection: close\r\nUser-Agent: Docker\r\n\r\ntest something!"),
    35  		},
    36  		{
    37  			[]byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\r\n\r\ntest something! " + strings.Repeat("test", 15000)),
    38  			[]byte("GET /foo\nHost: \r\nConnection: close\r\nUser-Agent: Docker\r\n\r\ntest something! " + strings.Repeat("test", 15000)),
    39  		},
    40  		{
    41  			[]byte("GET /foo\nFoo: Bar\nHost: /var/run/docker.sock\nUser-Agent: Docker\r\n\r\n"),
    42  			[]byte("GET /foo\nFoo: Bar\nHost: /var/run/docker.sock\nUser-Agent: Docker\r\n\r\n"),
    43  		},
    44  	}
    45  
    46  	// Test for https://github.com/docker/docker/issues/23045
    47  	h0 := "GET /foo\nUser-Agent: Docker\r\n\r\n"
    48  	h0 = h0 + strings.Repeat("a", 4096-len(h0)-1) + "\n"
    49  	tests = append(tests, [2][]byte{[]byte(h0), []byte(h0)})
    50  
    51  	for _, pair := range tests {
    52  		read := make([]byte, 4096)
    53  		client := &bufConn{
    54  			buf: bytes.NewBuffer(pair[0]),
    55  		}
    56  		l := MalformedHostHeaderOverrideConn{client, true}
    57  
    58  		n, err := l.Read(read)
    59  		if err != nil && err != io.EOF {
    60  			t.Fatalf("read: %d - %d, err: %v\n%s", n, len(pair[0]), err, string(read[:n]))
    61  		}
    62  		if !bytes.Equal(read[:n], pair[1][:n]) {
    63  			t.Fatalf("\n%s\n%s\n", read[:n], pair[1][:n])
    64  		}
    65  	}
    66  }
    67  
    68  func BenchmarkWithHack(b *testing.B) {
    69  	client, srv := net.Pipe()
    70  	done := make(chan struct{})
    71  	req := []byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\n")
    72  	read := make([]byte, 4096)
    73  	b.SetBytes(int64(len(req) * 30))
    74  
    75  	l := MalformedHostHeaderOverrideConn{client, true}
    76  	go func() {
    77  		for {
    78  			if _, err := srv.Write(req); err != nil {
    79  				srv.Close()
    80  				break
    81  			}
    82  			l.first = true // make sure each subsequent run uses the hack parsing
    83  		}
    84  		close(done)
    85  	}()
    86  
    87  	for i := 0; i < b.N; i++ {
    88  		for i := 0; i < 30; i++ {
    89  			if n, err := l.Read(read); err != nil && err != io.EOF {
    90  				b.Fatalf("read: %d - %d, err: %v\n%s", n, len(req), err, string(read[:n]))
    91  			}
    92  		}
    93  	}
    94  	l.Close()
    95  	<-done
    96  }
    97  
    98  func BenchmarkNoHack(b *testing.B) {
    99  	client, srv := net.Pipe()
   100  	done := make(chan struct{})
   101  	req := []byte("GET /foo\nHost: /var/run/docker.sock\nUser-Agent: Docker\n")
   102  	read := make([]byte, 4096)
   103  	b.SetBytes(int64(len(req) * 30))
   104  
   105  	go func() {
   106  		for {
   107  			if _, err := srv.Write(req); err != nil {
   108  				srv.Close()
   109  				break
   110  			}
   111  		}
   112  		close(done)
   113  	}()
   114  
   115  	for i := 0; i < b.N; i++ {
   116  		for i := 0; i < 30; i++ {
   117  			if _, err := client.Read(read); err != nil && err != io.EOF {
   118  				b.Fatal(err)
   119  			}
   120  		}
   121  	}
   122  	client.Close()
   123  	<-done
   124  }