Hi,

In a lot of places in the code we have many structures doing
declarations of the type foo[1] to emulate variable length arrays.
Attached are a set of patches aimed at replacing that with
FLEXIBLE_ARRAY_MEMBER to prevent potential failures that could be
caused by compiler optimizations and improve report of static code
analyzers of the type Coverity (idea by Tom, patches from me):
- 0001 uses FLEXIBLE_ARRAY_MEMBER in a bunch of trivial places (at
least check-world does not complain)
- 0002 does the same for catalog tables
- 0003 changes varlena in c.h. This is done as a separate patch
because this needs some other modifications as variable-length things
need to be placed at the end of structures, because of:
-- rolpassword that should be placed as the last field of pg_authid
(and shouldn't there be CATALOG_VARLEN here??)
-- inv_api.c uses bytea in an internal structure without putting it at
the end of the structure. For clarity I think that we should just use
a bytea pointer and do a sufficient allocation for the duration of the
lobj manipulation.
-- Similarly, tuptoaster.c needed to be patched for toast_save_datum

There are as well couple of things that are not changed on purpose:
- in namespace.h for FuncCandidateList. I tried manipulating it but it
resulted in allocation overflow in PortalHeapMemory
- I don't think that the t_bits fields in htup_details.h should be
updated either.
Regards,
-- 
Michael
From f3389a945811e1db19eb5debc9e41b84fed0a9f5 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@otacoo.com>
Date: Mon, 16 Feb 2015 02:44:10 +0900
Subject: [PATCH 1/3] First cut with FLEXIBLE_ARRAY_MEMBER

This is targetted to prevent false positive errors that static code
analyzers may do by assuming that some structures have an unvarying
size.
---
 contrib/cube/cubedata.h                     |  7 +++----
 contrib/intarray/_int.h                     |  4 ++--
 contrib/ltree/ltree.h                       | 14 +++++++-------
 contrib/pg_trgm/trgm.h                      |  2 +-
 src/bin/pg_dump/dumputils.h                 |  2 +-
 src/include/access/gin_private.h            |  4 ++--
 src/include/access/gist_private.h           |  5 +++--
 src/include/access/heapam_xlog.h            |  2 +-
 src/include/access/htup_details.h           |  4 ++--
 src/include/access/spgist_private.h         | 10 +++++-----
 src/include/access/xact.h                   |  8 ++++----
 src/include/c.h                             |  4 ++--
 src/include/commands/dbcommands.h           |  4 ++--
 src/include/commands/tablespace.h           |  2 +-
 src/include/executor/hashjoin.h             |  2 +-
 src/include/nodes/bitmapset.h               |  2 +-
 src/include/nodes/params.h                  |  2 +-
 src/include/nodes/tidbitmap.h               |  2 +-
 src/include/postgres.h                      |  9 +++++----
 src/include/postmaster/syslogger.h          |  2 +-
 src/include/replication/walsender_private.h |  2 +-
 src/include/storage/bufpage.h               |  3 ++-
 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                |  2 +-
 src/include/utils/datetime.h                |  5 +++--
 src/include/utils/geo_decls.h               |  3 ++-
 src/include/utils/jsonb.h                   |  2 +-
 src/include/utils/relmapper.h               |  2 +-
 src/include/utils/varbit.h                  |  3 ++-
 33 files changed, 69 insertions(+), 64 deletions(-)

diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index 5d44e11..3535847 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
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index 7f93206..d524f0f 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 1b1305b..c604357 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/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index ed649b8..f030558 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/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
index a39c1b6..94476a9 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];
 } SimpleStringListCell;
 
 typedef struct SimpleStringList
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index bda7c28..8968993 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -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) )
@@ -527,7 +527,7 @@ typedef struct
 	ItemPointerData rrightbound;	/* new right bound of right page */
 
 	/* FOLLOWS: new compressed posting lists of left and right page */
-	char		newdata[1];
+	char		newdata[FLEXIBLE_ARRAY_MEMBER];
 } ginxlogSplitDataLeaf;
 
 typedef struct
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 382826e..36f5257 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]; /* array with numberOfOrderBys
+											  * entries */
 } GISTSearchItem;
 
 #define GISTSearchItemIsHeap(item)	((item).blkno == InvalidBlockNumber)
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
index a2ed2a0..f0f89de 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/htup_details.h b/src/include/access/htup_details.h
index d2ad910..0225b17 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -150,7 +150,7 @@ struct HeapTupleHeaderData
 
 	/* ^ - 23 bytes - ^ */
 
-	bits8		t_bits[1];		/* bitmap of NULLs -- VARIABLE LENGTH */
+	bits8		t_bits[1];		/* bitmap of NULLs */
 
 	/* MORE DATA FOLLOWS AT END OF STRUCT */
 };
@@ -579,7 +579,7 @@ struct MinimalTupleData
 
 	/* ^ - 23 bytes - ^ */
 
-	bits8		t_bits[1];		/* bitmap of NULLs -- VARIABLE LENGTH */
+	bits8		t_bits[1];		/* bitmap of NULLs */
 
 	/* MORE DATA FOLLOWS AT END OF STRUCT */
 };
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
index f11d8ef..0492ef6 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 8205504..9b95f10 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 b187520..bbd0d53 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -424,7 +424,7 @@ typedef struct
 	Oid			elemtype;
 	int			dim1;
 	int			lbound1;
-	int16		values[1];		/* VARIABLE LENGTH ARRAY */
+	int16		values[FLEXIBLE_ARRAY_MEMBER];
 } int2vector;					/* VARIABLE LENGTH STRUCT */
 
 typedef struct
@@ -435,7 +435,7 @@ typedef struct
 	Oid			elemtype;
 	int			dim1;
 	int			lbound1;
-	Oid			values[1];		/* VARIABLE LENGTH ARRAY */
+	Oid			values[FLEXIBLE_ARRAY_MEMBER];
 } oidvector;					/* VARIABLE LENGTH STRUCT */
 
 /*
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index cb7cc0e..be1cac2 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -26,7 +26,7 @@ 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 */
+	char		src_path[FLEXIBLE_ARRAY_MEMBER];
 	/* dst_path follows src_path */
 }	xl_dbase_create_rec_old;
 
@@ -34,7 +34,7 @@ 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 */
+	char		dir_path[FLEXIBLE_ARRAY_MEMBER];
 }	xl_dbase_drop_rec_old;
 
 typedef struct xl_dbase_create_rec
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index e8b9bc4..9e40e31 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];
 } 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 e79df71..71099b1 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 5f45f4d..1adabc3 100644
--- a/src/include/nodes/bitmapset.h
+++ b/src/include/nodes/bitmapset.h
@@ -32,7 +32,7 @@ typedef int32 signedbitmapword; /* must be the matching signed type */
 typedef struct Bitmapset
 {
 	int			nwords;			/* number of words in array */
-	bitmapword	words[1];		/* really [nwords] */
+	bitmapword	words[FLEXIBLE_ARRAY_MEMBER];	/* really [nwords] */
 } Bitmapset;					/* VARIABLE LENGTH STRUCT */
 
 
diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h
index 5b096c5..0ad7ef0 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[1];
 }	ParamListInfoData;
 
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index fb62c9e..bfbc0fb 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -41,7 +41,7 @@ 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 */
+	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;				/* VARIABLE LENGTH STRUCT */
 
 /* function prototypes in nodes/tidbitmap.c */
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 082c75b..482e676 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,8 @@ 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];	/* Data (of the type
+												 * indicated by va_tag) */
 } varattrib_1b_e;
 
 /*
diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h
index 602b13c..89a535c 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 8867750..02faad8 100644
--- a/src/include/replication/walsender_private.h
+++ b/src/include/replication/walsender_private.h
@@ -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 f693032..b7dbd6f 100644
--- a/src/include/storage/bufpage.h
+++ b/src/include/storage/bufpage.h
@@ -156,7 +156,8 @@ 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];	/* beginning of line pointer
+												 * array */
 } PageHeaderData;
 
 typedef PageHeaderData *PageHeader;
diff --git a/src/include/storage/fsm_internals.h b/src/include/storage/fsm_internals.h
index 1decd90..26340b4 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 c32c963..7626c4c 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 081a502..ddf5b60 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 a75552b..e512532 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 1cdfa82..ce919a2 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 8084785..f5361f9 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -147,7 +147,7 @@ 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 */
+	CatCTup    *members[FLEXIBLE_ARRAY_MEMBER];	/* members */
 } CatCList;						/* VARIABLE LENGTH STRUCT */
 
 
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index 8912ba5..d36f297 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,8 @@ 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];	/* zone name (var length,
+												 * NUL-terminated) */
 } DynamicZoneAbbrev;
 
 
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 0b6d3c3..63885f3 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -80,7 +80,8 @@ 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];	/* variable length array
+											 * of POINTs */
 } PATH;
 
 
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
index 887eb9b..9d1770e 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 420310d..73b4905 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 8afc3b1..bd5bf52 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;
 
 /*
-- 
2.3.0

From b607e5be3ff1099d7f0374bafb7a2b497a8860fd Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@otacoo.com>
Date: Mon, 16 Feb 2015 03:12:39 +0900
Subject: [PATCH 2/3] Use FLEXIBLE_ARRAY_MEMBER in catalog tables

---
 src/include/catalog/pg_attribute.h            |  6 +++---
 src/include/catalog/pg_class.h                |  5 +++--
 src/include/catalog/pg_constraint.h           | 12 ++++++------
 src/include/catalog/pg_database.h             |  2 +-
 src/include/catalog/pg_db_role_setting.h      |  3 ++-
 src/include/catalog/pg_default_acl.h          |  3 ++-
 src/include/catalog/pg_event_trigger.h        |  3 ++-
 src/include/catalog/pg_extension.h            |  6 ++++--
 src/include/catalog/pg_foreign_data_wrapper.h |  4 ++--
 src/include/catalog/pg_foreign_server.h       |  4 ++--
 src/include/catalog/pg_foreign_table.h        |  2 +-
 src/include/catalog/pg_language.h             |  2 +-
 src/include/catalog/pg_largeobject_metadata.h |  2 +-
 src/include/catalog/pg_namespace.h            |  2 +-
 src/include/catalog/pg_pltemplate.h           |  2 +-
 src/include/catalog/pg_policy.h               |  3 ++-
 src/include/catalog/pg_proc.h                 | 14 +++++++++-----
 src/include/catalog/pg_statistic.h            | 10 +++++-----
 src/include/catalog/pg_tablespace.h           |  5 +++--
 src/include/catalog/pg_type.h                 |  2 +-
 src/include/catalog/pg_user_mapping.h         |  2 +-
 21 files changed, 53 insertions(+), 41 deletions(-)

diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 87a3462..73bcefe 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -157,13 +157,13 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
 	/* NOTE: The following fields are not present in tuple descriptors. */
 
 	/* Column-level access permissions */
-	aclitem		attacl[1];
+	aclitem		attacl[FLEXIBLE_ARRAY_MEMBER];
 
 	/* Column-level options */
-	text		attoptions[1];
+	text		attoptions[FLEXIBLE_ARRAY_MEMBER];
 
 	/* Column-level FDW options */
-	text		attfdwoptions[1];
+	text		attfdwoptions[FLEXIBLE_ARRAY_MEMBER];
 #endif
 } FormData_pg_attribute;
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 8b4c35c..9516d5d 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -74,8 +74,9 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	/* NOTE: These fields are not present in a relcache entry's rd_rel field. */
-	aclitem		relacl[1];		/* access permissions */
-	text		reloptions[1];	/* access-method-specific options */
+	aclitem		relacl[FLEXIBLE_ARRAY_MEMBER];		/* access permissions */
+	text		reloptions[FLEXIBLE_ARRAY_MEMBER];	/* access-method-specific
+													 * options */
 #endif
 } FormData_pg_class;
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 6f32ac8..2100203 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -98,36 +98,36 @@ CATALOG(pg_constraint,2606)
 	 * Columns of conrelid that the constraint applies to, if known (this is
 	 * NULL for trigger constraints)
 	 */
-	int16		conkey[1];
+	int16		conkey[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If a foreign key, the referenced columns of confrelid
 	 */
-	int16		confkey[1];
+	int16		confkey[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If a foreign key, the OIDs of the PK = FK equality operators for each
 	 * column of the constraint
 	 */
-	Oid			conpfeqop[1];
+	Oid			conpfeqop[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If a foreign key, the OIDs of the PK = PK equality operators for each
 	 * column of the constraint (i.e., equality for the referenced columns)
 	 */
-	Oid			conppeqop[1];
+	Oid			conppeqop[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If a foreign key, the OIDs of the FK = FK equality operators for each
 	 * column of the constraint (i.e., equality for the referencing columns)
 	 */
-	Oid			conffeqop[1];
+	Oid			conffeqop[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If an exclusion constraint, the OIDs of the exclusion operators for
 	 * each column of the constraint
 	 */
-	Oid			conexclop[1];
+	Oid			conexclop[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * If a check constraint, nodeToString representation of expression
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 1045139..92e331e 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -45,7 +45,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_M
 	Oid			dattablespace;	/* default table space for this DB */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		datacl[1];		/* access permissions */
+	aclitem		datacl[FLEXIBLE_ARRAY_MEMBER];	/* access permissions */
 #endif
 } FormData_pg_database;
 
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index 9717569..ff931a9 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -38,7 +38,8 @@ CATALOG(pg_db_role_setting,2964) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
 	Oid			setrole;		/* role */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	text		setconfig[1];	/* GUC settings to apply at login */
+	text		setconfig[FLEXIBLE_ARRAY_MEMBER];	/* GUC settings to apply
+													 * at login */
 #endif
 } FormData_pg_db_role_setting;
 
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 0b5c554..dec4e32 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -34,7 +34,8 @@ CATALOG(pg_default_acl,826)
 	char		defaclobjtype;	/* see DEFACLOBJ_xxx constants below */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		defaclacl[1];	/* permissions to add at CREATE time */
+	aclitem		defaclacl[FLEXIBLE_ARRAY_MEMBER];	/* permissions to add
+													 * at CREATE time */
 #endif
 } FormData_pg_default_acl;
 
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index ca81a81..bb6c1aa 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -38,7 +38,8 @@ CATALOG(pg_event_trigger,3466)
 								 * session_replication_role */
 
 #ifdef CATALOG_VARLEN
-	text		evttags[1];		/* command TAGs this event trigger targets */
+	text		evttags[FLEXIBLE_ARRAY_MEMBER];	/* command TAGs this event
+												 * trigger targets */
 #endif
 } FormData_pg_event_trigger;
 
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index f45d6cb..ff54dbc 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -38,8 +38,10 @@ CATALOG(pg_extension,3079)
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	/* extversion should never be null, but the others can be. */
 	text		extversion;		/* extension version name */
-	Oid			extconfig[1];	/* dumpable configuration tables */
-	text		extcondition[1];	/* WHERE clauses for config tables */
+	Oid			extconfig[FLEXIBLE_ARRAY_MEMBER];	/* dumpable configuration
+													 * tables */
+	text		extcondition[FLEXIBLE_ARRAY_MEMBER]; /* WHERE clauses for
+													  * config tables */
 #endif
 } FormData_pg_extension;
 
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 1c7db04..091ea38 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -36,8 +36,8 @@ CATALOG(pg_foreign_data_wrapper,2328)
 	Oid			fdwvalidator;	/* option validation function, or 0 if none */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		fdwacl[1];		/* access permissions */
-	text		fdwoptions[1];	/* FDW options */
+	aclitem		fdwacl[FLEXIBLE_ARRAY_MEMBER];		/* access permissions */
+	text		fdwoptions[FLEXIBLE_ARRAY_MEMBER];	/* FDW options */
 #endif
 } FormData_pg_foreign_data_wrapper;
 
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 7ac6fd9..3c28d57 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -35,8 +35,8 @@ CATALOG(pg_foreign_server,1417)
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	text		srvtype;
 	text		srvversion;
-	aclitem		srvacl[1];		/* access permissions */
-	text		srvoptions[1];	/* FDW-specific options */
+	aclitem		srvacl[FLEXIBLE_ARRAY_MEMBER];		/* access permissions */
+	text		srvoptions[FLEXIBLE_ARRAY_MEMBER];	/* FDW-specific options */
 #endif
 } FormData_pg_foreign_server;
 
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 2e6b947..727214c 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -32,7 +32,7 @@ CATALOG(pg_foreign_table,3118) BKI_WITHOUT_OIDS
 	Oid			ftserver;		/* OID of foreign server */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	text		ftoptions[1];	/* FDW-specific options */
+	text		ftoptions[FLEXIBLE_ARRAY_MEMBER];	/* FDW-specific options */
 #endif
 } FormData_pg_foreign_table;
 
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index b82cca2..c7b10fc 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -39,7 +39,7 @@ CATALOG(pg_language,2612)
 	Oid			lanvalidator;	/* Optional validation function */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		lanacl[1];		/* Access privileges */
+	aclitem		lanacl[FLEXIBLE_ARRAY_MEMBER];	/* Access privileges */
 #endif
 } FormData_pg_language;
 
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index 033f7bd..85658d2 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -33,7 +33,7 @@ CATALOG(pg_largeobject_metadata,2995)
 	Oid			lomowner;		/* OID of the largeobject owner */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		lomacl[1];		/* access permissions */
+	aclitem		lomacl[FLEXIBLE_ARRAY_MEMBER];	/* access permissions */
 #endif
 } FormData_pg_largeobject_metadata;
 
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 2c8887c..e1258a8 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -39,7 +39,7 @@ CATALOG(pg_namespace,2615)
 	Oid			nspowner;
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		nspacl[1];
+	aclitem		nspacl[FLEXIBLE_ARRAY_MEMBER];
 #endif
 } FormData_pg_namespace;
 
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
index c5e6554..def9cea 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -39,7 +39,7 @@ CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
 	text		tmplinline;		/* name of anonymous-block handler, or NULL */
 	text		tmplvalidator;	/* name of validator function, or NULL */
 	text		tmpllibrary;	/* path of shared library */
-	aclitem		tmplacl[1];		/* access privileges for template */
+	aclitem		tmplacl[FLEXIBLE_ARRAY_MEMBER];	/* access privileges for template */
 #endif
 } FormData_pg_pltemplate;
 
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
index ae71f3f..87b1b5f 100644
--- a/src/include/catalog/pg_policy.h
+++ b/src/include/catalog/pg_policy.h
@@ -25,7 +25,8 @@ CATALOG(pg_policy,3256)
 	char			polcmd;			/* One of ACL_*_CHR, or '*' for all */
 
 #ifdef CATALOG_VARLEN
-	Oid				polroles[1];	/* Roles associated with policy, not-NULL */
+	Oid				polroles[FLEXIBLE_ARRAY_MEMBER];	/* Roles associated
+														 * with policy, not-NULL */
 	pg_node_tree	polqual;		/* Policy quals. */
 	pg_node_tree	polwithcheck;	/* WITH CHECK quals. */
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 9edfdb8..1efae3f 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -61,15 +61,19 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
 	oidvector	proargtypes;	/* parameter types (excludes OUT params) */
 
 #ifdef CATALOG_VARLEN
