ndistinct-valgrind-fix.patch
text/x-diff
Filename: ndistinct-valgrind-fix.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/statistics/mvdistinct.c | 24 | 11 |
diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c index 5df4e29..acc2d7e 100644 --- a/src/backend/statistics/mvdistinct.c +++ b/src/backend/statistics/mvdistinct.c @@ -161,10 +161,10 @@ statext_ndistinct_serialize(MVNDistinct *ndistinct) Assert(ndistinct->type == STATS_NDISTINCT_TYPE_BASIC); /* - * Base size is base struct size, plus one base struct for each items, - * including number of items for each. + * Base size is size of scalar fields in the struct, plus one base struct + * for each item, including number of items for each. */ - len = VARHDRSZ + offsetof(MVNDistinct, items) + + len = VARHDRSZ + (3 * sizeof(uint32)) + ndistinct->nitems * (offsetof(MVNDistinctItem, attrs) + sizeof(int)); /* and also include space for the actual attribute numbers */ @@ -182,9 +182,15 @@ statext_ndistinct_serialize(MVNDistinct *ndistinct) tmp = VARDATA(output); - /* Store the base struct values */ - memcpy(tmp, ndistinct, offsetof(MVNDistinct, items)); - tmp += offsetof(MVNDistinct, items); + /* Store the base struct values (magic, type, nitems) */ + memcpy(tmp, &ndistinct->magic, sizeof(uint32)); + tmp += sizeof(uint32); + + memcpy(tmp, &ndistinct->type, sizeof(uint32)); + tmp += sizeof(uint32); + + memcpy(tmp, &ndistinct->nitems, sizeof(uint32)); + tmp += sizeof(uint32); /* * store number of attributes and attribute numbers for each ndistinct @@ -231,9 +237,10 @@ statext_ndistinct_deserialize(bytea *data) if (data == NULL) return NULL; - if (VARSIZE_ANY_EXHDR(data) < offsetof(MVNDistinct, items)) + /* we expect at least the basic fields of MVNDistinct struct */ + if (VARSIZE_ANY_EXHDR(data) < (3 * sizeof(uint32))) elog(ERROR, "invalid MVNDistinct size %ld (expected at least %ld)", - VARSIZE_ANY_EXHDR(data), offsetof(MVNDistinct, items)); + VARSIZE_ANY_EXHDR(data), 3 * sizeof(uint32)); /* read the MVNDistinct header */ ndistinct = (MVNDistinct *) palloc(sizeof(MVNDistinct)); @@ -241,18 +248,24 @@ statext_ndistinct_deserialize(bytea *data) /* initialize pointer to the data part (skip the varlena header) */ tmp = VARDATA_ANY(data); - /* get the header and perform basic sanity checks */ - memcpy(ndistinct, tmp, offsetof(MVNDistinct, items)); - tmp += offsetof(MVNDistinct, items); + /* get the header fields and perform basic sanity checks */ + memcpy(&ndistinct->magic, tmp, sizeof(uint32)); + tmp += sizeof(uint32); if (ndistinct->magic != STATS_NDISTINCT_MAGIC) elog(ERROR, "invalid ndistinct magic %d (expected %d)", ndistinct->magic, STATS_NDISTINCT_MAGIC); + memcpy(&ndistinct->type, tmp, sizeof(uint32)); + tmp += sizeof(uint32); + if (ndistinct->type != STATS_NDISTINCT_TYPE_BASIC) elog(ERROR, "invalid ndistinct type %d (expected %d)", ndistinct->type, STATS_NDISTINCT_TYPE_BASIC); + memcpy(&ndistinct->nitems, tmp, sizeof(uint32)); + tmp += sizeof(uint32); + Assert(ndistinct->nitems > 0); /* what minimum bytea size do we expect for those parameters */