diff --git a/fix_int.go b/fix_int.go index 6bd968003..a7bd62ca8 100644 --- a/fix_int.go +++ b/fix_int.go @@ -31,6 +31,10 @@ const ( // atoi is similar to the function in strconv, but is tuned for ints appearing in FIX field types. func atoi(d []byte) (int, error) { + if len(d) == 0 { + return 0, errors.New("empty bytes") + } + if d[0] == asciiMinus { n, err := parseUInt(d[1:]) return (-1) * n, err diff --git a/fix_int_test.go b/fix_int_test.go index caa9b7840..ee363fe6c 100644 --- a/fix_int_test.go +++ b/fix_int_test.go @@ -35,6 +35,9 @@ func TestFIXInt_Read(t *testing.T) { err = field.Read([]byte("blah")) assert.NotNil(t, err, "Unexpected error") + + err = field.Read([]byte("")) + assert.NotNil(t, err, "Unexpected error") } func TestFIXInt_Int(t *testing.T) { diff --git a/message.go b/message.go index 69407cf5d..02ca2ad66 100644 --- a/message.go +++ b/message.go @@ -553,6 +553,12 @@ func extractXMLDataField(parsedFieldBytes *TagValue, buffer []byte, dataLen int) remBytes = buffer return } + // Compared against the remaining buffer so a large dataLen cannot overflow int. + if dataLen < 0 || dataLen > len(buffer)-endIndex-2 { + err = parseError{OrigError: fmt.Sprintf("extractXMLDataField: XMLDataLen %d exceeds remaining buffer of %d bytes", dataLen, len(buffer)-endIndex-2)} + remBytes = buffer + return + } endIndex += dataLen + 1 err = parsedFieldBytes.parse(buffer[:endIndex+1]) diff --git a/message_test.go b/message_test.go index a51c5231e..e096f1da2 100644 --- a/message_test.go +++ b/message_test.go @@ -64,6 +64,38 @@ func (s *MessageSuite) TestParseMessageEmpty() { s.NotNil(err) } +func (s *MessageSuite) TestParseMessageXMLDataLenOutOfRange() { + var tests = []struct { + name string + rawMsg string + }{ + {"overrun", "8=FIX.4.29=2035=n34=249=CME56=OAEAAAN212=999999999213=10=000"}, + {"int overflow", "8=FIX.4.29=2035=n34=249=CME56=OAEAAAN212=9223372036854775807213=10=000"}, + } + + for _, test := range tests { + s.Run(test.name, func() { + s.NotNil(ParseMessage(NewMessage(), bytes.NewBufferString(test.rawMsg))) + }) + } +} + +func (s *MessageSuite) TestParseMessageEmptyIntField() { + var tests = []struct { + name string + rawMsg string + }{ + {"body length", "8=FIX.4.29=35=D34=249=TW56=ISLD10=000"}, + {"xml data len", "8=FIX.4.29=2035=n34=249=CME56=OAEAAAN212=213=10=000"}, + } + + for _, test := range tests { + s.Run(test.name, func() { + s.NotNil(ParseMessage(NewMessage(), bytes.NewBufferString(test.rawMsg))) + }) + } +} + func (s *MessageSuite) TestParseMessage() { rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039")