Skip to content
This repository was archived by the owner on Jul 12, 2025. It is now read-only.

Commit 945c212

Browse files
committed
Backport fixes from pgx v5
Check for overflow on uint16 sizes in pgproto3 Do not allow protocol messages larger than ~1GB The PostgreSQL server will reject messages greater than ~1 GB anyway. However, worse than that is that a message that is larger than 4 GB could wrap the 32-bit integer message size and be interpreted by the server as multiple messages. This could allow a malicious client to inject arbitrary protocol messages. GHSA-mrww-27vc-gghv
1 parent 0c0f7b0 commit 945c212

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+359
-359
lines changed

authentication_cleartext_password.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ func (dst *AuthenticationCleartextPassword) Decode(src []byte) error {
3535
}
3636

3737
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
38-
func (src *AuthenticationCleartextPassword) Encode(dst []byte) []byte {
39-
dst = append(dst, 'R')
40-
dst = pgio.AppendInt32(dst, 8)
38+
func (src *AuthenticationCleartextPassword) Encode(dst []byte) ([]byte, error) {
39+
dst, sp := beginMessage(dst, 'R')
4140
dst = pgio.AppendUint32(dst, AuthTypeCleartextPassword)
42-
return dst
41+
return finishMessage(dst, sp)
4342
}
4443

4544
// MarshalJSON implements encoding/json.Marshaler.

authentication_gss.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/binary"
55
"encoding/json"
66
"errors"
7+
78
"github.com/jackc/pgio"
89
)
910

@@ -26,11 +27,10 @@ func (a *AuthenticationGSS) Decode(src []byte) error {
2627
return nil
2728
}
2829

