Skip to content

Negative field length panics in DataRow.Decode #2507

@athuljayaram

Description

@athuljayaram

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 0x800000000xFFFFFFFE).


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
}

Reference

https://securityinfinity.com/research/memory-safety-vulnerabilities-in-go-postgresql-wire-protocol-parsers-pgproto3-pgx

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions