PgDoorman rejects PostgreSQL StartupMessage packets containing an empty parameter value.

Open Beginner friendly
#274 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
postgresql, rust
Domain
backend, databases

Research direction

Start in src/messages/protocol.rs at parse_params() and inspect how the StartupMessage parameter sequence is split. Reproduce the issue with a packet containing options\0\0, then verify that empty parameter values are retained while the empty parameter name still terminates the list. Done means the lib/pq v1.11.1 startup sequence is accepted without the odd-parameter-count error.

Written by the indexing model from the issue text.

Description

Summary

PgDoorman rejects PostgreSQL StartupMessage packets containing an empty parameter value.

This affects clients using lib/pq. In particular, lib/pq v1.11.1 always includes the options parameter in the startup packet, even when its value is empty:

options\0\0

PgDoorman's parse_params() ignores every empty null-terminated string. As a result, it keeps the options key but drops its empty value, producing an odd number of parsed strings and rejecting the connection.

Error

Protocol synchronization error: Invalid client startup message: Expected key-value pairs, but received 7 parameters

Environment

  • PgDoorman version: 3.10.7
  • PostgreSQL driver: github.com/lib/pq v1.11.1
  • PostgreSQL SSL mode: disabled

Steps to reproduce

postgresql://my-user:my-password@pg-doorman-address:6432/my-database?sslmode=disable

PgDoorman rejects the startup packet with:

Invalid client startup message: Expected key-value pairs, but received 7 parameters

A representative startup parameter sequence is:

user\0my-user\0
database\0my-database\0
options\0\0
client_encoding\0UTF8\0
\0

Expected behavior

PgDoorman should accept empty parameter values.

In the PostgreSQL startup protocol:

  • An empty parameter name marks the end of the parameter list.
  • A parameter value may be empty.
  • options\0\0 should therefore be parsed as options = "", not as a missing value.

Actual behavior

In src/messages/protocol.rs, parse_params() only pushes a parsed string when it is non-empty:

if !tmp.is_empty() {
    buf.push(tmp.clone());
    tmp.clear();
}

This removes both:

  • the final empty parameter-list terminator;
  • legitimate empty parameter values.

After the empty options value is discarded, PgDoorman sees seven strings and reports an invalid key/value pair count.

Note

Upgrading clients to lib/pq v1.11.2 fixes the issue, as they stop sending empty options.
link to release

Workaround

Setting a non-empty options value allows the client to connect:

postgresql://my-user:my-password@pg-doorman-address:6432/my-database?sslmode=disable%20options='-c%20application_name=my-application'

This workaround has been tested successfully.

AI disclosure

This issue was drafted with assistance from ChatGPT. The reported behavior, reproduction steps, workaround, and technical details were manually verified before submission.

Dominant language
Rust
Stars
275
Forks
12
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ozontech/pg_doorman

All issues in ozontech/pg_doorman

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.