public inbox for [email protected]
help / color / mirror / Atom feedFrom: David Rowley <[email protected]>
To: Tom Lane <[email protected]>
Cc: PostgreSQL Developers <[email protected]>
Subject: Re: Small and unlikely overflow hazard in bms_next_member()
Date: Fri, 3 Apr 2026 15:08:58 +1300
Message-ID: <CAApHDvqTUm3Cbgz3ZLV+ad8s_HJHZYrVbrBvGyPQdxCRR-6dvA@mail.gmail.com> (raw)
In-Reply-To: <CAApHDvrvvq_m+nRwjsOpCsFa4EtVtmvJX7zAD=Siria-x6DpbQ@mail.gmail.com>
References: <CAApHDvq0T=iJ0Sf5TNE9yyWwfOeVjmrBt0wSywDnGD9Y4YJQBA@mail.gmail.com>
<[email protected]>
<CAApHDvrvvq_m+nRwjsOpCsFa4EtVtmvJX7zAD=Siria-x6DpbQ@mail.gmail.com>
On Fri, 3 Apr 2026 at 11:12, David Rowley <[email protected]> wrote:
>
> On Thu, 2 Apr 2026 at 17:22, Tom Lane <[email protected]> wrote:
> > I don't think we should add cycles here for this purpose.
>
> I'm not keen on slowing things down for this either. I did do some
> experiments in [1] that sees fewer instructions from using 64-bit
> maths. I might go off and see if there are any wins there that also
> give us the INT_MAX fix. It's not great effort to reward ratio
> though...
The reduction in instructions with the patched version got me curious
to see if it would translate into a performance increase. I tested on
an AMD Zen2 machine, and it's a decent amount faster than master. I
tested with gcc and clang.
I also scanned over the remaining parts of bitmapset.c and didn't find
anywhere else that has overflow risk aside from what you pointed out
in bms_prev_member().
The attached patch contains the benchmark function I added to the
test_bitmapset module. It should apply to master with a bit of noise.
CREATE EXTENSION test_bitmapset;
SELECT
generate_series(1,3) AS run,
bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 AS
bms_next_member_us,
bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 AS
bms_prev_member_us;
master (gcc)
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26473 | 40404
2 | 26218 | 40413
3 | 26209 | 40387
patched (gcc)
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25409 | 29705
2 | 24905 | 29693
3 | 24870 | 29707
Times are in microseconds to do 1 million bms_*_member() loops over
the entire set.
I've also attached the full results I got. I've also included the
results from Chao's version, which does slow things down decently on
clang.
IMO, if we can make bitmapset.c work with INT_MAX members and get a
performance increase, then we should do it.
David
> [1] https://godbolt.org/z/Eh1vzssq7
** GCC **
Master:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26473 | 40404
2 | 26218 | 40413
3 | 26209 | 40387
4 | 26245 | 40521
5 | 26343 | 40559
6 | 26343 | 40580
7 | 26366 | 40639
8 | 26735 | 40467
9 | 26201 | 40334
10 | 26208 | 40343
(10 rows)
Time: 735.560 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26616 | 40392
2 | 26239 | 40374
3 | 26191 | 40374
4 | 26230 | 40370
5 | 26232 | 40380
6 | 26210 | 40377
7 | 26206 | 40395
8 | 26249 | 40431
9 | 26209 | 40374
10 | 26234 | 40432
(10 rows)
Time: 733.927 ms
Patched:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25409 | 29705
2 | 24905 | 29693
3 | 24870 | 29707
4 | 24933 | 29869
5 | 25059 | 29870
6 | 25026 | 29906
7 | 25055 | 29897
8 | 25055 | 29875
9 | 25031 | 29870
10 | 25042 | 29816
(10 rows)
Time: 604.086 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25074 | 29723
2 | 24882 | 29721
3 | 24875 | 29710
4 | 24976 | 29854
5 | 25052 | 29865
6 | 25021 | 29904
7 | 25025 | 29818
8 | 25034 | 29813
9 | 25029 | 29828
10 | 25042 | 29866
(10 rows)
Time: 603.708 ms
Chao's idea:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25677 | 40376
2 | 25271 | 40430
3 | 25263 | 40370
4 | 25301 | 40377
5 | 25357 | 40552
6 | 25394 | 40560
7 | 25412 | 40501
8 | 25401 | 40558
9 | 25381 | 40565
10 | 25370 | 40548
(10 rows)
Time: 725.376 ms
** CLANG **
master:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 29970 | 42551
2 | 29479 | 42765
3 | 29475 | 42805
4 | 29523 | 42825
5 | 29578 | 42898
6 | 29529 | 42997
7 | 29535 | 42985
8 | 29593 | 43021
9 | 29575 | 42976
10 | 29562 | 42967
(10 rows)
Time: 798.131 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 30919 | 42516
2 | 29312 | 42629
3 | 29422 | 42777
4 | 29307 | 42811
5 | 29273 | 42852
6 | 29219 | 42826
7 | 29860 | 43264
8 | 29325 | 42814
9 | 29299 | 42837
10 | 29351 | 42909
(10 rows)
Time: 796.495 ms
Patched:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26741 | 33537
2 | 26094 | 33590
3 | 26087 | 33724
4 | 26276 | 33868
5 | 26346 | 33943
6 | 26433 | 33815
7 | 26324 | 33927
8 | 26274 | 33893
9 | 26350 | 33878
10 | 26304 | 33841
(10 rows)
Time: 661.924 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26502 | 33523
2 | 26173 | 33635
3 | 26188 | 33772
4 | 26290 | 33767
5 | 26325 | 33935
6 | 26326 | 33951
7 | 26335 | 33883
8 | 26571 | 33884
9 | 26472 | 33837
10 | 26277 | 33919
(10 rows)
Time: 662.422 ms
Chao's idea:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 34865 | 42599
2 | 34547 | 42817
3 | 34623 | 42948
4 | 34689 | 42954
5 | 34733 | 42928
6 | 34731 | 42845
7 | 34727 | 42967
8 | 34763 | 43014
9 | 34775 | 42987
10 | 34788 | 43038
(10 rows)
Time: 854.851 ms
Attachments:
[text/plain] benchmark_results.txt (8.0K, 2-benchmark_results.txt)
download | inline:
** GCC **
Master:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26473 | 40404
2 | 26218 | 40413
3 | 26209 | 40387
4 | 26245 | 40521
5 | 26343 | 40559
6 | 26343 | 40580
7 | 26366 | 40639
8 | 26735 | 40467
9 | 26201 | 40334
10 | 26208 | 40343
(10 rows)
Time: 735.560 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26616 | 40392
2 | 26239 | 40374
3 | 26191 | 40374
4 | 26230 | 40370
5 | 26232 | 40380
6 | 26210 | 40377
7 | 26206 | 40395
8 | 26249 | 40431
9 | 26209 | 40374
10 | 26234 | 40432
(10 rows)
Time: 733.927 ms
Patched:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25409 | 29705
2 | 24905 | 29693
3 | 24870 | 29707
4 | 24933 | 29869
5 | 25059 | 29870
6 | 25026 | 29906
7 | 25055 | 29897
8 | 25055 | 29875
9 | 25031 | 29870
10 | 25042 | 29816
(10 rows)
Time: 604.086 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25074 | 29723
2 | 24882 | 29721
3 | 24875 | 29710
4 | 24976 | 29854
5 | 25052 | 29865
6 | 25021 | 29904
7 | 25025 | 29818
8 | 25034 | 29813
9 | 25029 | 29828
10 | 25042 | 29866
(10 rows)
Time: 603.708 ms
Chao's idea:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 25677 | 40376
2 | 25271 | 40430
3 | 25263 | 40370
4 | 25301 | 40377
5 | 25357 | 40552
6 | 25394 | 40560
7 | 25412 | 40501
8 | 25401 | 40558
9 | 25381 | 40565
10 | 25370 | 40548
(10 rows)
Time: 725.376 ms
** CLANG **
master:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 29970 | 42551
2 | 29479 | 42765
3 | 29475 | 42805
4 | 29523 | 42825
5 | 29578 | 42898
6 | 29529 | 42997
7 | 29535 | 42985
8 | 29593 | 43021
9 | 29575 | 42976
10 | 29562 | 42967
(10 rows)
Time: 798.131 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 30919 | 42516
2 | 29312 | 42629
3 | 29422 | 42777
4 | 29307 | 42811
5 | 29273 | 42852
6 | 29219 | 42826
7 | 29860 | 43264
8 | 29325 | 42814
9 | 29299 | 42837
10 | 29351 | 42909
(10 rows)
Time: 796.495 ms
Patched:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26741 | 33537
2 | 26094 | 33590
3 | 26087 | 33724
4 | 26276 | 33868
5 | 26346 | 33943
6 | 26433 | 33815
7 | 26324 | 33927
8 | 26274 | 33893
9 | 26350 | 33878
10 | 26304 | 33841
(10 rows)
Time: 661.924 ms
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 26502 | 33523
2 | 26173 | 33635
3 | 26188 | 33772
4 | 26290 | 33767
5 | 26325 | 33935
6 | 26326 | 33951
7 | 26335 | 33883
8 | 26571 | 33884
9 | 26472 | 33837
10 | 26277 | 33919
(10 rows)
Time: 662.422 ms
Chao's idea:
postgres=# select generate_series(1,10) run,bench_bms_next_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_next_member_us, bench_bms_prev_member('(b 1 2 3 4 5 6 7 8 64)', 1000000)/1000 as bms_prev_member_us;
run | bms_next_member_us | bms_prev_member_us
-----+--------------------+--------------------
1 | 34865 | 42599
2 | 34547 | 42817
3 | 34623 | 42948
4 | 34689 | 42954
5 | 34733 | 42928
6 | 34731 | 42845
7 | 34727 | 42967
8 | 34763 | 43014
9 | 34775 | 42987
10 | 34788 | 43038
(10 rows)
Time: 854.851 ms
[application/octet-stream] bms_fixes.patch (5.0K, 3-bms_fixes.patch)
download | inline diff:
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index ac3e763de43..46b4ca4b0f1 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -1444,6 +1444,7 @@ bms_join(Bitmapset *a, Bitmapset *b)
int
bms_next_member(const Bitmapset *a, int prevbit)
{
+ int64 currbit;
int nwords;
bitmapword mask;
@@ -1452,13 +1453,13 @@ bms_next_member(const Bitmapset *a, int prevbit)
if (a == NULL)
return -2;
nwords = a->nwords;
- prevbit++;
- mask = (~(bitmapword) 0) << BITNUM(prevbit);
- for (int wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
+ currbit = (int64) prevbit + 1;
+ mask = (~(bitmapword) 0) << BITNUM(currbit);
+ for (int wordnum = WORDNUM(currbit); wordnum < nwords; wordnum++)
{
bitmapword w = a->words[wordnum];
- /* ignore bits before prevbit */
+ /* ignore bits before currbit */
w &= mask;
if (w != 0)
@@ -1505,6 +1506,7 @@ int
bms_prev_member(const Bitmapset *a, int prevbit)
{
int ushiftbits;
+ uint32 currbit;
bitmapword mask;
Assert(bms_is_valid_set(a));
@@ -1517,18 +1519,18 @@ bms_prev_member(const Bitmapset *a, int prevbit)
return -2;
/* Validate callers didn't give us something out of range */
- Assert(prevbit <= a->nwords * BITS_PER_BITMAPWORD);
+ Assert(prevbit <= (int64) a->nwords * BITS_PER_BITMAPWORD);
Assert(prevbit >= -1);
/* transform -1 to the highest possible bit we could have set */
if (prevbit == -1)
- prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
+ currbit = (uint32) a->nwords * BITS_PER_BITMAPWORD - 1;
else
- prevbit--;
+ currbit = prevbit - 1;
- ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(prevbit) + 1);
+ ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(currbit) + 1);
mask = (~(bitmapword) 0) >> ushiftbits;
- for (int wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
+ for (int wordnum = WORDNUM(currbit); wordnum >= 0; wordnum--)
{
bitmapword w = a->words[wordnum];
diff --git a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
index 6668bcef9a9..d6c0f739e13 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
+++ b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
@@ -3,6 +3,15 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_bitmapset" to load this file. \quit
+-- Benchmark functions
+CREATE FUNCTION bench_bms_next_member(text, integer)
+RETURNS bigint
+AS 'MODULE_PATHNAME' LANGUAGE C;
+
+CREATE FUNCTION bench_bms_prev_member(text, integer)
+RETURNS bigint
+AS 'MODULE_PATHNAME' LANGUAGE C;
+
-- Bitmapset API functions
CREATE FUNCTION test_bms_make_singleton(integer)
RETURNS text STRICT
diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c
index 4fe22ee64d2..990347a0f22 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset.c
+++ b/src/test/modules/test_bitmapset/test_bitmapset.c
@@ -17,6 +17,7 @@
#include "postgres.h"
#include <stddef.h>
+#include <time.h>
#include "catalog/pg_type.h"
#include "common/pg_prng.h"
#include "utils/array.h"
@@ -27,8 +28,13 @@
#include "utils/builtins.h"
#include "utils/timestamp.h"
+
PG_MODULE_MAGIC;
+/* Benchmark functions */
+PG_FUNCTION_INFO_V1(bench_bms_next_member);
+PG_FUNCTION_INFO_V1(bench_bms_prev_member);
+
/* Bitmapset API functions in order of appearance in bitmapset.c */
PG_FUNCTION_INFO_V1(test_bms_make_singleton);
PG_FUNCTION_INFO_V1(test_bms_add_member);
@@ -105,6 +111,73 @@ PG_FUNCTION_INFO_V1(test_random_shift_operations);
#define PG_RETURN_BITMAPSET_AS_TEXT(bms) \
PG_RETURN_TEXT_P(BITMAPSET_TO_TEXT(bms))
+#define NANOSEC_PER_SEC 1000000000
+
+int64 get_clock_diff(struct timespec* t1, struct timespec* t2);
+
+int64
+get_clock_diff(struct timespec* t1, struct timespec* t2)
+{
+ int64_t nanosec = (t1->tv_sec - t2->tv_sec) * NANOSEC_PER_SEC;
+ nanosec += (t1->tv_nsec - t2->tv_nsec);
+
+ return nanosec;
+}
+
+Datum
+bench_bms_next_member(PG_FUNCTION_ARGS)
+{
+ Bitmapset* bms = PG_ARG_GETBITMAPSET(0);
+ int32 loops = PG_GETARG_INT32(1);
+
+ struct timespec start, end;
+ int64 nanoseconds;
+ int64 counter = 0;
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
+
+ for (int i = 0; i < loops; i++)
+ {
+ int m = -1;
+ while ((m = bms_next_member(bms, m)) >= 0)
+ {
+ counter++;
+ }
+ }
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
+ nanoseconds = get_clock_diff(&end, &start);
+
+ PG_RETURN_INT64(nanoseconds);
+}
+
+Datum
+bench_bms_prev_member(PG_FUNCTION_ARGS)
+{
+ Bitmapset* bms = PG_ARG_GETBITMAPSET(0);
+ int32 loops = PG_GETARG_INT32(1);
+
+ struct timespec start, end;
+ int64 nanoseconds;
+ int64 counter = 0;
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
+
+ for (int i = 0; i < loops; i++)
+ {
+ int m = -1;
+ while ((m = bms_prev_member(bms, m)) >= 0)
+ {
+ counter++;
+ }
+ }
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
+ nanoseconds = get_clock_diff(&end, &start);
+
+ PG_RETURN_INT64(nanoseconds);
+}
+
/*
* Individual test functions for each bitmapset API function
*
view thread (17+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected]
Subject: Re: Small and unlikely overflow hazard in bms_next_member()
In-Reply-To: <CAApHDvqTUm3Cbgz3ZLV+ad8s_HJHZYrVbrBvGyPQdxCRR-6dvA@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox