base: improve negative tests

This commit is contained in:
aler9
2021-04-24 11:46:48 +02:00
parent 49dfd34ede
commit e9518993d4
6 changed files with 109 additions and 16 deletions

View File

@@ -36,6 +36,7 @@ type Header map[string]HeaderValue
func (h *Header) read(rb *bufio.Reader) error { func (h *Header) read(rb *bufio.Reader) error {
*h = make(Header) *h = make(Header)
count := 0
for { for {
byt, err := rb.ReadByte() byt, err := rb.ReadByte()
@@ -52,15 +53,14 @@ func (h *Header) read(rb *bufio.Reader) error {
break break
} }
if len(*h) >= headerMaxEntryCount { if count >= headerMaxEntryCount {
return fmt.Errorf("headers count exceeds %d (it's %d)", return fmt.Errorf("headers count exceeds %d", headerMaxEntryCount)
headerMaxEntryCount, len(*h))
} }
key := string([]byte{byt}) key := string([]byte{byt})
byts, err := readBytesLimited(rb, ':', headerMaxKeyLength-1) byts, err := readBytesLimited(rb, ':', headerMaxKeyLength-1)
if err != nil { if err != nil {
return err return fmt.Errorf("value is missing")
} }
key += string(byts[:len(byts)-1]) key += string(byts[:len(byts)-1])
key = headerKeyNormalize(key) key = headerKeyNormalize(key)
@@ -85,16 +85,13 @@ func (h *Header) read(rb *bufio.Reader) error {
} }
val := string(byts[:len(byts)-1]) val := string(byts[:len(byts)-1])
if len(val) == 0 {
return fmt.Errorf("empty header value")
}
err = readByteEqual(rb, '\n') err = readByteEqual(rb, '\n')
if err != nil { if err != nil {
return err return err
} }
(*h)[key] = append((*h)[key], val) (*h)[key] = append((*h)[key], val)
count++
} }
return nil return nil

View File

@@ -42,6 +42,16 @@ var casesHeader = []struct {
}, },
}, },
}, },
{
"empty",
[]byte("Testing:\r\n" +
"\r\n"),
[]byte("Testing: \r\n" +
"\r\n"),
Header{
"Testing": HeaderValue{""},
},
},
{ {
"without space", "without space",
[]byte("CSeq:2\r\n" + []byte("CSeq:2\r\n" +
@@ -116,3 +126,50 @@ func TestHeaderWrite(t *testing.T) {
}) })
} }
} }
func TestHeaderReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
dec []byte
err string
}{
{
"empty",
[]byte{},
"EOF",
},
{
"r without n",
[]byte("Testing: val\rTesting: val\r\n"),
"expected '\n', got 'T'",
},
{
"final r without n",
[]byte("Testing: val\r\nTesting: val\r\n\r"),
"EOF",
},
{
"missing value",
[]byte("Testing\r\n"),
"value is missing",
},
{
"too many entries",
func() []byte {
var ret []byte
for i := 0; i < headerMaxEntryCount+2; i++ {
ret = append(ret, []byte("Testing: val\r\n")...)
}
ret = append(ret, []byte("\r\n")...)
return ret
}(),
"headers count exceeds 255",
},
} {
t.Run(ca.name, func(t *testing.T) {
h := make(Header)
err := h.read(bufio.NewReader(bytes.NewBuffer(ca.dec)))
require.Equal(t, ca.err, err.Error())
})
}
}

View File

@@ -71,7 +71,7 @@ func (req *Request) Read(rb *bufio.Reader) error {
ur, err := ParseURL(rawURL) ur, err := ParseURL(rawURL)
if err != nil { if err != nil {
return fmt.Errorf("unable to parse url (%v)", rawURL) return fmt.Errorf("invalid URL (%v)", rawURL)
} }
req.URL = ur req.URL = ur

View File

@@ -160,48 +160,73 @@ func TestRequestReadErrors(t *testing.T) {
for _, ca := range []struct { for _, ca := range []struct {
name string name string
byts []byte byts []byte
err string
}{ }{
{ {
"empty", "empty",
[]byte{}, []byte{},
"EOF",
}, },
{ {
"missing url, protocol, eol", "missing url, protocol, eol",
[]byte("GET"), []byte("GET"),
"EOF",
}, },
{ {
"missing protocol, eol", "missing protocol, eol",
[]byte("GET rtsp://testing123/test"), []byte("GET rtsp://testing123/test"),
"EOF",
}, },
{ {
"missing eol", "missing eol",
[]byte("GET rtsp://testing123/test RTSP/1.0"), []byte("GET rtsp://testing123/test RTSP/1.0"),
"EOF",
}, },
{ {
"empty method", "empty method",
[]byte(" rtsp://testing123 RTSP/1.0\r\n"), []byte(" rtsp://testing123 RTSP/1.0\r\n"),
"empty method",
}, },
{ {
"empty URL", "empty URL",
[]byte("GET RTSP/1.0\r\n"), []byte("GET RTSP/1.0\r\n"),
"invalid URL ()",
}, },
{ {
"empty protocol", "empty protocol",
[]byte("GET http://testing123 \r\n"), []byte("GET rtsp://testing123 \r\n"),
"expected 'RTSP/1.0', got ''",
}, },
{ {
"invalid URL", "invalid URL",
[]byte("GET http://testing123 RTSP/1.0\r\n"), []byte("GET http://testing123 RTSP/1.0\r\n"),
"invalid URL (http://testing123)",
}, },
{ {
"invalid protocol", "invalid protocol",
[]byte("GET rtsp://testing123 RTSP/2.0\r\n"), []byte("GET rtsp://testing123 RTSP/2.0\r\n"),
"expected 'RTSP/1.0', got 'RTSP/2.0'",
}, },
} { } {
t.Run(ca.name, func(t *testing.T) { t.Run(ca.name, func(t *testing.T) {
var req Request var req Request
err := req.Read(bufio.NewReader(bytes.NewBuffer(ca.byts))) err := req.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
require.Error(t, err) require.Equal(t, ca.err, err.Error())
}) })
} }
} }
func TestRequestReadIgnoreFrames(t *testing.T) {
byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4}
byts = append(byts, []byte("OPTIONS rtsp://example.com/media.mp4 RTSP/1.0\r\n"+
"CSeq: 1\r\n"+
"Proxy-Require: gzipped-messages\r\n"+
"Require: implicit-play\r\n"+
"\r\n")...)
rb := bufio.NewReader(bytes.NewBuffer(byts))
buf := make([]byte, 10)
var req Request
err := req.ReadIgnoreFrames(rb, buf)
require.NoError(t, err)
}

View File

@@ -164,7 +164,7 @@ func (res *Response) Read(rb *bufio.Reader) error {
res.StatusMessage = string(byts[:len(byts)-1]) res.StatusMessage = string(byts[:len(byts)-1])
if len(res.StatusMessage) == 0 { if len(res.StatusMessage) == 0 {
return fmt.Errorf("empty status") return fmt.Errorf("empty status message")
} }
err = readByteEqual(rb, '\n') err = readByteEqual(rb, '\n')

View File

@@ -122,44 +122,58 @@ func TestResponseReadErrors(t *testing.T) {
for _, ca := range []struct { for _, ca := range []struct {
name string name string
byts []byte byts []byte
err string
}{ }{
{ {
"empty", "empty",
[]byte{}, []byte{},
"EOF",
}, },
{ {
"missing code, message, eol", "missing code, message, eol",
[]byte("RTSP/1.0"), []byte("RTSP/1.0"),
"EOF",
}, },
{ {
"missing message, eol", "missing message, eol",
[]byte("RTSP/1.0 200"), []byte("RTSP/1.0 200"),
"EOF",
}, },
{ {
"missing eol", "missing eol",
[]byte("RTSP/1.0 200 OK"), []byte("RTSP/1.0 200 OK"),
"EOF",
}, },
{ {
"missing eol 2", "missing eol 2",
[]byte("RTSP/1.0 200 OK\r"), []byte("RTSP/1.0 200 OK\r"),
"EOF",
}, },
{ {
"invalid protocol", "invalid protocol",
[]byte("RTSP/2.0 200 OK\r\n"), []byte("RTSP/2.0 200 OK\r\n"),
"expected 'RTSP/1.0', got 'RTSP/2.0'",
},
{
"code too long",
[]byte("RTSP/1.0 1234 OK\r\n"),
"buffer length exceeds 4",
}, },
{ {
"invalid code", "invalid code",
[]byte("RTSP/2.0 string OK\r\n"), []byte("RTSP/1.0 str OK\r\n"),
"unable to parse status code",
}, },
{ {
"empty message", "empty message",
[]byte("RTSP/2.0 string \r\n"), []byte("RTSP/1.0 200 \r\n"),
"empty status message",
}, },
} { } {
t.Run(ca.name, func(t *testing.T) { t.Run(ca.name, func(t *testing.T) {
var res Response var res Response
err := res.Read(bufio.NewReader(bytes.NewBuffer(ca.byts))) err := res.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
require.Error(t, err) require.Equal(t, ca.err, err.Error())
}) })
} }
} }
@@ -193,7 +207,7 @@ func TestResponseWriteAutoFillStatus(t *testing.T) {
require.Equal(t, byts, buf.Bytes()) require.Equal(t, byts, buf.Bytes())
} }
func TestReadIgnoreFrames(t *testing.T) { func TestResponseReadIgnoreFrames(t *testing.T) {
byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4} byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4}
byts = append(byts, []byte("RTSP/1.0 200 OK\r\n"+ byts = append(byts, []byte("RTSP/1.0 200 OK\r\n"+
"CSeq: 1\r\n"+ "CSeq: 1\r\n"+