-	Oid			proallargtypes[1];		/* all param types (NULL if IN only) */
-	char		proargmodes[1]; /* parameter modes (NULL if IN only) */
-	text		proargnames[1]; /* parameter names (NULL if no names) */
+	Oid			proallargtypes[FLEXIBLE_ARRAY_MEMBER];	/* all param types
+														 * (NULL if IN only) */
+	char		proargmodes[FLEXIBLE_ARRAY_MEMBER];		/* parameter modes
+														 * (NULL if IN only) */
+	text		proargnames[FLEXIBLE_ARRAY_MEMBER];		/* parameter names
+														 * (NULL if no names) */
 	pg_node_tree proargdefaults;/* list of expression trees for argument
 								 * defaults (NULL if none) */
 	text		prosrc;			/* procedure source text */
 	text		probin;			/* secondary procedure info (can be NULL) */
-	text		proconfig[1];	/* procedure-local GUC settings */
-	aclitem		proacl[1];		/* access permissions */
+	text		proconfig[FLEXIBLE_ARRAY_MEMBER];	/* procedure-local GUC
+													 * settings */
+	aclitem		proacl[FLEXIBLE_ARRAY_MEMBER];		/* access permissions */
 #endif
 } FormData_pg_proc;
 
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 62a00fe..a9c695a 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -97,11 +97,11 @@ CATALOG(pg_statistic,2619) BKI_WITHOUT_OIDS
 	Oid			staop5;
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	float4		stanumbers1[1];
-	float4		stanumbers2[1];
-	float4		stanumbers3[1];
-	float4		stanumbers4[1];
-	float4		stanumbers5[1];
+	float4		stanumbers1[FLEXIBLE_ARRAY_MEMBER];
+	float4		stanumbers2[FLEXIBLE_ARRAY_MEMBER];
+	float4		stanumbers3[FLEXIBLE_ARRAY_MEMBER];
+	float4		stanumbers4[FLEXIBLE_ARRAY_MEMBER];
+	float4		stanumbers5[FLEXIBLE_ARRAY_MEMBER];
 
 	/*
 	 * Values in these arrays are values of the column's data type, or of some
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index 24b1d8f..3868d0b 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -34,8 +34,9 @@ CATALOG(pg_tablespace,1213) BKI_SHARED_RELATION
 	Oid			spcowner;		/* owner of tablespace */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	aclitem		spcacl[1];		/* access permissions */
-	text		spcoptions[1];	/* per-tablespace options */
+	aclitem		spcacl[FLEXIBLE_ARRAY_MEMBER];		/* access permissions */
+	text		spcoptions[FLEXIBLE_ARRAY_MEMBER];	/* per-tablespace
+													 * options */
 #endif
 } FormData_pg_tablespace;
 
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 0a900dd..cda6a22 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -221,7 +221,7 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
 	/*
 	 * Access permissions
 	 */
-	aclitem		typacl[1];
+	aclitem		typacl[FLEXIBLE_ARRAY_MEMBER];
 #endif
 } FormData_pg_type;
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 3e76e99..5237be3 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -33,7 +33,7 @@ CATALOG(pg_user_mapping,1418)
 	Oid			umserver;		/* server of this mapping */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
-	text		umoptions[1];	/* user mapping options */
+	text		umoptions[FLEXIBLE_ARRAY_MEMBER];	/* user mapping options */
 #endif
 } FormData_pg_user_mapping;
 
-- 
2.3.0

From ad8f54cdb5776146f17d1038bb295b5f13b549f1 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@otacoo.com>
Date: Mon, 16 Feb 2015 03:53:38 +0900
Subject: [PATCH 3/3] Update varlena in c.h to use FLEXIBLE_ARRAY_MEMBER

