Skip to content

Fix: Extended Query Protocol Parse packets corrupted by interceptor#18

Draft
nik-localstack wants to merge 1 commit into
masterfrom
fix/parametrized-upsert
Draft

Fix: Extended Query Protocol Parse packets corrupted by interceptor#18
nik-localstack wants to merge 1 commit into
masterfrom
fix/parametrized-upsert

Conversation

@nik-localstack
Copy link
Copy Markdown

Motivation

psycopg v3 (and asyncpg) use the Extended Query Protocol, sending a Parse packet whose body ends with binary uint32 parameter-type OIDs.
The interceptor sliced the body with data[1:-2], leaking those OID bytes into a UTF-8 decode.
The jsonb OID (3802 = 0x0EDA) contains 0xDA which is invalid UTF-8 and as a result crashing the interceptor and leaving the connection in a broken state.

In LocalStack this surfaced as an indefinite hang.

Fix

Use find(b"\x00") to locate the true null-terminators of the statement name and query text, so the binary OID suffix is never fed to the text decoder.

Tests

A new e2e regression test that connects via psycopg v3 through the proxy and executes a parameterized INSERT with jsonb and text arguments.

…y OID suffix

The Parse packet body (type 'P') has the format:
  statement_name\x00 + query\x00 + int16(param_count) + uint32[] OIDs
The old handler used data[1:-2] / data[-2:] which treated only the last
2 bytes as the param-count field, leaking binary OID bytes into the query
slice fed to _intercept_query().  When a parameter type OID contains a
byte >= 0x80 (e.g. jsonb OID 3802 = 0x00000EDA), the subsequent UTF-8
decode raised UnicodeDecodeError, causing the connection to drop or hang.
Fix: use find(b'\x00') to locate the true boundaries of statement name
and query text, so the binary suffix is never touched by the text decoder.
Adds a regression test using psycopg v3 (Extended Query Protocol) with
a jsonb+text parameterized INSERT through the proxy.

Co-authored-by: GitHub Copilot <copilot@github.com>
@nik-localstack nik-localstack self-assigned this May 22, 2026
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.

1 participant