@@ -161,10 +161,10 @@ statext_ndistinct_serialize(MVNDistinct *ndistinct)
161
161
Assert (ndistinct -> type == STATS_NDISTINCT_TYPE_BASIC );
162
162
163
163
/*
164
- * Base size is base struct size , plus one base struct for each items,
165
- * including number of items for each.
164
+ * Base size is size of scalar fields in the struct , plus one base struct
165
+ * for each item, including number of items for each.
166
166
*/
167
- len = VARHDRSZ + offsetof( MVNDistinct , items ) +
167
+ len = VARHDRSZ + SizeOfMVNDistinct +
168
168
ndistinct -> nitems * (offsetof(MVNDistinctItem , attrs ) + sizeof (int ));
169
169
170
170
/* and also include space for the actual attribute numbers */
@@ -182,9 +182,13 @@ statext_ndistinct_serialize(MVNDistinct *ndistinct)
182
182
183
183
tmp = VARDATA (output );
184
184
185
- /* Store the base struct values */
186
- memcpy (tmp , ndistinct , offsetof(MVNDistinct , items ));
187
- tmp += offsetof(MVNDistinct , items );
185
+ /* Store the base struct values (magic, type, nitems) */
186
+ memcpy (tmp , & ndistinct -> magic , sizeof (uint32 ));
187
+ tmp += sizeof (uint32 );
188
+ memcpy (tmp , & ndistinct -> type , sizeof (uint32 ));
189
+ tmp += sizeof (uint32 );
190
+ memcpy (tmp , & ndistinct -> nitems , sizeof (uint32 ));
191
+ tmp += sizeof (uint32 );
188
192
189
193
/*
190
194
* store number of attributes and attribute numbers for each ndistinct
@@ -224,49 +228,64 @@ MVNDistinct *
224
228
statext_ndistinct_deserialize (bytea * data )
225
229
{
226
230
int i ;
227
- Size expected_size ;
231
+ Size minimum_size ;
232
+ MVNDistinct ndist ;
228
233
MVNDistinct * ndistinct ;
229
234
char * tmp ;
230
235
231
236
if (data == NULL )
232
237
return NULL ;
233
238
234
- if (VARSIZE_ANY_EXHDR (data ) < offsetof(MVNDistinct , items ))
239
+ /* we expect at least the basic fields of MVNDistinct struct */
240
+ if (VARSIZE_ANY_EXHDR (data ) < SizeOfMVNDistinct )
235
241
elog (ERROR , "invalid MVNDistinct size %ld (expected at least %ld)" ,
236
- VARSIZE_ANY_EXHDR (data ), offsetof(MVNDistinct , items ));
237
-
238
- /* read the MVNDistinct header */
239
- ndistinct = (MVNDistinct * ) palloc (sizeof (MVNDistinct ));
242
+ VARSIZE_ANY_EXHDR (data ), SizeOfMVNDistinct );
240
243
241
244
/* initialize pointer to the data part (skip the varlena header) */
242
245
tmp = VARDATA_ANY (data );
243
246
244
- /* get the header and perform basic sanity checks */
245
- memcpy (ndistinct , tmp , offsetof(MVNDistinct , items ));
246
- tmp += offsetof(MVNDistinct , items );
247
-
248
- if (ndistinct -> magic != STATS_NDISTINCT_MAGIC )
249
- elog (ERROR , "invalid ndistinct magic %d (expected %d)" ,
250
- ndistinct -> magic , STATS_NDISTINCT_MAGIC );
251
-
252
- if (ndistinct -> type != STATS_NDISTINCT_TYPE_BASIC )
253
- elog (ERROR , "invalid ndistinct type %d (expected %d)" ,
254
- ndistinct -> type , STATS_NDISTINCT_TYPE_BASIC );
255
-
256
- Assert (ndistinct -> nitems > 0 );
247
+ /* read the header fields and perform basic sanity checks */
248
+ memcpy (& ndist .magic , tmp , sizeof (uint32 ));
249
+ tmp += sizeof (uint32 );
250
+ memcpy (& ndist .type , tmp , sizeof (uint32 ));
251
+ tmp += sizeof (uint32 );
252
+ memcpy (& ndist .nitems , tmp , sizeof (uint32 ));
253
+ tmp += sizeof (uint32 );
254
+
255
+ if (ndist .magic != STATS_NDISTINCT_MAGIC )
256
+ ereport (ERROR ,
257
+ (errcode (ERRCODE_DATA_CORRUPTED ),
258
+ errmsg ("invalid ndistinct magic %08x (expected %08x)" ,
259
+ ndist .magic , STATS_NDISTINCT_MAGIC )));
260
+ if (ndist .type != STATS_NDISTINCT_TYPE_BASIC )
261
+ ereport (ERROR ,
262
+ (errcode (ERRCODE_DATA_CORRUPTED ),
263
+ errmsg ("invalid ndistinct type %d (expected %d)" ,
264
+ ndist .type , STATS_NDISTINCT_TYPE_BASIC )));
265
+ if (ndist .nitems == 0 )
266
+ ereport (ERROR ,
267
+ (errcode (ERRCODE_DATA_CORRUPTED ),
268
+ errmsg ("invalid zero-length item array in MVNDistinct" )));
257
269
258
270
/* what minimum bytea size do we expect for those parameters */
259
- expected_size = offsetof(MVNDistinct , items ) +
260
- ndistinct -> nitems * (offsetof(MVNDistinctItem , attrs ) +
261
- sizeof (AttrNumber ) * 2 );
271
+ minimum_size = (SizeOfMVNDistinct +
272
+ ndist .nitems * (SizeOfMVNDistinctItem +
273
+ sizeof (AttrNumber ) * 2 ));
274
+ if (VARSIZE_ANY_EXHDR (data ) < minimum_size )
275
+ ereport (ERROR ,
276
+ (errcode (ERRCODE_DATA_CORRUPTED ),
277
+ errmsg ("invalid MVNDistinct size %ld (expected at least %ld)" ,
278
+ VARSIZE_ANY_EXHDR (data ), minimum_size )));
262
279
263
- if (VARSIZE_ANY_EXHDR (data ) < expected_size )
264
- elog (ERROR , "invalid dependencies size %ld (expected at least %ld)" ,
265
- VARSIZE_ANY_EXHDR (data ), expected_size );
266
-
267
- /* allocate space for the ndistinct items */
268
- ndistinct = repalloc (ndistinct , offsetof(MVNDistinct , items ) +
269
- (ndistinct -> nitems * sizeof (MVNDistinctItem )));
280
+ /*
281
+ * Allocate space for the ndistinct items (no space for each item's attnos:
282
+ * those live in bitmapsets allocated separately)
283
+ */
284
+ ndistinct = palloc0 (MAXALIGN (SizeOfMVNDistinct ) +
285
+ (ndist .nitems * sizeof (MVNDistinctItem )));
286
+ ndistinct -> magic = ndist .magic ;
287
+ ndistinct -> type = ndist .type ;
288
+ ndistinct -> nitems = ndist .nitems ;
270
289
271
290
for (i = 0 ; i < ndistinct -> nitems ; i ++ )
272
291
{
0 commit comments