Places using a variable-length variable not at the end of a structure
are changed with workaround, without impacting what those features do.
---
 src/backend/access/heap/tuptoaster.c       | 16 ++++++------
 src/backend/storage/large_object/inv_api.c | 40 ++++++++++++++----------------
 src/include/c.h                            |  2 +-
 src/include/catalog/pg_authid.h            |  8 +++---
 4 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index f8c1401..a8f178c 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -1365,12 +1365,7 @@ toast_save_datum(Relation rel, Datum value,
 	CommandId	mycid = GetCurrentCommandId(true);
 	struct varlena *result;
 	struct varatt_external toast_pointer;
-	struct
-	{
-		struct varlena hdr;
-		char		data[TOAST_MAX_CHUNK_SIZE]; /* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			chunk_data;
+	struct varlena *chunk_data;
 	int32		chunk_size;
 	int32		chunk_seq = 0;
 	char	   *data_p;
@@ -1381,6 +1376,9 @@ toast_save_datum(Relation rel, Datum value,
 
 	Assert(!VARATT_IS_EXTERNAL(value));
 
+	chunk_data = (struct varlena *)
+		palloc(MAXALIGN(TOAST_MAX_CHUNK_SIZE + VARHDRSZ));
+
 	/*
 	 * Open the toast relation and its indexes.  We can use the index to check
 	 * uniqueness of the OID we assign to the toasted item, even though it has
@@ -1523,7 +1521,7 @@ toast_save_datum(Relation rel, Datum value,
 	 * Initialize constant parts of the tuple data
 	 */
 	t_values[0] = ObjectIdGetDatum(toast_pointer.va_valueid);
-	t_values[2] = PointerGetDatum(&chunk_data);
+	t_values[2] = PointerGetDatum(chunk_data);
 	t_isnull[0] = false;
 	t_isnull[1] = false;
 	t_isnull[2] = false;
@@ -1546,8 +1544,8 @@ toast_save_datum(Relation rel, Datum value,
 		 * Build a tuple and store it
 		 */
 		t_values[1] = Int32GetDatum(chunk_seq++);
-		SET_VARSIZE(&chunk_data, chunk_size + VARHDRSZ);
-		memcpy(VARDATA(&chunk_data), data_p, chunk_size);
+		SET_VARSIZE(chunk_data, chunk_size + VARHDRSZ);
+		memcpy(VARDATA(chunk_data), data_p, chunk_size);
 		toasttup = heap_form_tuple(toasttupDesc, t_values, t_isnull);
 
 		heap_insert(toastrel, toasttup, mycid, options, NULL);
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index a19c401..b44fae7 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -562,13 +562,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 	bool		neednextpage;
 	bytea	   *datafield;
 	bool		pfreeit;
-	struct
-	{
-		bytea		hdr;
-		char		data[LOBLKSIZE];	/* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			workbuf;
-	char	   *workb = VARDATA(&workbuf.hdr);
+	bytea	   *workbuf;
+	char	   *workb;
 	HeapTuple	newtup;
 	Datum		values[Natts_pg_largeobject];
 	bool		nulls[Natts_pg_largeobject];
@@ -591,6 +586,9 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 				 errmsg("invalid large object write request size: %d",
 						nbytes)));
 
+	workbuf = (bytea *) palloc(MAXALIGN(LOBLKSIZE + VARHDRSZ));
+	workb = VARDATA(workbuf);
+
 	open_lo_relation();
 
 	indstate = CatalogOpenIndexes(lo_heap_r);
@@ -664,7 +662,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			off += n;
 			/* compute valid length of new page */
 			len = (len >= off) ? len : off;
-			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);
+			SET_VARSIZE(workbuf, len + VARHDRSZ);
 
 			/*
 			 * Form and insert updated tuple
@@ -672,7 +670,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			memset(values, 0, sizeof(values));
 			memset(nulls, false, sizeof(nulls));
 			memset(replace, false, sizeof(replace));
-			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 			replace[Anum_pg_largeobject_data - 1] = true;
 			newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r),
 									   values, nulls, replace);
@@ -708,7 +706,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			obj_desc->offset += n;
 			/* compute valid length of new page */
 			len = off + n;
-			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);
+			SET_VARSIZE(workbuf, len + VARHDRSZ);
 
 			/*
 			 * Form and insert updated tuple
@@ -717,7 +715,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			memset(nulls, false, sizeof(nulls));
 			values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);
 			values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
-			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 			newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls);
 			simple_heap_insert(lo_heap_r, newtup);
 			CatalogIndexInsert(indstate, newtup);
@@ -748,13 +746,8 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 	SysScanDesc sd;
 	HeapTuple	oldtuple;
 	Form_pg_largeobject olddata;
-	struct
-	{
-		bytea		hdr;
-		char		data[LOBLKSIZE];	/* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			workbuf;
-	char	   *workb = VARDATA(&workbuf.hdr);
+	bytea	   *workbuf;
+	char	   *workb;
 	HeapTuple	newtup;
 	Datum		values[Natts_pg_largeobject];
 	bool		nulls[Natts_pg_largeobject];
@@ -776,6 +769,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 				 errmsg_internal("invalid large object truncation target: " INT64_FORMAT,
 								 len)));
 
+	workbuf = (bytea *) palloc(MAXALIGN(LOBLKSIZE + VARHDRSZ));
+	workb = VARDATA(workbuf);
+
 	open_lo_relation();
 
 	indstate = CatalogOpenIndexes(lo_heap_r);
@@ -834,7 +830,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 			MemSet(workb + pagelen, 0, off - pagelen);
 
 		/* compute length of new page */
-		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);
+		SET_VARSIZE(workbuf, off + VARHDRSZ);
 
 		/*
 		 * Form and insert updated tuple
@@ -842,7 +838,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 		memset(values, 0, sizeof(values));
 		memset(nulls, false, sizeof(nulls));
 		memset(replace, false, sizeof(replace));
-		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 		replace[Anum_pg_largeobject_data - 1] = true;
 		newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r),
 								   values, nulls, replace);
@@ -873,7 +869,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 			MemSet(workb, 0, off);
 
 		/* compute length of new page */
-		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);
+		SET_VARSIZE(workbuf, off + VARHDRSZ);
 
 		/*
 		 * Form and insert new tuple
@@ -882,7 +878,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 		memset(nulls, false, sizeof(nulls));
 		values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);
 		values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
-		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 		newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls);
 		simple_heap_insert(lo_heap_r, newtup);
 		CatalogIndexInsert(indstate, newtup);
diff --git a/src/include/c.h b/src/include/c.h
index bbd0d53..36ec468 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -391,7 +391,7 @@ typedef struct
 struct varlena
 {
 	char		vl_len_[4];		/* Do not touch this field directly! */
-	char		vl_dat[1];
+	char		vl_dat[FLEXIBLE_ARRAY_MEMBER];
 };
 
 #define VARHDRSZ		((int32) sizeof(int32))
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index e01e6aa..d8789a5 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -56,8 +56,10 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MAC
 	int32		rolconnlimit;	/* max connections allowed (-1=no limit) */
 
 	/* remaining fields may be null; use heap_getattr to read them! */
-	text		rolpassword;	/* password, if any */
 	timestamptz rolvaliduntil;	/* password expiration time, if any */
+#ifdef CATALOG_VARLEN
+	text		rolpassword;	/* password, if any */
+#endif
 } FormData_pg_authid;
 
 #undef timestamptz
@@ -85,8 +87,8 @@ typedef FormData_pg_authid *Form_pg_authid;
 #define Anum_pg_authid_rolreplication	8
 #define Anum_pg_authid_rolbypassrls		9
 #define Anum_pg_authid_rolconnlimit		10
-#define Anum_pg_authid_rolpassword		11
-#define Anum_pg_authid_rolvaliduntil	12
+#define Anum_pg_authid_rolvaliduntil	11
+#define Anum_pg_authid_rolpassword		12
 
 /* ----------------
  *		initial contents of pg_authid
-- 
2.3.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to