fix(pgdriver): guard protocol message sizes against overflow and invalid lengths - #1401
Open
namtzigla wants to merge 2 commits into
Open
fix(pgdriver): guard protocol message sizes against overflow and invalid lengths#1401namtzigla wants to merge 2 commits into
namtzigla wants to merge 2 commits into
Conversation
…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
force-pushed
the
fix/pgdriver-message-size-overflow
branch
from
July 22, 2026 03:52
5890db2 to
0413bbe
Compare
Aoang
self-requested a review
July 22, 2026 08:44
Aoang
requested changes
Aug 6, 2026
Co-authored-by: Aoang <aoang@x2oe.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/pgdriverwrote message/parameter length prefixes by castinglen()touint32/int16with no bound check. A single query or parameter ≥ 4 GiB wrapped thelength 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
Querymessage and the wrapped length letsthe 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 servercould crash the client (negative length → panic) or exhaust memory.
Change
Write side
writeBufferrecords a sticky error when a message (FinishMessage) or parameter(
FinishParam) would exceed the 32-bit size limit, andConn.writerefuses to send abuffer whose message failed to build — so an overflowing message never reaches the wire.
writeBindExecuterejects> math.MaxInt16parameters instead of truncating the count.Read side
readMessageTyperejects a length field< 4(would produce a negative body length).reader.ReadTemprejects a negativen.readColumnValue's default branch treats a non-positive length as NULL rather thanmake([]byte, negative).Tests
driver/pgdriver/message_size_test.gocovers the write guards (the 4 GiB limit is atest-overridable var so the test needs no multi-GB allocation), the Bind param-count cap,
and the read-side rejections.
go build,go vet,gofmtclean; new tests pass. (The twopre-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