Skip to content

fix(pgdriver): guard protocol message sizes against overflow and invalid lengths - #1401

Open
namtzigla wants to merge 2 commits into
uptrace:masterfrom
namtzigla:fix/pgdriver-message-size-overflow
Open

fix(pgdriver): guard protocol message sizes against overflow and invalid lengths#1401
namtzigla wants to merge 2 commits into
uptrace:masterfrom
namtzigla:fix/pgdriver-message-size-overflow

Conversation

@namtzigla

Copy link
Copy Markdown
Contributor

What

Guards the pgdriver Postgres protocol against message-size integer overflow (write
side) and invalid/negative server-supplied lengths (read side).

Closes #1397.

Why

driver/pgdriver wrote message/parameter length prefixes by casting len() to
uint32/int16 with no bound check. A single query or parameter ≥ 4 GiB wrapped the
length field, desyncing the server — the same integer-overflow → protocol-desync → SQL
injection class as jackc/pgx CVE-2024-27304. bun uses the simple protocol, so an
oversized inlined parameter goes out as one Query message and the wrapped length lets
the server parse attacker bytes as a new frame. Separately, server-supplied lengths were
fed straight into make([]byte, n) / slice expressions, so a malicious or on-path server
could crash the client (negative length → panic) or exhaust memory.

Change

Write side

  • writeBuffer records a sticky error when a message (FinishMessage) or parameter
    (FinishParam) would exceed the 32-bit size limit, and Conn.write refuses to send a
    buffer whose message failed to build — so an overflowing message never reaches the wire.
  • writeBindExecute rejects > math.MaxInt16 parameters instead of truncating the count.

Read side

  • readMessageType rejects a length field < 4 (would produce a negative body length).
  • reader.ReadTemp rejects a negative n.
  • readColumnValue's default branch treats a non-positive length as NULL rather than
    make([]byte, negative).

Tests

driver/pgdriver/message_size_test.go covers the write guards (the 4 GiB limit is a
test-overridable var so the test needs no multi-GB allocation), the Bind param-count cap,
and the read-side rejections. go build, go vet, gofmt clean; new tests pass. (The two
pre-existing failing tests in this package require a live PostgreSQL and fail identically on
master.)

Notes / scope

The read-side change guards the negative-length panics; a configurable cap for very large
(but positive) server-declared lengths is intentionally left out to avoid breaking legitimate
large result values — happy to add one if preferred.

Reference

…lid lengths

Write side: the message/parameter length prefixes were written by casting len()
to uint32/int16 with no bound check. A query or parameter >= 4 GiB wrapped the
length field, desyncing the server and enabling SQL injection (same class as
jackc/pgx CVE-2024-27304); >32767 bind parameters truncated the Bind count.

- writeBuffer now records a sticky error when a message/param exceeds the 32-bit
  size limit (FinishMessage/FinishParam), and Conn.write refuses to send a buffer
  whose message failed to build, so an overflowing message never reaches the wire.
- writeBindExecute rejects > math.MaxInt16 parameters instead of truncating.

Read side: server-supplied lengths were used directly in make([]byte, n) /
slice expressions, so a malicious or on-path server could crash the client with
a negative length (panic) or exhaust memory.

- readMessageType rejects a length field < 4 (would yield a negative body length).
- reader.ReadTemp rejects a negative n.
- readColumnValue's default branch treats a non-positive length as NULL instead
  of make([]byte, negative).

Adds unit tests (the 4 GiB limit is a test-overridable var).
@namtzigla
namtzigla force-pushed the fix/pgdriver-message-size-overflow branch from 5890db2 to 0413bbe Compare July 22, 2026 03:52
@Aoang
Aoang self-requested a review July 22, 2026 08:44
Comment thread driver/pgdriver/column.go Outdated
Co-authored-by: Aoang <aoang@x2oe.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pgdriver: message-length uint32 overflow → SQL injection (pgx CVE-2024-27304 class) + unbounded server-controlled allocations

2 participants