From 09d8d110a604e52216102e73fb8475b7aa88f1d1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 20 Feb 2015 00:11:42 -0500 Subject: [PATCH] Use FLEXIBLE_ARRAY_MEMBER in a bunch more places. Replace some bogus "x[1]" declarations with "x[FLEXIBLE_ARRAY_MEMBER]". Aside from being more self-documenting, this should help prevent bogus warnings from static code analyzers and perhaps compiler misoptimizations. This patch is just a down payment on eliminating the whole problem, but it gets rid of a lot of easy-to-fix cases. Note that the main problem with doing this is that one must no longer rely on computing sizeof(the containing struct), since the result would be compiler-dependent. Instead use offsetof(struct, lastfield). Autoconf also warns against spelling that offsetof(struct, lastfield[0]). Michael Paquier, review and additional fixes by me. --- contrib/cube/cubedata.h | 15 +++++++------- contrib/intarray/_int.h | 4 ++-- contrib/ltree/ltree.h | 14 ++++++------- contrib/pageinspect/rawpage.c | 2 +- contrib/pg_trgm/trgm.h | 2 +- src/backend/catalog/namespace.c | 13 ++++++------ src/backend/commands/prepare.c | 5 ++--- src/backend/executor/functions.c | 6 +++--- src/backend/executor/spi.c | 5 ++--- src/backend/nodes/params.c | 5 ++--- src/backend/postmaster/syslogger.c | 4 ++-- src/backend/tcop/postgres.c | 5 ++--- src/backend/utils/adt/geo_ops.c | 22 ++++++++++----------- src/backend/utils/cache/catcache.c | 2 +- src/bin/pg_dump/dumputils.c | 3 +-- src/bin/pg_dump/dumputils.h | 2 +- src/include/access/gin_private.h | 4 ++-- src/include/access/gist_private.h | 7 ++++--- src/include/access/heapam_xlog.h | 2 +- src/include/access/spgist_private.h | 10 +++++----- src/include/access/xact.h | 8 ++++---- src/include/c.h | 8 ++++---- src/include/catalog/namespace.h | 4 ++-- src/include/commands/dbcommands.h | 15 -------------- src/include/commands/tablespace.h | 2 +- src/include/executor/hashjoin.h | 2 +- src/include/nodes/bitmapset.h | 4 ++-- src/include/nodes/params.h | 2 +- src/include/nodes/tidbitmap.h | 4 ++-- src/include/postgres.h | 8 ++++---- src/include/postmaster/syslogger.h | 2 +- src/include/replication/walsender_private.h | 4 ++-- src/include/storage/bufpage.h | 2 +- src/include/storage/fsm_internals.h | 2 +- src/include/storage/standby.h | 4 ++-- src/include/tsearch/dicts/regis.h | 2 +- src/include/tsearch/dicts/spell.h | 6 +++--- src/include/tsearch/ts_type.h | 6 +++--- src/include/utils/catcache.h | 4 ++-- src/include/utils/datetime.h | 4 ++-- src/include/utils/geo_decls.h | 4 ++-- src/include/utils/jsonb.h | 2 +- src/include/utils/relmapper.h | 2 +- src/include/utils/varbit.h | 3 ++- 44 files changed, 109 insertions(+), 127 deletions(-) diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h index 5d44e11081..719e43d421 100644 --- a/contrib/cube/cubedata.h +++ b/contrib/cube/cubedata.h @@ -23,11 +23,10 @@ typedef struct NDBOX unsigned int header; /* - * Variable length array. The lower left coordinates for each dimension - * come first, followed by upper right coordinates unless the point flag - * is set. + * The lower left coordinates for each dimension come first, followed by + * upper right coordinates unless the point flag is set. */ - double x[1]; + double x[FLEXIBLE_ARRAY_MEMBER]; } NDBOX; #define POINT_BIT 0x80000000 @@ -41,9 +40,9 @@ typedef struct NDBOX #define LL_COORD(cube, i) ( (cube)->x[i] ) #define UR_COORD(cube, i) ( IS_POINT(cube) ? (cube)->x[i] : (cube)->x[(i) + DIM(cube)] ) -#define POINT_SIZE(_dim) (offsetof(NDBOX, x[0]) + sizeof(double)*(_dim)) -#define CUBE_SIZE(_dim) (offsetof(NDBOX, x[0]) + sizeof(double)*(_dim)*2) +#define POINT_SIZE(_dim) (offsetof(NDBOX, x) + sizeof(double)*(_dim)) +#define CUBE_SIZE(_dim) (offsetof(NDBOX, x) + sizeof(double)*(_dim)*2) -#define DatumGetNDBOX(x) ((NDBOX*)DatumGetPointer(x)) -#define PG_GETARG_NDBOX(x) DatumGetNDBOX( PG_DETOAST_DATUM(PG_GETARG_DATUM(x)) ) +#define DatumGetNDBOX(x) ((NDBOX *) PG_DETOAST_DATUM(x)) +#define PG_GETARG_NDBOX(x) DatumGetNDBOX(PG_GETARG_DATUM(x)) #define PG_RETURN_NDBOX(x) PG_RETURN_POINTER(x) diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h index 7f93206e89..d524f0fed5 100644 --- a/contrib/intarray/_int.h +++ b/contrib/intarray/_int.h @@ -73,7 +73,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 flag; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } GISTTYPE; #define ALLISTRUE 0x04 @@ -133,7 +133,7 @@ typedef struct QUERYTYPE { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 size; /* number of ITEMs */ - ITEM items[1]; /* variable length array */ + ITEM items[FLEXIBLE_ARRAY_MEMBER]; } QUERYTYPE; #define HDRSIZEQT offsetof(QUERYTYPE, items) diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h index 1b1305b483..c604357dbf 100644 --- a/contrib/ltree/ltree.h +++ b/contrib/ltree/ltree.h @@ -10,7 +10,7 @@ typedef struct { uint16 len; - char name[1]; + char name[FLEXIBLE_ARRAY_MEMBER]; } ltree_level; #define LEVEL_HDRSIZE (offsetof(ltree_level,name)) @@ -20,7 +20,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ uint16 numlevel; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } ltree; #define LTREE_HDRSIZE MAXALIGN( offsetof(ltree, data) ) @@ -34,7 +34,7 @@ typedef struct int32 val; uint16 len; uint8 flag; - char name[1]; + char name[FLEXIBLE_ARRAY_MEMBER]; } lquery_variant; #define LVAR_HDRSIZE MAXALIGN(offsetof(lquery_variant, name)) @@ -51,7 +51,7 @@ typedef struct uint16 numvar; uint16 low; uint16 high; - char variants[1]; + char variants[FLEXIBLE_ARRAY_MEMBER]; } lquery_level; #define LQL_HDRSIZE MAXALIGN( offsetof(lquery_level,variants) ) @@ -72,7 +72,7 @@ typedef struct uint16 numlevel; uint16 firstgood; uint16 flag; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } lquery; #define LQUERY_HDRSIZE MAXALIGN( offsetof(lquery, data) ) @@ -107,7 +107,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 size; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } ltxtquery; #define HDRSIZEQT MAXALIGN(VARHDRSZ + sizeof(int32)) @@ -208,7 +208,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ uint32 flag; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } ltree_gist; #define LTG_ONENODE 0x01 diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index 1dada098af..38c136f987 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -192,7 +192,7 @@ page_header(PG_FUNCTION_ARGS) * Check that enough data was supplied, so that we don't try to access * fields outside the supplied buffer. */ - if (raw_page_size < sizeof(PageHeaderData)) + if (raw_page_size < SizeOfPageHeaderData) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("input page too small (%d bytes)", raw_page_size))); diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h index ed649b8dcc..f030558088 100644 --- a/contrib/pg_trgm/trgm.h +++ b/contrib/pg_trgm/trgm.h @@ -63,7 +63,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ uint8 flag; - char data[1]; + char data[FLEXIBLE_ARRAY_MEMBER]; } TRGM; #define TRGMHDRSIZE (VARHDRSZ + sizeof(uint8)) diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index bfb4fdcc66..1af977cb1d 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -261,9 +261,9 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, * with the answer changing under them, or that they already hold some * appropriate lock, and therefore return the first answer we get without * checking for invalidation messages. Also, if the requested lock is - * already held, LockRelationOid will not AcceptInvalidationMessages, - * so we may fail to notice a change. We could protect against that case - * by calling AcceptInvalidationMessages() before beginning this loop, but + * already held, LockRelationOid will not AcceptInvalidationMessages, so + * we may fail to notice a change. We could protect against that case by + * calling AcceptInvalidationMessages() before beginning this loop, but * that would add a significant amount overhead, so for now we don't. */ for (;;) @@ -1075,8 +1075,8 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames, */ effective_nargs = Max(pronargs, nargs); newResult = (FuncCandidateList) - palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid) - + effective_nargs * sizeof(Oid)); + palloc(offsetof(struct _FuncCandidateList, args) + + effective_nargs * sizeof(Oid)); newResult->pathpos = pathpos; newResult->oid = HeapTupleGetOid(proctup); newResult->nargs = effective_nargs; @@ -1597,7 +1597,8 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok) * separate palloc for each operator, but profiling revealed that the * pallocs used an unreasonably large fraction of parsing time. */ -#define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid)) +#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \ + 2 * sizeof(Oid)) if (catlist->n_members > 0) resultSpace = palloc(catlist->n_members * SPACE_PER_OP); diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 71b08f01bf..fb33d305af 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -383,10 +383,9 @@ EvaluateParams(PreparedStatement *pstmt, List *params, /* Prepare the expressions for execution */ exprstates = (List *) ExecPrepareExpr((Expr *) params, estate); - /* sizeof(ParamListInfoData) includes the first array element */ paramLI = (ParamListInfo) - palloc(sizeof(ParamListInfoData) + - (num_params - 1) * sizeof(ParamExternData)); + palloc(offsetof(ParamListInfoData, params) + + num_params * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 84be37c7a3..6c3eff7c58 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -896,9 +896,9 @@ postquel_sub_params(SQLFunctionCachePtr fcache, if (fcache->paramLI == NULL) { - /* sizeof(ParamListInfoData) includes the first array element */ - paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) + - (nargs - 1) * sizeof(ParamExternData)); + paramLI = (ParamListInfo) + palloc(offsetof(ParamListInfoData, params) + + nargs * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 4b86e910df..b3c05025bc 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -2290,9 +2290,8 @@ _SPI_convert_params(int nargs, Oid *argtypes, { int i; - /* sizeof(ParamListInfoData) includes the first array element */ - paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) + - (nargs - 1) * sizeof(ParamExternData)); + paramLI = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) + + nargs * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index 2f2f5edb83..fb803f8ee8 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -40,9 +40,8 @@ copyParamList(ParamListInfo from) if (from == NULL || from->numParams <= 0) return NULL; - /* sizeof(ParamListInfoData) includes the first array element */ - size = sizeof(ParamListInfoData) + - (from->numParams - 1) * sizeof(ParamExternData); + size = offsetof(ParamListInfoData, params) + + from->numParams * sizeof(ParamExternData); retval = (ParamListInfo) palloc(size); retval->paramFetch = NULL; diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 41b8dbb6c2..14ff1477c1 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -785,13 +785,13 @@ process_pipe_input(char *logbuffer, int *bytes_in_logbuffer) int dest = LOG_DESTINATION_STDERR; /* While we have enough for a header, process data... */ - while (count >= (int) sizeof(PipeProtoHeader)) + while (count >= (int) (offsetof(PipeProtoHeader, data) +1)) { PipeProtoHeader p; int chunklen; /* Do we have a valid header? */ - memcpy(&p, cursor, sizeof(PipeProtoHeader)); + memcpy(&p, cursor, offsetof(PipeProtoHeader, data)); if (p.nuls[0] == '\0' && p.nuls[1] == '\0' && p.len > 0 && p.len <= PIPE_MAX_PAYLOAD && p.pid != 0 && diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 28af40c3dc..33720e8f8b 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -1619,9 +1619,8 @@ exec_bind_message(StringInfo input_message) { int paramno; - /* sizeof(ParamListInfoData) includes the first array element */ - params = (ParamListInfo) palloc(sizeof(ParamListInfoData) + - (numParams - 1) * sizeof(ParamExternData)); + params = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) + + numParams * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ params->paramFetch = NULL; params->paramFetchArg = NULL; diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 6b6510e8e2..6cb6be5c5f 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -1390,7 +1390,7 @@ path_in(PG_FUNCTION_ARGS) } base_size = sizeof(path->p[0]) * npts; - size = offsetof(PATH, p[0]) +base_size; + size = offsetof(PATH, p) +base_size; /* Check for integer overflow */ if (base_size / npts != sizeof(path->p[0]) || size <= base_size) @@ -1443,12 +1443,12 @@ path_recv(PG_FUNCTION_ARGS) closed = pq_getmsgbyte(buf); npts = pq_getmsgint(buf, sizeof(int32)); - if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(PATH, p[0])) / sizeof(Point))) + if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(PATH, p)) / sizeof(Point))) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid number of points in external \"path\" value"))); - size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts; + size = offsetof(PATH, p) +sizeof(path->p[0]) * npts; path = (PATH *) palloc(size); SET_VARSIZE(path, size); @@ -3476,7 +3476,7 @@ poly_in(PG_FUNCTION_ARGS) errmsg("invalid input syntax for type polygon: \"%s\"", str))); base_size = sizeof(poly->p[0]) * npts; - size = offsetof(POLYGON, p[0]) +base_size; + size = offsetof(POLYGON, p) +base_size; /* Check for integer overflow */ if (base_size / npts != sizeof(poly->p[0]) || size <= base_size) @@ -3530,12 +3530,12 @@ poly_recv(PG_FUNCTION_ARGS) int size; npts = pq_getmsgint(buf, sizeof(int32)); - if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(POLYGON, p[0])) / sizeof(Point))) + if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(POLYGON, p)) / sizeof(Point))) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid number of points in external \"polygon\" value"))); - size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts; + size = offsetof(POLYGON, p) +sizeof(poly->p[0]) * npts; poly = (POLYGON *) palloc0(size); /* zero any holes */ SET_VARSIZE(poly, size); @@ -4251,7 +4251,7 @@ path_add(PG_FUNCTION_ARGS) PG_RETURN_NULL(); base_size = sizeof(p1->p[0]) * (p1->npts + p2->npts); - size = offsetof(PATH, p[0]) +base_size; + size = offsetof(PATH, p) +base_size; /* Check for integer overflow */ if (base_size / sizeof(p1->p[0]) != (p1->npts + p2->npts) || @@ -4393,7 +4393,7 @@ path_poly(PG_FUNCTION_ARGS) * Never overflows: the old size fit in MaxAllocSize, and the new size is * just a small constant larger. */ - size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * path->npts; + size = offsetof(POLYGON, p) +sizeof(poly->p[0]) * path->npts; poly = (POLYGON *) palloc(size); SET_VARSIZE(poly, size); @@ -4468,7 +4468,7 @@ box_poly(PG_FUNCTION_ARGS) int size; /* map four corners of the box to a polygon */ - size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * 4; + size = offsetof(POLYGON, p) +sizeof(poly->p[0]) * 4; poly = (POLYGON *) palloc(size); SET_VARSIZE(poly, size); @@ -4502,7 +4502,7 @@ poly_path(PG_FUNCTION_ARGS) * Never overflows: the old size fit in MaxAllocSize, and the new size is * smaller by a small constant. */ - size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * poly->npts; + size = offsetof(PATH, p) +sizeof(path->p[0]) * poly->npts; path = (PATH *) palloc(size); SET_VARSIZE(path, size); @@ -5181,7 +5181,7 @@ circle_poly(PG_FUNCTION_ARGS) errmsg("must request at least 2 points"))); base_size = sizeof(poly->p[0]) * npts; - size = offsetof(POLYGON, p[0]) +base_size; + size = offsetof(POLYGON, p) +base_size; /* Check for integer overflow */ if (base_size / npts != sizeof(poly->p[0]) || size <= base_size) diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 2e4d0b393a..1af43c6de6 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -1590,7 +1590,7 @@ SearchCatCacheList(CatCache *cache, oldcxt = MemoryContextSwitchTo(CacheMemoryContext); nmembers = list_length(ctlist); cl = (CatCList *) - palloc(sizeof(CatCList) + nmembers * sizeof(CatCTup *)); + palloc(offsetof(CatCList, members) +nmembers * sizeof(CatCTup *)); heap_copytuple_with_tuple(ntp, &cl->tuple); MemoryContextSwitchTo(oldcxt); heap_freetuple(ntp); diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 095c50770b..d7506e119e 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -1216,9 +1216,8 @@ simple_string_list_append(SimpleStringList *list, const char *val) { SimpleStringListCell *cell; - /* this calculation correctly accounts for the null trailing byte */ cell = (SimpleStringListCell *) - pg_malloc(sizeof(SimpleStringListCell) + strlen(val)); + pg_malloc(offsetof(SimpleStringListCell, val) +strlen(val) + 1); cell->next = NULL; strcpy(cell->val, val); diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index a39c1b66b0..b1767468c1 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -38,7 +38,7 @@ typedef struct SimpleOidList typedef struct SimpleStringListCell { struct SimpleStringListCell *next; - char val[1]; /* VARIABLE LENGTH FIELD */ + char val[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string here */ } SimpleStringListCell; typedef struct SimpleStringList diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 9bb0ba4b05..c1a2049d08 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -322,7 +322,7 @@ typedef struct GinOptions { int32 vl_len_; /* varlena header (do not touch directly!) */ bool useFastUpdate; /* use fast updates? */ - int pendingListCleanupSize; /* maximum size of pending list */ + int pendingListCleanupSize; /* maximum size of pending list */ } GinOptions; #define GIN_DEFAULT_USE_FASTUPDATE true @@ -389,7 +389,7 @@ typedef struct { ItemPointerData first; /* first item in this posting list (unpacked) */ uint16 nbytes; /* number of bytes that follow */ - unsigned char bytes[1]; /* varbyte encoded items (variable length) */ + unsigned char bytes[FLEXIBLE_ARRAY_MEMBER]; /* varbyte encoded items */ } GinPostingList; #define SizeOfGinPostingList(plist) (offsetof(GinPostingList, bytes) + SHORTALIGN((plist)->nbytes) ) diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index 382826eb85..ce83042e17 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -47,7 +47,7 @@ typedef struct { BlockNumber prev; uint32 freespace; - char tupledata[1]; + char tupledata[FLEXIBLE_ARRAY_MEMBER]; } GISTNodeBufferPage; #define BUFFER_PAGE_DATA_OFFSET MAXALIGN(offsetof(GISTNodeBufferPage, tupledata)) @@ -131,7 +131,8 @@ typedef struct GISTSearchItem /* we must store parentlsn to detect whether a split occurred */ GISTSearchHeapItem heap; /* heap info, if heap tuple */ } data; - double distances[1]; /* array with numberOfOrderBys entries */ + double distances[FLEXIBLE_ARRAY_MEMBER]; /* numberOfOrderBys + * entries */ } GISTSearchItem; #define GISTSearchItemIsHeap(item) ((item).blkno == InvalidBlockNumber) @@ -144,7 +145,7 @@ typedef struct GISTSearchItem typedef struct GISTScanOpaqueData { GISTSTATE *giststate; /* index information, see above */ - pairingheap *queue; /* queue of unvisited items */ + pairingheap *queue; /* queue of unvisited items */ MemoryContext queueCxt; /* context holding the queue */ bool qual_ok; /* false if qual can never be satisfied */ bool firstCall; /* true until first gistgettuple call */ diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index a2ed2a058f..f0f89dec0f 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -132,7 +132,7 @@ typedef struct xl_heap_multi_insert { uint8 flags; uint16 ntuples; - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } xl_heap_multi_insert; #define SizeOfHeapMultiInsert offsetof(xl_heap_multi_insert, offsets) diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h index f11d8ef490..0492ef6114 100644 --- a/src/include/access/spgist_private.h +++ b/src/include/access/spgist_private.h @@ -426,7 +426,7 @@ typedef struct spgxlogMoveLeafs * the dead tuple from the source *---------- */ - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogMoveLeafs; #define SizeOfSpgxlogMoveLeafs offsetof(spgxlogMoveLeafs, offsets) @@ -534,7 +534,7 @@ typedef struct spgxlogPickSplit * list of leaf tuples, length nInsert (unaligned!) *---------- */ - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogPickSplit; #define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets) @@ -558,7 +558,7 @@ typedef struct spgxlogVacuumLeaf * tuple numbers to insert in nextOffset links *---------- */ - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumLeaf; #define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets) @@ -571,7 +571,7 @@ typedef struct spgxlogVacuumRoot spgxlogState stateSrc; /* offsets of tuples to delete follow */ - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumRoot; #define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets) @@ -583,7 +583,7 @@ typedef struct spgxlogVacuumRedirect TransactionId newestRedirectXid; /* newest XID of removed redirects */ /* offsets of redirect tuples to make placeholders follow */ - OffsetNumber offsets[1]; + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumRedirect; #define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets) diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 8205504e6e..d7e5f6447c 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -118,7 +118,7 @@ typedef struct xl_xact_assignment { TransactionId xtop; /* assigned XID's top-level XID */ int nsubxacts; /* number of subtransaction XIDs */ - TransactionId xsub[1]; /* assigned subxids */ + TransactionId xsub[FLEXIBLE_ARRAY_MEMBER]; /* assigned subxids */ } xl_xact_assignment; #define MinSizeOfXactAssignment offsetof(xl_xact_assignment, xsub) @@ -128,7 +128,7 @@ typedef struct xl_xact_commit_compact TimestampTz xact_time; /* time of commit */ int nsubxacts; /* number of subtransaction XIDs */ /* ARRAY OF COMMITTED SUBTRANSACTION XIDs FOLLOWS */ - TransactionId subxacts[1]; /* VARIABLE LENGTH ARRAY */ + TransactionId subxacts[FLEXIBLE_ARRAY_MEMBER]; } xl_xact_commit_compact; #define MinSizeOfXactCommitCompact offsetof(xl_xact_commit_compact, subxacts) @@ -143,7 +143,7 @@ typedef struct xl_xact_commit Oid dbId; /* MyDatabaseId */ Oid tsId; /* MyDatabaseTableSpace */ /* Array of RelFileNode(s) to drop at commit */ - RelFileNode xnodes[1]; /* VARIABLE LENGTH ARRAY */ + RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER]; /* ARRAY OF COMMITTED SUBTRANSACTION XIDs FOLLOWS */ /* ARRAY OF SHARED INVALIDATION MESSAGES FOLLOWS */ } xl_xact_commit; @@ -171,7 +171,7 @@ typedef struct xl_xact_abort int nrels; /* number of RelFileNodes */ int nsubxacts; /* number of subtransaction XIDs */ /* Array of RelFileNode(s) to drop at abort */ - RelFileNode xnodes[1]; /* VARIABLE LENGTH ARRAY */ + RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER]; /* ARRAY OF ABORTED SUBTRANSACTION XIDs FOLLOWS */ } xl_xact_abort; diff --git a/src/include/c.h b/src/include/c.h index b187520973..2de86f9141 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -424,8 +424,8 @@ typedef struct Oid elemtype; int dim1; int lbound1; - int16 values[1]; /* VARIABLE LENGTH ARRAY */ -} int2vector; /* VARIABLE LENGTH STRUCT */ + int16 values[FLEXIBLE_ARRAY_MEMBER]; +} int2vector; typedef struct { @@ -435,8 +435,8 @@ typedef struct Oid elemtype; int dim1; int lbound1; - Oid values[1]; /* VARIABLE LENGTH ARRAY */ -} oidvector; /* VARIABLE LENGTH STRUCT */ + Oid values[FLEXIBLE_ARRAY_MEMBER]; +} oidvector; /* * Representation of a Name: effectively just a C string, but null-padded to diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index d2e51986a6..cf5f7d0a78 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -34,8 +34,8 @@ typedef struct _FuncCandidateList int nvargs; /* number of args to become variadic array */ int ndargs; /* number of defaulted args */ int *argnumbers; /* args' positional indexes, if named call */ - Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */ -} *FuncCandidateList; /* VARIABLE LENGTH STRUCT */ + Oid args[FLEXIBLE_ARRAY_MEMBER]; /* arg types */ +} *FuncCandidateList; /* * Structure for xxxOverrideSearchPath functions diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index cb7cc0e228..4b60cdbedc 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -22,21 +22,6 @@ #define XLOG_DBASE_CREATE 0x00 #define XLOG_DBASE_DROP 0x10 -typedef struct xl_dbase_create_rec_old -{ - /* Records copying of a single subdirectory incl. contents */ - Oid db_id; - char src_path[1]; /* VARIABLE LENGTH STRING */ - /* dst_path follows src_path */ -} xl_dbase_create_rec_old; - -typedef struct xl_dbase_drop_rec_old -{ - /* Records dropping of a single subdirectory incl. contents */ - Oid db_id; - char dir_path[1]; /* VARIABLE LENGTH STRING */ -} xl_dbase_drop_rec_old; - typedef struct xl_dbase_create_rec { /* Records copying of a single subdirectory incl. contents */ diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index e8b9bc407c..70734d6030 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -25,7 +25,7 @@ typedef struct xl_tblspc_create_rec { Oid ts_id; - char ts_path[1]; /* VARIABLE LENGTH STRING */ + char ts_path[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string */ } xl_tblspc_create_rec; typedef struct xl_tblspc_drop_rec diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h index e79df715de..71099b15bb 100644 --- a/src/include/executor/hashjoin.h +++ b/src/include/executor/hashjoin.h @@ -114,7 +114,7 @@ typedef struct HashMemoryChunkData struct HashMemoryChunkData *next; /* pointer to the next chunk (linked list) */ - char data[1]; /* buffer allocated at the end */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* buffer allocated at the end */ } HashMemoryChunkData; typedef struct HashMemoryChunkData *HashMemoryChunk; diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h index 5f45f4dbf3..3a556eed0a 100644 --- a/src/include/nodes/bitmapset.h +++ b/src/include/nodes/bitmapset.h @@ -32,8 +32,8 @@ typedef int32 signedbitmapword; /* must be the matching signed type */ typedef struct Bitmapset { int nwords; /* number of words in array */ - bitmapword words[1]; /* really [nwords] */ -} Bitmapset; /* VARIABLE LENGTH STRUCT */ + bitmapword words[FLEXIBLE_ARRAY_MEMBER]; /* really [nwords] */ +} Bitmapset; /* result of bms_subset_compare */ diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index 5b096c54b5..a0f7dd0c55 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -71,7 +71,7 @@ typedef struct ParamListInfoData ParserSetupHook parserSetup; /* parser setup hook */ void *parserSetupArg; int numParams; /* number of ParamExternDatas following */ - ParamExternData params[1]; /* VARIABLE LENGTH ARRAY */ + ParamExternData params[FLEXIBLE_ARRAY_MEMBER]; } ParamListInfoData; diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h index fb62c9e683..cfba64b0c5 100644 --- a/src/include/nodes/tidbitmap.h +++ b/src/include/nodes/tidbitmap.h @@ -41,8 +41,8 @@ typedef struct int ntuples; /* -1 indicates lossy result */ bool recheck; /* should the tuples be rechecked? */ /* Note: recheck is always true if ntuples < 0 */ - OffsetNumber offsets[1]; /* VARIABLE LENGTH ARRAY */ -} TBMIterateResult; /* VARIABLE LENGTH STRUCT */ + OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; +} TBMIterateResult; /* function prototypes in nodes/tidbitmap.c */ diff --git a/src/include/postgres.h b/src/include/postgres.h index 082c75b093..cbb7f796e1 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -117,20 +117,20 @@ typedef union struct /* Normal varlena (4-byte length) */ { uint32 va_header; - char va_data[1]; + char va_data[FLEXIBLE_ARRAY_MEMBER]; } va_4byte; struct /* Compressed-in-line format */ { uint32 va_header; uint32 va_rawsize; /* Original data size (excludes header) */ - char va_data[1]; /* Compressed data */ + char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */ } va_compressed; } varattrib_4b; typedef struct { uint8 va_header; - char va_data[1]; /* Data begins here */ + char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Data begins here */ } varattrib_1b; /* TOAST pointers are a subset of varattrib_1b with an identifying tag byte */ @@ -138,7 +138,7 @@ typedef struct { uint8 va_header; /* Always 0x80 or 0x01 */ uint8 va_tag; /* Type of datum */ - char va_data[1]; /* Data (of the type indicated by va_tag) */ + char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */ } varattrib_1b_e; /* diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h index 602b13c097..89a535c18f 100644 --- a/src/include/postmaster/syslogger.h +++ b/src/include/postmaster/syslogger.h @@ -48,7 +48,7 @@ typedef struct int32 pid; /* writer's pid */ char is_last; /* last chunk of message? 't' or 'f' ('T' or * 'F' for CSV case) */ - char data[1]; /* data payload starts here */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* data payload starts here */ } PipeProtoHeader; typedef union diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h index 88677506f3..40351da47f 100644 --- a/src/include/replication/walsender_private.h +++ b/src/include/replication/walsender_private.h @@ -54,7 +54,7 @@ typedef struct WalSnd * Pointer to the walsender's latch. Used by backends to wake up this * walsender when it has work to do. NULL if the walsender isn't active. */ - Latch *latch; + Latch *latch; /* * The priority order of the standby managed by this WALSender, as listed @@ -88,7 +88,7 @@ typedef struct */ bool sync_standbys_defined; - WalSnd walsnds[1]; /* VARIABLE LENGTH ARRAY */ + WalSnd walsnds[FLEXIBLE_ARRAY_MEMBER]; } WalSndCtlData; extern WalSndCtlData *WalSndCtl; diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index f693032724..c2fbffc8e9 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -156,7 +156,7 @@ typedef struct PageHeaderData LocationIndex pd_special; /* offset to start of special space */ uint16 pd_pagesize_version; TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */ - ItemIdData pd_linp[1]; /* beginning of line pointer array */ + ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* line pointer array */ } PageHeaderData; typedef PageHeaderData *PageHeader; diff --git a/src/include/storage/fsm_internals.h b/src/include/storage/fsm_internals.h index 1decd90133..26340b4b2e 100644 --- a/src/include/storage/fsm_internals.h +++ b/src/include/storage/fsm_internals.h @@ -39,7 +39,7 @@ typedef struct * NonLeafNodesPerPage elements are upper nodes, and the following * LeafNodesPerPage elements are leaf nodes. Unused nodes are zero. */ - uint8 fp_nodes[1]; + uint8 fp_nodes[FLEXIBLE_ARRAY_MEMBER]; } FSMPageData; typedef FSMPageData *FSMPage; diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h index c32c96379c..7626c4c4f4 100644 --- a/src/include/storage/standby.h +++ b/src/include/storage/standby.h @@ -60,7 +60,7 @@ extern void StandbyReleaseOldLocks(int nxids, TransactionId *xids); typedef struct xl_standby_locks { int nlocks; /* number of entries in locks array */ - xl_standby_lock locks[1]; /* VARIABLE LENGTH ARRAY */ + xl_standby_lock locks[FLEXIBLE_ARRAY_MEMBER]; } xl_standby_locks; /* @@ -75,7 +75,7 @@ typedef struct xl_running_xacts TransactionId oldestRunningXid; /* *not* oldestXmin */ TransactionId latestCompletedXid; /* so we can set xmax */ - TransactionId xids[1]; /* VARIABLE LENGTH ARRAY */ + TransactionId xids[FLEXIBLE_ARRAY_MEMBER]; } xl_running_xacts; #define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids) diff --git a/src/include/tsearch/dicts/regis.h b/src/include/tsearch/dicts/regis.h index 081a502d69..ddf5b605c4 100644 --- a/src/include/tsearch/dicts/regis.h +++ b/src/include/tsearch/dicts/regis.h @@ -21,7 +21,7 @@ typedef struct RegisNode len:16, unused:14; struct RegisNode *next; - unsigned char data[1]; + unsigned char data[FLEXIBLE_ARRAY_MEMBER]; } RegisNode; #define RNHDRSZ (offsetof(RegisNode,data)) diff --git a/src/include/tsearch/dicts/spell.h b/src/include/tsearch/dicts/spell.h index a75552bbeb..e512532f8e 100644 --- a/src/include/tsearch/dicts/spell.h +++ b/src/include/tsearch/dicts/spell.h @@ -49,7 +49,7 @@ typedef struct typedef struct SPNode { uint32 length; - SPNodeData data[1]; + SPNodeData data[FLEXIBLE_ARRAY_MEMBER]; } SPNode; #define SPNHDRSZ (offsetof(SPNode,data)) @@ -70,7 +70,7 @@ typedef struct spell_struct int len; } d; } p; - char word[1]; /* variable length, null-terminated */ + char word[FLEXIBLE_ARRAY_MEMBER]; } SPELL; #define SPELLHDRSZ (offsetof(SPELL, word)) @@ -120,7 +120,7 @@ typedef struct AffixNode { uint32 isvoid:1, length:31; - AffixNodeData data[1]; + AffixNodeData data[FLEXIBLE_ARRAY_MEMBER]; } AffixNode; #define ANHRDSZ (offsetof(AffixNode, data)) diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h index 1cdfa82fb0..ce919a2c66 100644 --- a/src/include/tsearch/ts_type.h +++ b/src/include/tsearch/ts_type.h @@ -63,7 +63,7 @@ typedef uint16 WordEntryPos; typedef struct { uint16 npos; - WordEntryPos pos[1]; /* variable length */ + WordEntryPos pos[FLEXIBLE_ARRAY_MEMBER]; } WordEntryPosVector; @@ -82,7 +82,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 size; - WordEntry entries[1]; /* variable length */ + WordEntry entries[FLEXIBLE_ARRAY_MEMBER]; /* lexemes follow the entries[] array */ } TSVectorData; @@ -233,7 +233,7 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 size; /* number of QueryItems */ - char data[1]; /* data starts here */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* data starts here */ } TSQueryData; typedef TSQueryData *TSQuery; diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h index 8084785354..a3a699c2fa 100644 --- a/src/include/utils/catcache.h +++ b/src/include/utils/catcache.h @@ -147,8 +147,8 @@ typedef struct catclist uint32 hash_value; /* hash value for lookup keys */ HeapTupleData tuple; /* header for tuple holding keys */ int n_members; /* number of member tuples */ - CatCTup *members[1]; /* members --- VARIABLE LENGTH ARRAY */ -} CatCList; /* VARIABLE LENGTH STRUCT */ + CatCTup *members[FLEXIBLE_ARRAY_MEMBER]; /* members */ +} CatCList; typedef struct catcacheheader diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 8912ba53bf..6b8ab3c656 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -219,7 +219,7 @@ typedef struct TimeZoneAbbrevTable { Size tblsize; /* size in bytes of TimeZoneAbbrevTable */ int numabbrevs; /* number of entries in abbrevs[] array */ - datetkn abbrevs[1]; /* VARIABLE LENGTH ARRAY */ + datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]; /* DynamicZoneAbbrev(s) may follow the abbrevs[] array */ } TimeZoneAbbrevTable; @@ -227,7 +227,7 @@ typedef struct TimeZoneAbbrevTable typedef struct DynamicZoneAbbrev { pg_tz *tz; /* NULL if not yet looked up */ - char zone[1]; /* zone name (var length, NUL-terminated) */ + char zone[FLEXIBLE_ARRAY_MEMBER]; /* NUL-terminated zone name */ } DynamicZoneAbbrev; diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 0b6d3c32d1..8da6c6c987 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -80,7 +80,7 @@ typedef struct int32 npts; int32 closed; /* is this a closed polygon? */ int32 dummy; /* padding to make it double align */ - Point p[1]; /* variable length array of POINTs */ + Point p[FLEXIBLE_ARRAY_MEMBER]; } PATH; @@ -115,7 +115,7 @@ typedef struct int32 vl_len_; /* varlena header (do not touch directly!) */ int32 npts; BOX boundbox; - Point p[1]; /* variable length array of POINTs */ + Point p[FLEXIBLE_ARRAY_MEMBER]; } POLYGON; /*--------------------------------------------------------------------- diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h index 887eb9b795..9d1770e4c9 100644 --- a/src/include/utils/jsonb.h +++ b/src/include/utils/jsonb.h @@ -194,7 +194,7 @@ typedef struct JsonbContainer { uint32 header; /* number of elements or key/value pairs, and * flags */ - JEntry children[1]; /* variable length */ + JEntry children[FLEXIBLE_ARRAY_MEMBER]; /* the data for each child node follows. */ } JsonbContainer; diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h index 420310d6fc..73b4905e3b 100644 --- a/src/include/utils/relmapper.h +++ b/src/include/utils/relmapper.h @@ -29,7 +29,7 @@ typedef struct xl_relmap_update Oid dbid; /* database ID, or 0 for shared map */ Oid tsid; /* database's tablespace, or pg_global */ int32 nbytes; /* size of relmap data */ - char data[1]; /* VARIABLE LENGTH ARRAY */ + char data[FLEXIBLE_ARRAY_MEMBER]; } xl_relmap_update; #define MinSizeOfRelmapUpdate offsetof(xl_relmap_update, data) diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index 8afc3b1a6a..da55e7d031 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -26,7 +26,8 @@ typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ int32 bit_len; /* number of valid bits */ - bits8 bit_dat[1]; /* bit string, most sig. byte first */ + bits8 bit_dat[FLEXIBLE_ARRAY_MEMBER]; /* bit string, most sig. byte + * first */ } VarBit; /*