-
-
Notifications
You must be signed in to change notification settings - Fork 998
Description
Package: github.com/jackc/pgproto3 v2.3.3
File: data_row.go:48–59
Severity: 7.5 High
CWE: CWE-129 - Improper Validation of Array Index
Summary
DataRow.Decode panics with slice bounds out of range when a server
sends a field length that is a negative int32 value (any uint32 in the
range 0x80000000–0xFFFFFFFE).
Root Cause
Line 48 reads the field length correctly as a signed int32:
go
msgSize := int(int32(binary.BigEndian.Uint32(src[rp:])))
The null sentinel check on the following line correctly handles -1.
However, the subsequent bounds check at line 55:
if len(src[rp:]) < msgSize {
return &invalidMessageFormatErr{messageType: "DataRow"}
}
is vacuously false whenever msgSize is negative. In Go, len() always
returns a non-negative integer, so len(...) < -13619152 can never be
true. The guard is bypassed entirely, and execution reaches line 59:
dst.Values[i] = src[rp : rp+msgSize : rp+msgSize]
// panic: runtime error: slice bounds out of range [:-13619152]
The process terminates unconditionally.
Impact
A malicious or compromised PostgreSQL server can crash any Go application
using this library by sending a single crafted DataRow message. No
special privilege is required — any server the client connects to can
trigger this.
CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 High
Fix
Add a msgSize < 0 guard between the null check and the bounds check:
if msgSize == -1 {
dst.Values[i] = nil
} else if msgSize < 0 || len(src[rp:]) < msgSize {
return &invalidMessageFormatErr{messageType: "DataRow"}
} else {
dst.Values[i] = src[rp : rp+msgSize : rp+msgSize]
rp += msgSize
}