@@ -16,9 +16,11 @@ package wiremessage
1616import (
1717 "bytes"
1818 "encoding/binary"
19+ "math"
1920 "strings"
2021 "sync/atomic"
2122
23+ "go.mongodb.org/mongo-driver/v2/internal/binaryutil"
2224 "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore"
2325)
2426
@@ -219,18 +221,18 @@ const (
219221// starts in dst and the updated slice.
220222func AppendHeaderStart (dst []byte , reqid , respto int32 , opcode OpCode ) (index int32 , b []byte ) {
221223 index , dst = bsoncore .ReserveLength (dst )
222- dst = appendi32 (dst , reqid )
223- dst = appendi32 (dst , respto )
224- dst = appendi32 (dst , int32 (opcode ))
224+ dst = binaryutil . AppendI32 (dst , reqid )
225+ dst = binaryutil . AppendI32 (dst , respto )
226+ dst = binaryutil . AppendI32 (dst , int32 (opcode ))
225227 return index , dst
226228}
227229
228230// AppendHeader appends a header to dst.
229231func AppendHeader (dst []byte , length , reqid , respto int32 , opcode OpCode ) []byte {
230- dst = appendi32 (dst , length )
231- dst = appendi32 (dst , reqid )
232- dst = appendi32 (dst , respto )
233- dst = appendi32 (dst , int32 (opcode ))
232+ dst = binaryutil . AppendI32 (dst , length )
233+ dst = binaryutil . AppendI32 (dst , reqid )
234+ dst = binaryutil . AppendI32 (dst , respto )
235+ dst = binaryutil . AppendI32 (dst , int32 (opcode ))
234236 return dst
235237}
236238
@@ -240,26 +242,31 @@ func ReadHeader(src []byte) (length, requestID, responseTo int32, opcode OpCode,
240242 return 0 , 0 , 0 , 0 , src , false
241243 }
242244
243- length = readi32unsafe (src )
244- requestID = readi32unsafe (src [4 :])
245- responseTo = readi32unsafe (src [8 :])
246- opcode = OpCode (readi32unsafe (src [12 :]))
245+ length = binaryutil . ReadI32Unsafe (src )
246+ requestID = binaryutil . ReadI32Unsafe (src [4 :])
247+ responseTo = binaryutil . ReadI32Unsafe (src [8 :])
248+ opcode = OpCode (binaryutil . ReadI32Unsafe (src [12 :]))
247249 return length , requestID , responseTo , opcode , src [16 :], true
248250}
249251
250252// AppendQueryFlags appends the flags for an OP_QUERY wire message.
251253func AppendQueryFlags (dst []byte , flags QueryFlag ) []byte {
252- return appendi32 (dst , int32 (flags ))
254+ return binaryutil . AppendI32 (dst , int32 (flags ))
253255}
254256
255257// AppendMsgFlags appends the flags for an OP_MSG wire message.
256258func AppendMsgFlags (dst []byte , flags MsgFlag ) []byte {
257- return appendi32 (dst , int32 (flags ))
259+ if flags > MsgFlag (math .MaxInt32 ) {
260+ panic ("AppendMsgFlags: flag value exceeds int32 range" )
261+ }
262+
263+ // nolint:gosec // G602: key length is validated at function entry
264+ return binaryutil .AppendI32 (dst , int32 (flags ))
258265}
259266
260267// AppendReplyFlags appends the flags for an OP_REPLY wire message.
261268func AppendReplyFlags (dst []byte , flags ReplyFlag ) []byte {
262- return appendi32 (dst , int32 (flags ))
269+ return binaryutil . AppendI32 (dst , int32 (flags ))
263270}
264271
265272// AppendMsgSectionType appends the section type to dst.
@@ -274,37 +281,39 @@ func AppendQueryFullCollectionName(dst []byte, ns string) []byte {
274281
275282// AppendQueryNumberToSkip appends the number to skip to dst.
276283func AppendQueryNumberToSkip (dst []byte , skip int32 ) []byte {
277- return appendi32 (dst , skip )
284+ return binaryutil . AppendI32 (dst , skip )
278285}
279286
280287// AppendQueryNumberToReturn appends the number to return to dst.
281288func AppendQueryNumberToReturn (dst []byte , nor int32 ) []byte {
282- return appendi32 (dst , nor )
289+ return binaryutil . AppendI32 (dst , nor )
283290}
284291
285292// AppendReplyCursorID appends the cursor ID to dst.
286293func AppendReplyCursorID (dst []byte , id int64 ) []byte {
287- return appendi64 (dst , id )
294+ return binaryutil . AppendI64 (dst , id )
288295}
289296
290297// AppendReplyStartingFrom appends the starting from field to dst.
291298func AppendReplyStartingFrom (dst []byte , sf int32 ) []byte {
292- return appendi32 (dst , sf )
299+ return binaryutil . AppendI32 (dst , sf )
293300}
294301
295302// AppendReplyNumberReturned appends the number returned to dst.
296303func AppendReplyNumberReturned (dst []byte , nr int32 ) []byte {
297- return appendi32 (dst , nr )
304+ return binaryutil . AppendI32 (dst , nr )
298305}
299306
300307// AppendCompressedOriginalOpCode appends the original opcode to dst.
301308func AppendCompressedOriginalOpCode (dst []byte , opcode OpCode ) []byte {
302- return appendi32 (dst , int32 (opcode ))
309+ return binaryutil . AppendI32 (dst , int32 (opcode ))
303310}
304311
305312// AppendCompressedUncompressedSize appends the uncompressed size of a
306313// compressed wiremessage to dst.
307- func AppendCompressedUncompressedSize (dst []byte , size int32 ) []byte { return appendi32 (dst , size ) }
314+ func AppendCompressedUncompressedSize (dst []byte , size int32 ) []byte {
315+ return binaryutil .AppendI32 (dst , size )
316+ }
308317
309318// AppendCompressedCompressorID appends the ID of the compressor to dst.
310319func AppendCompressedCompressorID (dst []byte , id CompressorID ) []byte {
@@ -316,7 +325,7 @@ func AppendCompressedCompressedMessage(dst []byte, msg []byte) []byte { return a
316325
317326// AppendGetMoreZero appends the zero field to dst.
318327func AppendGetMoreZero (dst []byte ) []byte {
319- return appendi32 (dst , 0 )
328+ return binaryutil . AppendI32 (dst , 0 )
320329}
321330
322331// AppendGetMoreFullCollectionName appends the fullCollectionName field to dst.
@@ -326,43 +335,50 @@ func AppendGetMoreFullCollectionName(dst []byte, ns string) []byte {
326335
327336// AppendGetMoreNumberToReturn appends the numberToReturn field to dst.
328337func AppendGetMoreNumberToReturn (dst []byte , numToReturn int32 ) []byte {
329- return appendi32 (dst , numToReturn )
338+ return binaryutil . AppendI32 (dst , numToReturn )
330339}
331340
332341// AppendGetMoreCursorID appends the cursorID field to dst.
333342func AppendGetMoreCursorID (dst []byte , cursorID int64 ) []byte {
334- return appendi64 (dst , cursorID )
343+ return binaryutil . AppendI64 (dst , cursorID )
335344}
336345
337346// AppendKillCursorsZero appends the zero field to dst.
338347func AppendKillCursorsZero (dst []byte ) []byte {
339- return appendi32 (dst , 0 )
348+ return binaryutil . AppendI32 (dst , 0 )
340349}
341350
342351// AppendKillCursorsNumberIDs appends the numberOfCursorIDs field to dst.
343352func AppendKillCursorsNumberIDs (dst []byte , numIDs int32 ) []byte {
344- return appendi32 (dst , numIDs )
353+ return binaryutil . AppendI32 (dst , numIDs )
345354}
346355
347356// AppendKillCursorsCursorIDs appends each the cursorIDs field to dst.
348357func AppendKillCursorsCursorIDs (dst []byte , cursors []int64 ) []byte {
349358 for _ , cursor := range cursors {
350- dst = appendi64 (dst , cursor )
359+ dst = binaryutil . AppendI64 (dst , cursor )
351360 }
352361 return dst
353362}
354363
355364// ReadMsgFlags reads the OP_MSG flags from src.
356365func ReadMsgFlags (src []byte ) (flags MsgFlag , rem []byte , ok bool ) {
357- i32 , rem , ok := readi32 (src )
366+ i32 , rem , ok := binaryutil .ReadI32 (src )
367+ if i32 < 0 {
368+ return 0 , rem , false
369+ }
370+
358371 return MsgFlag (i32 ), rem , ok
359372}
360373
361374// IsMsgMoreToCome returns if the provided wire message is an OP_MSG with the more to come flag set.
362375func IsMsgMoreToCome (wm []byte ) bool {
363376 return len (wm ) >= 20 &&
364- OpCode (readi32unsafe (wm [12 :16 ])) == OpMsg &&
365- MsgFlag (readi32unsafe (wm [16 :20 ]))& MoreToCome == MoreToCome
377+ OpCode (binaryutil .ReadI32Unsafe (wm [12 :16 ])) == OpMsg &&
378+ func () bool {
379+ flagValue := binaryutil .ReadI32Unsafe (wm [16 :20 ])
380+ return flagValue >= 0 && MsgFlag (flagValue )& MoreToCome == MoreToCome
381+ }()
366382}
367383
368384// ReadMsgSectionType reads the section type from src.
@@ -405,7 +421,7 @@ func ReadMsgSectionDocumentSequence(src []byte) (identifier string, docs []bsonc
405421// ReadMsgSectionRawDocumentSequence reads an identifier and document sequence from src and returns the raw document
406422// sequence data.
407423func ReadMsgSectionRawDocumentSequence (src []byte ) (identifier string , data []byte , rem []byte , ok bool ) {
408- length , rem , ok := readi32 (src )
424+ length , rem , ok := binaryutil . ReadI32 (src )
409425 if ! ok || int (length ) > len (src ) || length < 4 {
410426 return "" , nil , src , false
411427 }
@@ -423,17 +439,16 @@ func ReadMsgSectionRawDocumentSequence(src []byte) (identifier string, data []by
423439}
424440
425441// ReadMsgChecksum reads a checksum from src.
426- func ReadMsgChecksum (src []byte ) (checksum uint32 , rem []byte , ok bool ) {
427- i32 , rem , ok := readi32 (src )
428- return uint32 (i32 ), rem , ok
442+ func ReadMsgChecksum (src []byte ) (uint32 , []byte , bool ) {
443+ return readu32 (src )
429444}
430445
431446// ReadQueryFlags reads OP_QUERY flags from src.
432447//
433448// Deprecated: Construct wiremessages with OpMsg and use the ReadMsg* functions
434449// instead.
435450func ReadQueryFlags (src []byte ) (flags QueryFlag , rem []byte , ok bool ) {
436- i32 , rem , ok := readi32 (src )
451+ i32 , rem , ok := binaryutil . ReadI32 (src )
437452 return QueryFlag (i32 ), rem , ok
438453}
439454
@@ -450,15 +465,15 @@ func ReadQueryFullCollectionName(src []byte) (collname string, rem []byte, ok bo
450465// Deprecated: Construct wiremessages with OpMsg and use the ReadMsg* functions
451466// instead.
452467func ReadQueryNumberToSkip (src []byte ) (nts int32 , rem []byte , ok bool ) {
453- return readi32 (src )
468+ return binaryutil . ReadI32 (src )
454469}
455470
456471// ReadQueryNumberToReturn reads the number to return from src.
457472//
458473// Deprecated: Construct wiremessages with OpMsg and use the ReadMsg* functions
459474// instead.
460475func ReadQueryNumberToReturn (src []byte ) (ntr int32 , rem []byte , ok bool ) {
461- return readi32 (src )
476+ return binaryutil . ReadI32 (src )
462477}
463478
464479// ReadQueryQuery reads the query from src.
@@ -478,24 +493,25 @@ func ReadQueryReturnFieldsSelector(src []byte) (rfs bsoncore.Document, rem []byt
478493}
479494
480495// ReadReplyFlags reads OP_REPLY flags from src.
481- func ReadReplyFlags (src []byte ) (flags ReplyFlag , rem []byte , ok bool ) {
482- i32 , rem , ok := readi32 (src )
496+ func ReadReplyFlags (src []byte ) (ReplyFlag , []byte , bool ) {
497+ i32 , rem , ok := binaryutil .ReadI32 (src )
498+
483499 return ReplyFlag (i32 ), rem , ok
484500}
485501
486502// ReadReplyCursorID reads a cursor ID from src.
487503func ReadReplyCursorID (src []byte ) (cursorID int64 , rem []byte , ok bool ) {
488- return readi64 (src )
504+ return binaryutil . ReadI64 (src )
489505}
490506
491507// ReadReplyStartingFrom reads the starting from src.
492508func ReadReplyStartingFrom (src []byte ) (startingFrom int32 , rem []byte , ok bool ) {
493- return readi32 (src )
509+ return binaryutil . ReadI32 (src )
494510}
495511
496512// ReadReplyNumberReturned reads the numbered returned from src.
497513func ReadReplyNumberReturned (src []byte ) (numberReturned int32 , rem []byte , ok bool ) {
498- return readi32 (src )
514+ return binaryutil . ReadI32 (src )
499515}
500516
501517// ReadReplyDocuments reads as many documents as possible from src
@@ -521,14 +537,14 @@ func ReadReplyDocument(src []byte) (doc bsoncore.Document, rem []byte, ok bool)
521537
522538// ReadCompressedOriginalOpCode reads the original opcode from src.
523539func ReadCompressedOriginalOpCode (src []byte ) (opcode OpCode , rem []byte , ok bool ) {
524- i32 , rem , ok := readi32 (src )
540+ i32 , rem , ok := binaryutil . ReadI32 (src )
525541 return OpCode (i32 ), rem , ok
526542}
527543
528544// ReadCompressedUncompressedSize reads the uncompressed size of a
529545// compressed wiremessage to dst.
530546func ReadCompressedUncompressedSize (src []byte ) (size int32 , rem []byte , ok bool ) {
531- return readi32 (src )
547+ return binaryutil . ReadI32 (src )
532548}
533549
534550// ReadCompressedCompressorID reads the ID of the compressor to dst.
@@ -541,20 +557,20 @@ func ReadCompressedCompressorID(src []byte) (id CompressorID, rem []byte, ok boo
541557
542558// ReadKillCursorsZero reads the zero field from src.
543559func ReadKillCursorsZero (src []byte ) (zero int32 , rem []byte , ok bool ) {
544- return readi32 (src )
560+ return binaryutil . ReadI32 (src )
545561}
546562
547563// ReadKillCursorsNumberIDs reads the numberOfCursorIDs field from src.
548564func ReadKillCursorsNumberIDs (src []byte ) (numIDs int32 , rem []byte , ok bool ) {
549- return readi32 (src )
565+ return binaryutil . ReadI32 (src )
550566}
551567
552568// ReadKillCursorsCursorIDs reads numIDs cursor IDs from src.
553569func ReadKillCursorsCursorIDs (src []byte , numIDs int32 ) (cursorIDs []int64 , rem []byte , ok bool ) {
554570 var i int32
555571 var id int64
556572 for i = 0 ; i < numIDs ; i ++ {
557- id , src , ok = readi64 (src )
573+ id , src , ok = binaryutil . ReadI64 (src )
558574 if ! ok {
559575 return cursorIDs , src , false
560576 }
@@ -564,39 +580,17 @@ func ReadKillCursorsCursorIDs(src []byte, numIDs int32) (cursorIDs []int64, rem
564580 return cursorIDs , src , true
565581}
566582
567- func appendi32 (dst []byte , x int32 ) []byte {
568- b := []byte {0 , 0 , 0 , 0 }
569- binary .LittleEndian .PutUint32 (b , uint32 (x ))
570- return append (dst , b ... )
571- }
572-
573- func appendi64 (dst []byte , x int64 ) []byte {
574- b := []byte {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
575- binary .LittleEndian .PutUint64 (b , uint64 (x ))
576- return append (dst , b ... )
577- }
578-
579583func appendCString (b []byte , str string ) []byte {
580584 b = append (b , str ... )
581585 return append (b , 0x00 )
582586}
583587
584- func readi32 (src []byte ) (int32 , []byte , bool ) {
588+ func readu32 (src []byte ) (uint32 , []byte , bool ) {
585589 if len (src ) < 4 {
586590 return 0 , src , false
587591 }
588- return readi32unsafe (src ), src [4 :], true
589- }
590592
591- func readi32unsafe (src []byte ) int32 {
592- return int32 (binary .LittleEndian .Uint32 (src ))
593- }
594-
595- func readi64 (src []byte ) (int64 , []byte , bool ) {
596- if len (src ) < 8 {
597- return 0 , src , false
598- }
599- return int64 (binary .LittleEndian .Uint64 (src )), src [8 :], true
593+ return binary .LittleEndian .Uint32 (src ), src [4 :], true
600594}
601595
602596func readcstring (src []byte ) (string , []byte , bool ) {
0 commit comments