@@ -19,6 +19,7 @@ package pgsql
1919
2020import (
2121 "errors"
22+ "fmt"
2223 "strings"
2324
2425 "github.com/elastic/beats/v7/libbeat/common"
@@ -85,7 +86,12 @@ func (pgsql *pgsqlPlugin) parseMessageStart(s *pgsqlStream) (bool, bool) {
8586 s .parseOffset += length
8687 m .end = s .parseOffset
8788 m .isSSLRequest = true
88- m .size = uint64 (m .end - m .start )
89+ msgSize := m .end - m .start
90+ if msgSize < 0 {
91+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
92+ return false , false
93+ }
94+ m .size = uint64 (msgSize )
8995
9096 return true , true
9197 }
@@ -94,7 +100,7 @@ func (pgsql *pgsqlPlugin) parseMessageStart(s *pgsqlStream) (bool, bool) {
94100
95101func (pgsql * pgsqlPlugin ) parseCommand (s * pgsqlStream ) (bool , bool ) {
96102 // read type
97- typ := byte ( s .data [s .parseOffset ])
103+ typ := s .data [s .parseOffset ]
98104
99105 if s .expectSSLResponse {
100106 // SSLRequest was received in the other stream
@@ -107,7 +113,12 @@ func (pgsql *pgsqlPlugin) parseCommand(s *pgsqlStream) (bool, bool) {
107113 s .parseOffset ++
108114 m .end = s .parseOffset
109115 m .isSSLResponse = true
110- m .size = uint64 (m .end - m .start )
116+ msgSize := m .end - m .start
117+ if msgSize < 0 {
118+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
119+ return false , false
120+ }
121+ m .size = uint64 (msgSize )
111122
112123 return true , true
113124 }
@@ -161,7 +172,12 @@ func (pgsql *pgsqlPlugin) parseSimpleQuery(s *pgsqlStream, length int) (bool, bo
161172 s .parseOffset ++ // type
162173 s .parseOffset += length
163174 m .end = s .parseOffset
164- m .size = uint64 (m .end - m .start )
175+ msgSize := m .end - m .start
176+ if msgSize < 0 {
177+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
178+ return false , false
179+ }
180+ m .size = uint64 (msgSize )
165181
166182 query , err := pgsqlString (s .data [m .start + 5 :], length - 4 )
167183 if err != nil {
@@ -224,7 +240,12 @@ func (pgsql *pgsqlPlugin) parseEmptyQueryResponse(s *pgsqlStream) (bool, bool) {
224240 m .toExport = true
225241 s .parseOffset += 5 // type + length
226242 m .end = s .parseOffset
227- m .size = uint64 (m .end - m .start )
243+ msgSize := m .end - m .start
244+ if msgSize < 0 {
245+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
246+ return false , false
247+ }
248+ m .size = uint64 (msgSize )
228249
229250 return true , true
230251}
@@ -248,7 +269,12 @@ func (pgsql *pgsqlPlugin) parseCommandComplete(s *pgsqlStream, length int) (bool
248269
249270 s .parseOffset += length
250271 m .end = s .parseOffset
251- m .size = uint64 (m .end - m .start )
272+ msgSize := m .end - m .start
273+ if msgSize < 0 {
274+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
275+ return false , false
276+ }
277+ m .size = uint64 (msgSize )
252278
253279 return true , true
254280}
@@ -257,7 +283,12 @@ func (pgsql *pgsqlPlugin) parseReadyForQuery(s *pgsqlStream, length int) (bool,
257283 // ReadyForQuery -> backend ready for a new query cycle
258284 m := s .message
259285 m .start = s .parseOffset
260- m .size = uint64 (m .end - m .start )
286+ msgSize := m .end - m .start
287+ if msgSize < 0 {
288+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
289+ return false , false
290+ }
291+ m .size = uint64 (msgSize )
261292
262293 s .parseOffset ++ // type
263294 s .parseOffset += length
@@ -281,7 +312,12 @@ func (pgsql *pgsqlPlugin) parseErrorResponse(s *pgsqlStream, length int) (bool,
281312
282313 s .parseOffset += length // length
283314 m .end = s .parseOffset
284- m .size = uint64 (m .end - m .start )
315+ msgSize := m .end - m .start
316+ if msgSize < 0 {
317+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
318+ return false , false
319+ }
320+ m .size = uint64 (msgSize )
285321
286322 return true , true
287323}
@@ -297,7 +333,12 @@ func (pgsql *pgsqlPlugin) parseExtReq(s *pgsqlStream, length int) (bool, bool) {
297333 s .parseOffset ++ // type
298334 s .parseOffset += length
299335 m .end = s .parseOffset
300- m .size = uint64 (m .end - m .start )
336+ msgSize := m .end - m .start
337+ if msgSize < 0 {
338+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
339+ return false , false
340+ }
341+ m .size = uint64 (msgSize )
301342 m .toExport = true
302343
303344 query , err := common .ReadString (s .data [m .start + 6 :])
@@ -341,7 +382,12 @@ func (pgsql *pgsqlPlugin) parseSkipMessage(s *pgsqlStream, length int) (bool, bo
341382
342383 m := s .message
343384 m .end = s .parseOffset
344- m .size = uint64 (m .end - m .start )
385+ msgSize := m .end - m .start
386+ if msgSize < 0 {
387+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
388+ return false , false
389+ }
390+ m .size = uint64 (msgSize )
345391
346392 // ok and complete, but ignore
347393 m .toExport = false
@@ -456,7 +502,7 @@ func (pgsql *pgsqlPlugin) parseMessageData(s *pgsqlStream) (bool, bool) {
456502
457503 for len (s .data [s .parseOffset :]) > 5 {
458504 // read type
459- typ := byte ( s .data [s .parseOffset ])
505+ typ := s .data [s .parseOffset ]
460506
461507 // read message length
462508 length := readLength (s .data [s .parseOffset + 1 :])
@@ -475,6 +521,7 @@ func (pgsql *pgsqlPlugin) parseMessageData(s *pgsqlStream) (bool, bool) {
475521 case 'D' :
476522 err := pgsql .parseDataRow (s , s .data [s .parseOffset + 5 :s .parseOffset + length + 1 ])
477523 if err != nil {
524+ pgsql .detailf ("error parsing data row: %s" , err )
478525 return false , false
479526 }
480527 s .parseOffset ++
@@ -494,7 +541,12 @@ func (pgsql *pgsqlPlugin) parseMessageData(s *pgsqlStream) (bool, bool) {
494541 pgsql .detailf ("CommandComplete length=%d, tag=%s" , length , name )
495542 s .parseOffset += length
496543 m .end = s .parseOffset
497- m .size = uint64 (m .end - m .start )
544+ msgSize := m .end - m .start
545+ if msgSize < 0 {
546+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
547+ return false , false
548+ }
549+ m .size = uint64 (msgSize )
498550 s .parseState = pgsqlStartState
499551
500552 pgsql .detailf ("Rows: %s" , m .rows )
@@ -531,7 +583,10 @@ func (pgsql *pgsqlPlugin) parseDataRow(s *pgsqlStream, buf []byte) error {
531583 rows := []string {}
532584 rowLength := 0
533585
534- for i := 0 ; i < fieldCount ; i ++ {
586+ if fieldCount > len (m .fieldsFormat ) {
587+ return fmt .Errorf ("%w: DataRow field mismatch, got %d, expected %d" , errFieldBufferBig , fieldCount , len (m .fieldsFormat ))
588+ }
589+ for field := range fieldCount {
535590 if len (buf ) <= off {
536591 return errFieldBufferShort
537592 }
@@ -541,14 +596,14 @@ func (pgsql *pgsqlPlugin) parseDataRow(s *pgsqlStream, buf []byte) error {
541596 off += 4
542597
543598 if columnLength > 0 && columnLength > len (buf [off :]) {
544- pgsql .log .Errorf ("Pgsql invalid column_length=%v, buffer_length=%v, i =%v" ,
545- columnLength , len (buf [off :]), i )
599+ pgsql .log .Errorf ("Pgsql invalid column_length=%v, buffer_length=%v, field =%v" ,
600+ columnLength , len (buf [off :]), field )
546601 return errInvalidLength
547602 }
548603
549604 // read column value (byten)
550605 var columnValue []byte
551- if m .fieldsFormat [i ] == 0 {
606+ if m .fieldsFormat [field ] == 0 {
552607 // field value in text format
553608 if columnLength > 0 {
554609 columnValue = buf [off : off + columnLength ]
@@ -593,7 +648,7 @@ func (pgsql *pgsqlPlugin) parseMessageExtendedQuery(s *pgsqlStream) (bool, bool)
593648
594649 for len (s .data [s .parseOffset :]) >= 5 {
595650 // read type
596- typ := byte ( s .data [s .parseOffset ])
651+ typ := s .data [s .parseOffset ]
597652
598653 // read message length
599654 length := readLength (s .data [s .parseOffset + 1 :])
@@ -637,7 +692,12 @@ func (pgsql *pgsqlPlugin) parseMessageExtendedQuery(s *pgsqlStream) (bool, bool)
637692 s .parseOffset ++
638693 s .parseOffset += length
639694 m .end = s .parseOffset
640- m .size = uint64 (m .end - m .start )
695+ msgSize := m .end - m .start
696+ if msgSize < 0 {
697+ pgsql .detailf ("invalid size: start: %d end: %d" , m .start , m .end )
698+ return false , false
699+ }
700+ m .size = uint64 (msgSize )
641701 s .parseState = pgsqlStartState
642702
643703 return true , true
0 commit comments