@@ -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 isbase struct size , plus one base struct for each items,
165
- * including number of items for each.
164
+ * Base size issize 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
{