Skip to content

Commit 705e6f3

Browse files
(gosec) Apply G115 fixes to x/mongo/driver/wiremessage package
Address gosec G115 integer overflow warnings in wiremessage: - Use binaryutil package for safe binary read/write operations - Add validation for MsgFlag overflow with nolint for safe conversions - Document safety of wire protocol flag conversions
1 parent acb5d3d commit 705e6f3

File tree

2 files changed

+65
-343
lines changed

2 files changed

+65
-343
lines changed

x/mongo/driver/wiremessage/wiremessage.go

Lines changed: 65 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ package wiremessage
1616
import (
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.
220222
func 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.
229231
func 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.
251253
func 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.
256258
func 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.
261268
func 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.
276283
func 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.
281288
func 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.
286293
func 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.
291298
func 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.
296303
func 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.
301308
func 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.
310319
func 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.
318327
func 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.
328337
func 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.
333342
func 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.
338347
func 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.
343352
func 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.
348357
func 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.
356365
func 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.
362375
func 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.
407423
func 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.
435450
func 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.
452467
func 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.
460475
func 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.
487503
func 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.
492508
func 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.
497513
func 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.
523539
func 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.
530546
func 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.
543559
func 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.
548564
func 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.
553569
func 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-
579583
func 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

602596
func readcstring(src []byte) (string, []byte, bool) {

0 commit comments

Comments
 (0)