[PATCH v1 0/2] Preserve input sign across numeric parameter parsing

Started by Haibo Yan9 days ago1 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

needs rebasesuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253769
psql -h localhost -U postgres

Built from patchset v1 (message #1), September 13, 2026 at 09:31 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253769_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253769_1 && git checkout t253769_1

Patchset v1 (message #1) is on t253769_1

Jump to latest
#1Haibo Yan
tristan.yim@gmail.com

Hi hackers,

While looking at the WAIT FOR timeout parsing issue, I noticed that the
underlying problem is not specific to WAIT FOR. parse_int() and parse_real()
can lose information about the original value during unit conversion and
rounding, before the caller gets a chance to validate it.

For example, these are currently accepted:

SET statement_timeout = '-0.5ms';
CREATE TABLE t (i int) WITH (parallel_workers = -0.4);
VACUUM (BUFFER_USAGE_LIMIT '-512B') t;

The first is stored as 0, the reloption is accepted after -0.4 rounds to 0, and
the VACUUM option is interpreted as the special value 0 (“no ring
buffer limit”).
WAIT FOR has the same issue: a timeout of ‘-0.4ms’ passes the negative check
after rounding and becomes an indefinite wait.

Patch 0001 adds parse_int_with_sign() and parse_real_with_sign(), which preserve
the sign of the input quantity before unit conversion or rounding. The existing
parse_int()/parse_real() interfaces are unchanged. GUC and integer reloption
validation use the preserved sign so that a negative input cannot become valid
merely by rounding to zero.

Patch 0002 uses the same information for WAIT FOR and VACUUM, where zero has
special semantics. An explicit zero remains valid, while a nonzero value that
collapses to zero is rejected.

This series deliberately does not change the existing behavior for positive GUC
values that round to zero. For example, statement_timeout = ‘0.4ms’ still
becomes 0. It also does not address the separate parse_real() unit-conversion
precision issue.

For WAIT FOR, I chose to reject positive timeouts below the 1 ms resolution
rather than silently turn them into an indefinite wait or clamp them to 1 ms.
I’m happy to change that if another behavior is preferred.

The series passes the regression tests and recovery/049_wait_for_lsn, as well
as the full Meson test suite on Linux x86_64 with assertions enabled.

Regards,
Haibo

Attachments:

t253769_1
v1-0001-Preserve-the-sign-of-a-numeric-parameter-value-ac.patchapplication/octet-stream; name=v1-0001-Preserve-the-sign-of-a-numeric-parameter-value-ac.patchDownload+242-9
v1-0002-Reject-nonzero-command-option-values-that-round-t.patchapplication/octet-stream; name=v1-0002-Reject-nonzero-command-option-values-that-round-t.patchDownload+76-6