@@ -5,8 +5,27 @@ import (
55 "encoding/binary"
66 "fmt"
77 "io"
8+ "sync/atomic"
89)
910
11+ var (
12+ // When using the PostgreSQL driver, it is impossible to set a limit using
13+ // the structure method, however, sometimes it is necessary to set a limit
14+ // for the safety of the application. A similar functionality
15+ // has been made for client messages.
16+ commonMaxBackendBodyLen atomic.Uint32
17+ )
18+
19+ // SetCommonMaxBackendBodyLen sets the maximum length of a message body in octets.
20+ // If a message body exceeds this length, Receive will return an error.
21+ // This is useful for protecting against malicious clients that send
22+ // large messages with the intent of causing memory exhaustion.
23+ // The default value is 0.
24+ // If value is 0, then no maximum is enforced.
25+ func SetCommonMaxBackendBodyLen (value uint32 ) {
26+ commonMaxBackendBodyLen .Store (value )
27+ }
28+
1029// Backend acts as a server for the PostgreSQL wire protocol version 3.
1130type Backend struct {
1231 cr * chunkReader
@@ -39,7 +58,9 @@ type Backend struct {
3958 terminate Terminate
4059
4160 bodyLen int
42- maxBodyLen int // maxBodyLen is the maximum length of a message body in octets. If a message body exceeds this length, Receive will return an error.
61+ maxBodyLen int
62+ // maxBodyLen is the maximum length of a message body in octets.
63+ // If a message body exceeds this length, Receive will return an error.
4364 msgType byte
4465 partialMsg bool
4566 authType uint32
@@ -175,10 +196,20 @@ func (b *Backend) Receive() (FrontendMessage, error) {
175196 }
176197
177198 b .msgType = header [0 ]
178- b .bodyLen = int (binary .BigEndian .Uint32 (header [1 :])) - 4
199+
200+ msgLength := int (binary .BigEndian .Uint32 (header [1 :]))
201+ if msgLength < 4 {
202+ return nil , fmt .Errorf ("invalid message length: %d" , msgLength )
203+ }
204+
205+ b .bodyLen = msgLength - 4
179206 if b .maxBodyLen > 0 && b .bodyLen > b .maxBodyLen {
180207 return nil , & ExceededMaxBodyLenErr {b .maxBodyLen , b .bodyLen }
181208 }
209+ commonMaxBodyLen := int (commonMaxBackendBodyLen .Load ())
210+ if commonMaxBodyLen > 0 && b .bodyLen > commonMaxBodyLen {
211+ return nil , & ExceededMaxBodyLenErr {commonMaxBodyLen , b .bodyLen }
212+ }
182213 b .partialMsg = true
183214 }
184215
@@ -282,9 +313,10 @@ func (b *Backend) SetAuthType(authType uint32) error {
282313 return nil
283314}
284315
285- // SetMaxBodyLen sets the maximum length of a message body in octets. If a message body exceeds this length, Receive will return
286- // an error. This is useful for protecting against malicious clients that send large messages with the intent of
287- // causing memory exhaustion.
316+ // SetMaxBodyLen sets the maximum length of a message body in octets.
317+ // If a message body exceeds this length, Receive will return an error.
318+ // This is useful for protecting against malicious clients that send
319+ // large messages with the intent of causing memory exhaustion.
288320// The default value is 0.
289321// If maxBodyLen is 0, then no maximum is enforced.
290322func (b * Backend ) SetMaxBodyLen (maxBodyLen int ) {
0 commit comments