| From: | ♂π≌26218 <1991230470(at)qq(dot)com> |
|---|---|
| To: | pgsql-bugs <pgsql-bugs(at)lists(dot)postgresql(dot)org> |
| Subject: | pg_restore_attribute_stats accepts and persists null_frac=NaN |
| Date: | 2026-09-08 09:53:01 |
| Message-ID: | tencent_16A3D0E291B9D54FC48D30FC166410A02806@qq.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi, I found a potential bug in PostgreSQL's planner statistics restoration function where `pg_restore_attribute_stats()` accepts and persists `null_frac=NaN`, even though `null_frac` represents a fraction of rows and should be a finite value between zero and one inclusive. Description: `pg_restore_attribute_stats()` is used to restore planner statistics for a given attribute. When called with `null_frac` set to `'NaN'::real`, the function returns `true` and writes the value into `pg_statistic.stanullfrac`. Subsequently, `pg_stats.null_frac` contains `NaN`. This violates the expected domain of `null_frac`, which should always be a finite fraction. The reviewed source location is `src/backend/statistics/attribute_stats.c:363-377`, where the input datum appears to be written without any finite/range validation. PostgreSQL version: - PostgreSQL 19beta3 (Docker-based runtime) - Reviewed source snapshot: `f836b688f8dc627ce97760dec5569aa7c064ffe9` - Build relationship: the tested image was not built from that exact source snapshot Environment: - Docker-based PostgreSQL 19beta3 runtime - No special server configuration required beyond the privileges needed to restore planner statistics Steps to Reproduce: ```sql \set VERBOSITY verbose CREATE TABLE attr_nan_test(a int); INSERT INTO attr_nan_test VALUES (1), (2), (3), (NULL); ANALYZE attr_nan_test; SELECT pg_catalog.pg_restore_attribute_stats( 'schemaname', 'public', 'relname', 'attr_nan_test', 'attname', 'a', 'inherited', false, 'null_frac', 'NaN'::real, 'n_distinct', 2::real ); SELECT null_frac FROM pg_stats WHERE tablename = 'attr_nan_test' AND attname = 'a';
For the control, replace 'NaN'::real with 0.25::real.
Actual Result:
The function returns true, and the query returns:
text
null_frac --------- NaN
Expected Result:
The restoration function should reject NaN, Infinity, negative values, and values greater than one for null_frac. It should return false or raise a controlled error without replacing the previous statistic.
Reproduction Frequency:
Positive reproduction: 2/2 on PostgreSQL 19beta3
Negative control: null_frac=0.25 was accepted and stored normally
Additional Observations:
The issue likely stems from the absence of validation on the null_frac input in attribute_stats.c:363-377. While the practical impact is limited because pg_restore_attribute_stats() is intended for privileged statistics restoration, accepting NaN could lead to unexpected planner behavior or confusion when viewing pg_stats.
I searched the public PostgreSQL bug archives and did not find any report specifically addressing null_frac=NaN acceptance in pg_restore_attribute_stats(). Please confirm whether this is considered a bug or an intentional behavior.
♂π≌26218
1991230470(at)qq(dot)com
| From | Date | Subject | |
|---|---|---|---|
| Next Message | ♂π≌26218 | 2026-09-08 09:56:41 | pg_restore_attribute_stats accepts an unsorted range-length histogram |
| Previous Message | ♂π≌26218 | 2026-09-08 09:50:09 | Hunspell AF alias count silently wraps to a smaller value |