Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions internal/inputhandlers/term_iac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package inputhandlers
import (
"testing"

"github.com/GoMudEngine/GoMud/internal/connections"
"github.com/GoMudEngine/GoMud/internal/term"
"github.com/stretchr/testify/assert"
)

// newEnvironPayload builds the bytes that appear between `IAC SB NEW-ENVIRON IS`
Expand Down Expand Up @@ -90,3 +92,17 @@ func TestNewEnvironResponseMatcher(t *testing.T) {
t.Errorf("expected extracted payload to be detected as Mudlet, payload=%v", payload)
}
}

// TestTelnetIACHandlerShortScreenSizeReport sends a NAWS report cut short after
// three bytes. It used to index past the payload and panic on the connection
// goroutine, which has no recover, so the whole server exited.
func TestTelnetIACHandlerShortScreenSizeReport(t *testing.T) {
clientInput := &connections.ClientInput{
ConnectionId: 1,
DataIn: []byte{term.TELNET_IAC, term.TELNET_SB, term.TELNET_OPT_NAWS, 0, 80, 0},
}

assert.NotPanics(t, func() {
TelnetIACHandler(clientInput, map[string]any{})
})
}
4 changes: 3 additions & 1 deletion internal/term/telnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ func TelnetDONT(what IACByte) []IACByte {

func TelnetParseScreenSizePayload(info []byte) (width int, height int, err error) {

if len(info) >= 3 {
// Width and height are two bytes each, so a report shorter than four
// bytes cannot be read. Any client can send one.
if len(info) >= 4 {

width = (int(info[0]) << 8) | int(info[1])
height = (int(info[2]) << 8) | int(info[3])
Expand Down
43 changes: 43 additions & 0 deletions internal/term/telnet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package term

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// A NAWS report is four bytes: width then height, each high byte first. A
// client can send fewer, and that must come back as an error rather than a
// read past the end of the payload.
func TestTelnetParseScreenSizePayload(t *testing.T) {
tests := []struct {
name string
payload []byte
wantWidth int
wantHeight int
wantErr bool
}{
{name: "80x24", payload: []byte{0, 80, 0, 24}, wantWidth: 80, wantHeight: 24},
{name: "high bytes", payload: []byte{1, 0, 0, 50}, wantWidth: 256, wantHeight: 50},
{name: "trailing IAC SE", payload: []byte{0, 120, 0, 40, TELNET_IAC, TELNET_SE}, wantWidth: 120, wantHeight: 40},
{name: "three bytes", payload: []byte{0, 80, 0}, wantErr: true},
{name: "two bytes", payload: []byte{0, 80}, wantErr: true},
{name: "empty", payload: []byte{}, wantErr: true},
{name: "nil", payload: nil, wantErr: true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
width, height, err := TelnetParseScreenSizePayload(tt.payload)
if tt.wantErr {
assert.Error(t, err)
return
}

require.NoError(t, err)
assert.Equal(t, tt.wantWidth, width)
assert.Equal(t, tt.wantHeight, height)
})
}
}