mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 08:43:58 +00:00
[OSS-fuzz] Fix FuzzMongoRead (#14807)
Co-authored-by: Marek Smoliński <marek@goteleport.com> Co-authored-by: Zac Bergquist <zac.bergquist@goteleport.com>
This commit is contained in:
parent
ecdb9dfff7
commit
925351e5be
|
@ -25,7 +25,72 @@ import (
|
|||
|
||||
func FuzzMongoRead(f *testing.F) {
|
||||
f.Add([]byte{})
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xdc\a\x00\x000000000\xca\x010000000"))
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xdd\a\x00\x000000\x01000\x8e0000000000000"))
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xdd\a\x00\x00000000000\x01\x02\x00\x00\x0000"))
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xdd\a\x00\x00000000000\x01\x01\x00\x00\x0000"))
|
||||
f.Add([]byte("0\x00\x00\x0000000000\x01\x00\x00\x0000000000000000000000\x03\x00\x00\x00\x00\x00\x00\x000000"))
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xd2\a\x00\x000000\x00\x00\x00\x00\x00\x00000000"))
|
||||
f.Add([]byte("000\xa4000000000000"))
|
||||
f.Add([]byte("0\x00\x00\x0000@00000\x01\x00\x00\x000000000000000000000\x01\x00\x00\x00\x0000000000"))
|
||||
f.Add([]byte(" \x00\x00\x0000000000\xdd\a\x00\x00000000000000\x01000"))
|
||||
f.Add([]byte{0x3f, 0x2d, 0x0, 0x0, 0x0, 0xf7, 0xfe, 0x0, 0xff, 0xff, 0xff, 0x29, 0xff, 0xdc, 0x7, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x71, 0x1, 0xff, 0xff, 0x2e, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb4,
|
||||
0x1a, 0x54, 0x6d, 0xff, 0xff, 0x0, 0xff, 0x53, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6, 0x36,
|
||||
0xd0, 0x4, 0x0, 0x84, 0x0, 0x0, 0x4, 0x29, 0x0})
|
||||
f.Add([]byte{0x1d, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x30, 0x13, 0x0, 0x0, 0xdc, 0x7, 0x0, 0x0, 0x30, 0x20,
|
||||
0x1d, 0x1d, 0x3, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x65, 0x0, 0xe2, 0xff, 0xff, 0xe2, 0x1d, 0x0, 0x0})
|
||||
f.Add([]byte{0x7e, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xd3, 0xc3, 0xd1, 0x26, 0x0, 0xfd, 0xa5, 0xdd, 0x7, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xa6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa5, 0xa5, 0xa5,
|
||||
0x7, 0x0, 0x0, 0xa5, 0xff, 0x9, 0x0, 0x0, 0xa5, 0xa5, 0x2a, 0xa5, 0xa5, 0x0, 0x0, 0x0, 0xa5, 0x10, 0xa5, 0xd3,
|
||||
0xc3, 0xd1, 0x26, 0x0, 0xfd, 0xa5})
|
||||
f.Add([]byte{0x42, 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x9, 0x0, 0x0, 0x0, 0x0, 0xdd, 0x7, 0x0, 0x0, 0x13, 0xa9,
|
||||
0x29, 0x13, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0x2,
|
||||
0xa, 0x16, 0x60, 0x56, 0x56, 0x56, 0xff, 0xa9, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0xa9, 0xa9, 0x0, 0xdc,
|
||||
0x7, 0x0, 0x0, 0xd4, 0x7, 0x0, 0x0, 0x11, 0x0, 0x92, 0x76, 0x76, 0xa9, 0x76, 0x76})
|
||||
f.Add([]byte{0x1c, 0x1a, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdd, 0x7, 0x0, 0x0, 0x12, 0x0, 0x0,
|
||||
0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x0, 0x80, 0xa, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0})
|
||||
f.Add([]byte{0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, 0x0, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0})
|
||||
f.Add([]byte{0x60, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x0, 0x0, 0xaa, 0xdc, 0x7, 0x0, 0x0, 0x0, 0x0,
|
||||
0x68, 0x0, 0x11, 0x1, 0x0, 0x3f, 0x1, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0xa4})
|
||||
f.Add([]byte{0x43, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30, 0x30, 0xd2, 0x7, 0x0, 0x0, 0x1, 0x10,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||
0x3c, 0x3c, 0x3c, 0xb})
|
||||
f.Add([]byte{0x47, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x1, 0x0, 0x0, 0x0, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x1, 0x0, 0x0, 0x4e, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x20, 0x32, 0x1, 0x1, 0xff, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff})
|
||||
f.Add([]byte{0x30, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xdd, 0x7, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xd6, 0x7, 0x0, 0x0, 0xfe, 0x1d, 0x0, 0x3a, 0x0, 0x0, 0x3a, 0x3a, 0x3a,
|
||||
0x31, 0x3a, 0x3a, 0x2a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x0, 0x7a, 0x0})
|
||||
f.Add([]byte{0x26, 0x24, 0x00, 0x00, 0x00, 0xdd, 0xff, 0xc7, 0xff, 0xff, 0xde, 0xff,
|
||||
0xf6, 0xdd, 0x07, 0x00, 0x00, 0x23, 0xad, 0x00, 0x39, 0x01, 0x00, 0x07,
|
||||
0xd7, 0x8e, 0x7e, 0xdf, 0x50, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x26,
|
||||
0x24, 0xe2, 0xff, 0xff, 0x06, 0xd6, 0xff, 0x77, 0x10, 0x00,
|
||||
})
|
||||
|
||||
f.Fuzz(func(t *testing.T, msgBytes []byte) {
|
||||
msg := bytes.NewReader(msgBytes)
|
||||
|
|
|
@ -114,6 +114,10 @@ func readOpCompressed(header MessageHeader, payload []byte) (message *MessageOpC
|
|||
CompressedMessage: compressedMessage,
|
||||
bytes: append(header.bytes[:], payload...),
|
||||
}
|
||||
if uncompressedSize <= 0 || len(compressedMessage) == 0 {
|
||||
return nil, trace.BadParameter("malformed OP_COMPRESSED: invalid message size %v", payload)
|
||||
}
|
||||
|
||||
message.originalMessage, err = decompress(message)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
|
@ -97,7 +97,7 @@ func readOpInsert(header MessageHeader, payload []byte) (*MessageOpInsert, error
|
|||
for len(rem) > 0 {
|
||||
var document bsoncore.Document
|
||||
document, rem, ok = bsoncore.ReadDocument(rem)
|
||||
if !ok {
|
||||
if !ok || len(document) == 0 {
|
||||
return nil, trace.BadParameter("malformed OP_INSERT: missing document %v", payload)
|
||||
}
|
||||
documents = append(documents, document)
|
||||
|
|
|
@ -251,6 +251,11 @@ func readOpMsg(header MessageHeader, payload []byte) (*MessageOpMsg, error) {
|
|||
case wiremessage.DocumentSequence:
|
||||
var id string
|
||||
var docs []bsoncore.Document
|
||||
|
||||
if err := validateDocumentSize(rem); err != nil {
|
||||
return nil, trace.BadParameter("malformed OP_MSG: %v %v", err, payload)
|
||||
}
|
||||
|
||||
id, docs, rem, ok = wiremessage.ReadMsgSectionDocumentSequence(rem)
|
||||
if !ok {
|
||||
return nil, trace.BadParameter("malformed OP_MSG: missing document sequence section %v", payload)
|
||||
|
@ -274,6 +279,23 @@ func readOpMsg(header MessageHeader, payload []byte) (*MessageOpMsg, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// validateDocumentSize validates document length encoded in the message.
|
||||
func validateDocumentSize(src []byte) error {
|
||||
const headerLen = 4
|
||||
if len(src) < headerLen {
|
||||
return trace.BadParameter("document is too short")
|
||||
}
|
||||
|
||||
// document length is encoded in the first 4 bytes
|
||||
documentLength := int(int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24)
|
||||
|
||||
// document payload cannot be shorter than the size of the whole message plus the header length.
|
||||
if documentLength+headerLen <= len(src) {
|
||||
return trace.BadParameter("invalid document length")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToWire converts this message to wire protocol message bytes.
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_msg
|
||||
|
|
|
@ -49,7 +49,7 @@ func MakeOpReply(document bsoncore.Document) *MessageOpReply {
|
|||
}
|
||||
}
|
||||
|
||||
// MakeOpReply is a shorthand to create OP_REPLY message from a single document
|
||||
// MakeOpReplyWithFlags is a shorthand to create OP_REPLY message from a single document
|
||||
// with provided flags.
|
||||
func MakeOpReplyWithFlags(document bsoncore.Document, flags wiremessage.ReplyFlag) *MessageOpReply {
|
||||
return &MessageOpReply{
|
||||
|
@ -123,7 +123,7 @@ func readOpReply(header MessageHeader, payload []byte) (*MessageOpReply, error)
|
|||
if !ok {
|
||||
return nil, trace.BadParameter("malformed OP_REPLY: missing number returned %v", payload)
|
||||
}
|
||||
documents, _, ok := wiremessage.ReadReplyDocuments(rem)
|
||||
documents, _, ok := ReadReplyDocuments(rem)
|
||||
if !ok {
|
||||
return nil, trace.BadParameter("malformed OP_REPLY: missing documents %v", payload)
|
||||
}
|
||||
|
@ -138,6 +138,26 @@ func readOpReply(header MessageHeader, payload []byte) (*MessageOpReply, error)
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ReadReplyDocuments reads multiple documents from the source.
|
||||
//
|
||||
// This function works in the same way as wiremessage.ReadReplyDocuments except, it can handle document of size 0.
|
||||
// When a document of size 0 is passed to wiremessage.ReadReplyDocuments, it will keep creating empty documents until
|
||||
// it uses all system memory/application crash.
|
||||
func ReadReplyDocuments(src []byte) (docs []bsoncore.Document, rem []byte, ok bool) {
|
||||
rem = src
|
||||
for {
|
||||
var doc bsoncore.Document
|
||||
doc, rem, ok = bsoncore.ReadDocument(rem)
|
||||
if !ok || len(doc) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
|
||||
return docs, rem, true
|
||||
}
|
||||
|
||||
// ToWire converts this message to wire protocol message bytes.
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_reply
|
||||
|
|
Loading…
Reference in a new issue