29-
func (a *AuthenticationGSS) Encode(dst []byte) []byte {
30-
dst = append(dst, 'R')
31-
dst = pgio.AppendInt32(dst, 4)
30+
func (a *AuthenticationGSS) Encode(dst []byte) ([]byte, error) {
31+
dst, sp := beginMessage(dst, 'R')
3232
dst = pgio.AppendUint32(dst, AuthTypeGSS)
33-
return dst
33+
return finishMessage(dst, sp)
3434
}
3535

3636
func (a *AuthenticationGSS) MarshalJSON() ([]byte, error) {

authentication_gss_continue.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/binary"
55
"encoding/json"
66
"errors"
7+
78
"github.com/jackc/pgio"
89
)
910

@@ -30,12 +31,11 @@ func (a *AuthenticationGSSContinue) Decode(src []byte) error {
3031
return nil
3132
}
3233

33-
func (a *AuthenticationGSSContinue) Encode(dst []byte) []byte {
34-
dst = append(dst, 'R')
35-
dst = pgio.AppendInt32(dst, int32(len(a.Data))+8)
34+
func (a *AuthenticationGSSContinue) Encode(dst []byte) ([]byte, error) {
35+
dst, sp := beginMessage(dst, 'R')
3636
dst = pgio.AppendUint32(dst, AuthTypeGSSCont)
3737
dst = append(dst, a.Data...)
38-
return dst
38+
return finishMessage(dst, sp)
3939
}
4040

4141
func (a *AuthenticationGSSContinue) MarshalJSON() ([]byte, error) {

authentication_md5_password.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ func (dst *AuthenticationMD5Password) Decode(src []byte) error {
3838
}
3939

4040
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
41-
func (src *AuthenticationMD5Password) Encode(dst []byte) []byte {
42-
dst = append(dst, 'R')
43-
dst = pgio.AppendInt32(dst, 12)
41+
func (src *AuthenticationMD5Password) Encode(dst []byte) ([]byte, error) {
42+
dst, sp := beginMessage(dst, 'R')
4443
dst = pgio.AppendUint32(dst, AuthTypeMD5Password)
4544
dst = append(dst, src.Salt[:]...)
46-
return dst
45+
return finishMessage(dst, sp)
4746
}
4847

4948
// MarshalJSON implements encoding/json.Marshaler.

authentication_ok.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ func (dst *AuthenticationOk) Decode(src []byte) error {
3535
}
3636

3737
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
38-
func (src *AuthenticationOk) Encode(dst []byte) []byte {
39-
dst = append(dst, 'R')
40-
dst = pgio.AppendInt32(dst, 8)
38+
func (src *AuthenticationOk) Encode(dst []byte) ([]byte, error) {
39+
dst, sp := beginMessage(dst, 'R')
4140
dst = pgio.AppendUint32(dst, AuthTypeOk)
42-
return dst
41+
return finishMessage(dst, sp)
4342
}
4443

4544
// MarshalJSON implements encoding/json.Marshaler.

authentication_sasl.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ func (dst *AuthenticationSASL) Decode(src []byte) error {
4646
}
4747

4848
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
49-
func (src *AuthenticationSASL) Encode(dst []byte) []byte {
50-
dst = append(dst, 'R')
51-
sp := len(dst)
52-
dst = pgio.AppendInt32(dst, -1)
49+
func (src *AuthenticationSASL) Encode(dst []byte) ([]byte, error) {
50+
dst, sp := beginMessage(dst, 'R')
5351
dst = pgio.AppendUint32(dst, AuthTypeSASL)
5452

5553
for _, s := range src.AuthMechanisms {
@@ -58,9 +56,7 @@ func (src *AuthenticationSASL) Encode(dst []byte) []byte {
5856
}
5957
dst = append(dst, 0)
6058

61-
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
62-
63-
return dst
59+
return finishMessage(dst, sp)
6460
}
6561

6662
// MarshalJSON implements encoding/json.Marshaler.

authentication_sasl_continue.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,11 @@ func (dst *AuthenticationSASLContinue) Decode(src []byte) error {
3838
}
3939

4040
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
41-
func (src *AuthenticationSASLContinue) Encode(dst []byte) []byte {
42-
dst = append(dst, 'R')
43-
sp := len(dst)
44-
dst = pgio.AppendInt32(dst, -1)
41+
func (src *AuthenticationSASLContinue) Encode(dst []byte) ([]byte, error) {
42+
dst, sp := beginMessage(dst, 'R')
4543
dst = pgio.AppendUint32(dst, AuthTypeSASLContinue)
46-
4744
dst = append(dst, src.Data...)
48-
49-
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
50-
51-
return dst
45+
return finishMessage(dst, sp)
5246
}
5347

5448
// MarshalJSON implements encoding/json.Marshaler.

authentication_sasl_final.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,11 @@ func (dst *AuthenticationSASLFinal) Decode(src []byte) error {
3838
}
3939

4040
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
41-
func (src *AuthenticationSASLFinal) Encode(dst []byte) []byte {
42-
dst = append(dst, 'R')
43-
sp := len(dst)
44-
dst = pgio.AppendInt32(dst, -1)
41+
func (src *AuthenticationSASLFinal) Encode(dst []byte) ([]byte, error) {
42+
dst, sp := beginMessage(dst, 'R')
4543
dst = pgio.AppendUint32(dst, AuthTypeSASLFinal)
46-
4744
dst = append(dst, src.Data...)
48-
49-
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
50-
51-
return dst
45+
return finishMessage(dst, sp)
5246
}
5347

5448
// MarshalJSON implements encoding/json.Unmarshaler.

backend.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ func NewBackend(cr ChunkReader, w io.Writer) *Backend {
4949

5050
// Send sends a message to the frontend.
5151
func (b *Backend) Send(msg BackendMessage) error {
52-
_, err := b.w.Write(msg.Encode(nil))
52+
buf, err := msg.Encode(nil)
53+
if err != nil {
54+
return err
55+
}
56+
57+
_, err = b.w.Write(buf)
5358
return err
5459
}
5560

@@ -184,11 +189,11 @@ func (b *Backend) Receive() (FrontendMessage, error) {
184189
// contextual identification of FrontendMessages. For example, in the
185190
// PG message flow documentation for PasswordMessage:
186191
//
187-
// Byte1('p')
192+
// Byte1('p')
188193
//
189-
// Identifies the message as a password response. Note that this is also used for
190-
// GSSAPI, SSPI and SASL response messages. The exact message type can be deduced from
191-
// the context.
194+
// Identifies the message as a password response. Note that this is also used for
195+
// GSSAPI, SSPI and SASL response messages. The exact message type can be deduced from
196+
// the context.
192197
//
193198
// Since the Frontend does not know about the state of a backend, it is important
194199
// to call SetAuthType() after an authentication request is received by the Frontend.

backend_key_data.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@ func (dst *BackendKeyData) Decode(src []byte) error {
2929
}
3030

3131
// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
32-
func (src *BackendKeyData) Encode(dst []byte) []byte {
33-
dst = append(dst, 'K')
34-
dst = pgio.AppendUint32(dst, 12)
32+
func (src *BackendKeyData) Encode(dst []byte) ([]byte, error) {
33+
dst, sp := beginMessage(dst, 'K')
3534
dst = pgio.AppendUint32(dst, src.ProcessID)
3635
dst = pgio.AppendUint32(dst, src.SecretKey)
37-
return dst
36+
return finishMessage(dst, sp)
3837
}
3938

4039
// MarshalJSON implements encoding/json.Marshaler.

0 commit comments

Comments
 (0)