Skip to content

Commit

Permalink
Avoid deadlock when opening stream repeatedly
Browse files Browse the repository at this point in the history
  • Loading branch information
mohanson authored Sep 12, 2023
1 parent b2a9936 commit 86c7b72
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
6 changes: 4 additions & 2 deletions protocol/czar/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ func (m *Mux) Spawn() {
switch cmd {
case 0x00:
// Make sure the stream has been closed properly.
<-m.usb[idx].rdn
<-m.usb[idx].wdn
old := m.usb[idx]
old.ron.Do(func() { close(old.rdn) })
old.won.Do(func() { close(old.wdn) })
old.son.Do(func() { old.idp <- old.idx })
stm := NewStream(idx, m)
// The mux server does not need to using an id pool.
stm.idp = make(chan uint8, 1)
Expand Down
24 changes: 24 additions & 0 deletions protocol/czar/mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"log"
"net"
"slices"
"strings"
"testing"

Expand Down Expand Up @@ -77,6 +78,29 @@ func TestProtocolMuxClientClose(t *testing.T) {
doa.Doa(strings.Contains(er2.Error(), "use of closed network connection"))
}

func TestProtocolMuxServerRecvEvilPacket(t *testing.T) {
remote := Tester{daze.NewTester(EchoServerListenOn)}
remote.Mux()
defer remote.Close()

buf := make([]byte, 2048)

cl0 := doa.Try(net.Dial("tcp", EchoServerListenOn))
defer cl0.Close()
cl0.Write([]byte{0x00, 0x01, 0xff, 0xf0})
_, er0 := io.ReadFull(cl0, buf[:1])
doa.Doa(er0 == io.EOF)

cl1 := doa.Try(net.Dial("tcp", EchoServerListenOn))
defer cl1.Close()
cl1.Write([]byte{0x00, 0x00, 0x00, 0x00})
cl1.Write([]byte{0x00, 0x00, 0x00, 0x00})
cl1.Write([]byte{0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04})
_, er1 := io.ReadFull(cl1, buf[:12])
doa.Nil(er1)
doa.Doa(slices.Equal(buf[:8], []byte{0x00, 0x01, 0x00, 0x08, 0x01, 0x00, 0x00, 0x04}))
}

type Tester struct {
*daze.Tester
}
Expand Down

0 comments on commit 86c7b72

Please sign in to comment.