pg.ddx.io pgsql-hackers@postgresql.org mailing list archivehelp / color / mirror / Atom feed
[PATCH] Reject nonpositive Bloom filter element estimates 2+ messages / 2 participants [nested] [flat]
* [PATCH] Reject nonpositive Bloom filter element estimates @ 2026-09-18 10:31 CharSyam <charsyam@gmail.com> 0 siblings, 1 reply; 2+ messages in thread From: CharSyam @ 2026-09-18 10:31 UTC (permalink / raw) To: pgsql-hackers <pgsql-hackers@lists.postgresql.org> Hi, Hackers. bloom_create() currently accepts a zero total_elems estimate. This causes optimal_k() to divide by zero and then convert infinity to int, which is undefined behavior. The attached patch rejects nonpositive estimates before the calculation. It also performs the bitset size multiplication as unsigned arithmetic to avoid signed overflow for very large positive estimates, and adds a regression test for the zero case. The affected source and test module compile successfully, and git diff --check passes. Regards, DaeMyung Kang Attachments: [application/octet-stream] v1-0001-Reject-nonpositive-Bloom-filter-element-estimates.patch (2.3K, ../../CAMrLSE671yN2u4zeo2pnUY2rm=arYfb0rVSr5v+9m9t9vL802w@mail.gmail.com/2-v1-0001-Reject-nonpositive-Bloom-filter-element-estimates.patch) download | inline diff: diff --git a/src/backend/lib/bloomfilter.c b/src/backend/lib/bloomfilter.c index 73b3768a172..b24c932ab8f 100644 --- a/src/backend/lib/bloomfilter.c +++ b/src/backend/lib/bloomfilter.c @@ -91,6 +91,9 @@ bloom_create(int64 total_elems, int bloom_work_mem, uint64 seed) uint64 bitset_bytes; uint64 bitset_bits; + if (total_elems <= 0) + elog(ERROR, "total number of elements must be greater than zero"); + /* * Aim for two bytes per element; this is sufficient to get a false * positive rate below 1%, independent of the size of the bitset or total @@ -98,7 +101,8 @@ bloom_create(int64 total_elems, int bloom_work_mem, uint64 seed) * the next lowest power of two turns out to be a significant drop, the * false positive rate still won't exceed 2% in almost all cases. */ - bitset_bytes = Min(bloom_work_mem * UINT64CONST(1024), total_elems * 2); + bitset_bytes = Min(bloom_work_mem * UINT64CONST(1024), + (uint64) total_elems * 2); bitset_bytes = Max(1024 * 1024, bitset_bytes); /* diff --git a/src/test/modules/test_bloomfilter/expected/test_bloomfilter.out b/src/test/modules/test_bloomfilter/expected/test_bloomfilter.out index 21c068867d6..137eb4f2140 100644 --- a/src/test/modules/test_bloomfilter/expected/test_bloomfilter.out +++ b/src/test/modules/test_bloomfilter/expected/test_bloomfilter.out @@ -9,6 +9,12 @@ SELECT test_bloomfilter(power => 23, (1 row) +-- A Bloom filter cannot be sized for an empty set. +SELECT test_bloomfilter(power => 23, + nelements => 0, + seed => 0, + tests => 1); +ERROR: total number of elements must be greater than zero -- Equivalent "10 bits per element" tests for all possible bitset sizes: -- -- SELECT test_bloomfilter(24, 1677722) diff --git a/src/test/modules/test_bloomfilter/sql/test_bloomfilter.sql b/src/test/modules/test_bloomfilter/sql/test_bloomfilter.sql index 9ec159ce404..5a94c95eb2a 100644 --- a/src/test/modules/test_bloomfilter/sql/test_bloomfilter.sql +++ b/src/test/modules/test_bloomfilter/sql/test_bloomfilter.sql @@ -6,6 +6,12 @@ SELECT test_bloomfilter(power => 23, seed => -1, tests => 1); +-- A Bloom filter cannot be sized for an empty set. +SELECT test_bloomfilter(power => 23, + nelements => 0, + seed => 0, + tests => 1); + -- Equivalent "10 bits per element" tests for all possible bitset sizes: -- -- SELECT test_bloomfilter(24, 1677722) ^ permalink raw reply [nested|flat] 2+ messages in thread
* Re: [PATCH] Reject nonpositive Bloom filter element estimates @ 2026-09-18 14:41 Nathan Bossart <nathandbossart@gmail.com> parent: CharSyam <charsyam@gmail.com> 0 siblings, 0 replies; 2+ messages in thread From: Nathan Bossart @ 2026-09-18 14:41 UTC (permalink / raw) To: CharSyam <charsyam@gmail.com>; +Cc: pgsql-hackers <pgsql-hackers@lists.postgresql.org> On Fri, Sep 18, 2026 at 07:31:04PM +0900, CharSyam wrote: > bloom_create() currently accepts a zero total_elems estimate. This > causes optimal_k() to divide by zero and then convert infinity to int, > which is undefined behavior. > > The attached patch rejects nonpositive estimates before the calculation. For backend functions like this, I don't see much value in checking the arguments like this. It seems highly unlikely that any caller will provide a total_elems setting of 0. Maybe an assertion would be more appropriate, but IMHO we can still do without it. > It also performs the bitset size multiplication as unsigned arithmetic > to avoid signed overflow for very large positive estimates, and adds a > regression test for the zero case. Again, it seems highly unlikely that any caller will provide a total_elems value even close to 4.6 quintillion. -- nathan ^ permalink raw reply [nested|flat] 2+ messages in thread
end of thread, other threads:[~2026-09-18 14:41 UTC | newest] Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2026-09-18 10:31 [PATCH] Reject nonpositive Bloom filter element estimates CharSyam <charsyam@gmail.com> 2026-09-18 14:41 ` Nathan Bossart <nathandbossart@gmail.com>
This inbox is served by DDX for PostgreSQL; see mirroring instructions for how to clone and mirror all data and code used for this inbox