Skip to content

Commit 2841364

Browse files
committed
fix #45, avoid inconsistent results for incorrectly serialized bitmaps when using roaring_buffer_reader
1 parent 7a0560d commit 2841364

File tree

3 files changed

+45
-19
lines changed

3 files changed

+45
-19
lines changed

expected/roaringbitmap.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,3 +2671,11 @@ SELECT rb_and_cardinality('{100373,1829130,1861002,1975442,2353213,2456403}','{2
26712671
1
26722672
(1 row)
26732673

2674+
-- bugfix #45: rb_to_array and rb_min exhibits inconsistent results in a malformed serialize input
2675+
select rb_to_array('\x3a300000010000000000000000000000000000000000000000000000000000000000000000000000000000000008'::roaringbitmap),
2676+
rb_min('\x3a300000010000000000000000000000000000000000000000000000000000000000000000000000000000000008'::roaringbitmap);
2677+
rb_to_array | rb_min
2678+
-------------+--------
2679+
{0} | 0
2680+
(1 row)
2681+

roaringbitmap.c

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
typedef enum
1212
{
13-
RBITMAP_OUTPUT_ARRAY, /* output as int array */
14-
RBITMAP_OUTPUT_BYTEA /* output as bytea */
13+
RBITMAP_OUTPUT_ARRAY, /* output as int array */
14+
RBITMAP_OUTPUT_BYTEA /* output as bytea */
1515
}RBITMAPOutputFormat;
1616

1717
static const struct config_enum_entry output_format_options[] =
@@ -21,7 +21,7 @@ static const struct config_enum_entry output_format_options[] =
2121
{NULL, 0, false}
2222
};
2323

24-
static int rbitmap_output_format = RBITMAP_OUTPUT_BYTEA; /* output format */
24+
static int rbitmap_output_format = RBITMAP_OUTPUT_BYTEA; /* output format */
2525

2626
static roaring_memory_t rb_memory_hook = {
2727
.malloc = palloc,
@@ -32,25 +32,25 @@ static roaring_memory_t rb_memory_hook = {
3232
.aligned_free = pg_aligned_free,
3333
};
3434

35-
void _PG_init(void);
35+
void _PG_init(void);
3636
/*
3737
* Module load callback
3838
*/
3939
void
4040
_PG_init(void)
4141
{
42-
/* Define custom GUC variables. */
43-
DefineCustomEnumVariable("roaringbitmap.output_format",
44-
"Selects output format of roaringbitmap.",
45-
NULL,
46-
&rbitmap_output_format,
47-
RBITMAP_OUTPUT_BYTEA,
48-
output_format_options,
49-
PGC_USERSET,
50-
0,
51-
NULL,
52-
NULL,
53-
NULL);
42+
/* Define custom GUC variables. */
43+
DefineCustomEnumVariable("roaringbitmap.output_format",
44+
"Selects output format of roaringbitmap.",
45+
NULL,
46+
&rbitmap_output_format,
47+
RBITMAP_OUTPUT_BYTEA,
48+
output_format_options,
49+
PGC_USERSET,
50+
0,
51+
NULL,
52+
NULL,
53+
NULL);
5454
roaring_init_memory_hook(rb_memory_hook);
5555
}
5656

@@ -99,15 +99,22 @@ Datum
9999
rb_from_bytea(PG_FUNCTION_ARGS) {
100100
bytea *serializedbytes = PG_GETARG_BYTEA_P(0);
101101
roaring_bitmap_t *r1;
102+
size_t expectedsize;
103+
bytea *serializedbytes2;
102104

103105
r1 = roaring_bitmap_portable_deserialize_safe(VARDATA(serializedbytes), VARSIZE(serializedbytes) - VARHDRSZ);
104106
if (!r1)
105107
ereport(ERROR,
106108
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
107109
errmsg("bitmap format is error")));
108110

111+
expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
112+
serializedbytes2 = (bytea *) palloc(VARHDRSZ + expectedsize);
113+
roaring_bitmap_portable_serialize(r1, VARDATA(serializedbytes2));
109114
roaring_bitmap_free(r1);
110-
PG_RETURN_BYTEA_P(serializedbytes);
115+
116+
SET_VARSIZE(serializedbytes2, VARHDRSZ + expectedsize);
117+
PG_RETURN_BYTEA_P(serializedbytes2);
111118
}
112119

113120

@@ -136,12 +143,17 @@ roaringbitmap_in(PG_FUNCTION_ARGS) {
136143
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
137144
errmsg("bitmap format is error")));
138145

146+
expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
147+
serializedbytes = (bytea *) palloc(VARHDRSZ + expectedsize);
148+
roaring_bitmap_portable_serialize(r1, VARDATA(serializedbytes));
139149
roaring_bitmap_free(r1);
140-
return dd;
150+
151+
SET_VARSIZE(serializedbytes, VARHDRSZ + expectedsize);
152+
PG_RETURN_BYTEA_P(serializedbytes);
141153
}
142154
/* else int array input */
143155

144-
/* Find the head char '{' */
156+
/* Find the head char '{' */
145157
while (*ptr && isspace((unsigned char) *ptr))
146158
ptr++;
147159
if (*ptr !='{')

sql/roaringbitmap.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,9 @@ order by id limit 10;
610610
-- bugfix #22
611611
SELECT '{100373,1829130,1861002,1975442,2353213,2456403}'::roaringbitmap & '{2353213}'::roaringbitmap;
612612
SELECT rb_and_cardinality('{100373,1829130,1861002,1975442,2353213,2456403}','{2353213}');
613+
614+
-- bugfix #45: rb_to_array and rb_min exhibits inconsistent results in a malformed serialize input
615+
select rb_to_array('\x3a300000010000000000000000000000000000000000000000000000000000000000000000000000000000000008'::roaringbitmap),
616+
rb_min('\x3a300000010000000000000000000000000000000000000000000000000000000000000000000000000000000008'::roaringbitmap);
617+
618+

0 commit comments

Comments
 (0)