diff options
Diffstat (limited to 'hotline')
| -rw-r--r-- | hotline/field.go | 14 | ||||
| -rw-r--r-- | hotline/field_test.go | 16 |
2 files changed, 28 insertions, 2 deletions
diff --git a/hotline/field.go b/hotline/field.go index 554f63d..99d0d35 100644 --- a/hotline/field.go +++ b/hotline/field.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "slices" ) @@ -137,19 +138,28 @@ func (f *Field) DecodeNewsPath() ([]string, error) { if len(f.Data) == 0 { return []string{}, nil } + if len(f.Data) < 2 { + return nil, fmt.Errorf("news path too short: %d bytes", len(f.Data)) + } pathCount := binary.BigEndian.Uint16(f.Data[0:2]) scanner := bufio.NewScanner(bytes.NewReader(f.Data[2:])) scanner.Split(newsPathScanner) - var paths []string + paths := make([]string, 0, pathCount) for i := uint16(0); i < pathCount; i++ { - scanner.Scan() + if !scanner.Scan() { + return nil, fmt.Errorf("news path truncated: declared %d items, found %d", pathCount, i) + } paths = append(paths, scanner.Text()) } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("scan news path: %w", err) + } + return paths, nil } diff --git a/hotline/field_test.go b/hotline/field_test.go index 6dff102..b8d909b 100644 --- a/hotline/field_test.go +++ b/hotline/field_test.go @@ -248,6 +248,22 @@ func TestField_DecodeNewsPath(t *testing.T) { wantErr: assert.NoError, }, { + name: "one byte of data returns an error instead of panicking", + fields: fields{Data: []byte{0x00}}, + want: nil, + wantErr: assert.Error, + }, + { + name: "declared path count exceeding available items returns an error", + fields: fields{Data: []byte{ + 0x00, 0x02, // path count = 2 + 0x00, 0x00, 0x05, // 2 bytes unused + 1 byte length (5) + 0x48, 0x65, 0x6c, 0x6c, 0x6f, // "Hello" (only 1 item present) + }}, + want: nil, + wantErr: assert.Error, + }, + { name: "single path", fields: fields{Data: []byte{ 0x00, 0x01, // path count = 1 |