From 2e211211a76782b6084194a5ced94c0795460047 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 21 Feb 2015 16:12:14 -0500
Subject: [PATCH] Use FLEXIBLE_ARRAY_MEMBER in a number of other places.

I think we're about done with this...
---
 contrib/hstore/hstore_gist.c          |  2 +-
 contrib/spi/timetravel.c              | 25 ++++++++++++++++---------
 src/backend/access/heap/syncscan.c    |  5 +++--
 src/backend/commands/async.c          | 22 +++++++++++-----------
 src/backend/libpq/auth.c              |  3 +--
 src/backend/storage/buffer/freelist.c |  2 +-
 src/backend/storage/ipc/sinvaladt.c   | 13 +++----------
 src/backend/utils/adt/numeric.c       | 10 +++++-----
 src/backend/utils/adt/tsgistidx.c     |  2 +-
 src/backend/utils/adt/tsvector_op.c   |  2 +-
 src/backend/utils/adt/txid.c          |  3 ++-
 src/backend/utils/fmgr/dfmgr.c        | 11 +++--------
 src/backend/utils/sort/logtape.c      | 14 +++++---------
 src/interfaces/ecpg/ecpglib/extern.h  |  2 +-
 14 files changed, 54 insertions(+), 62 deletions(-)

diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index 54e96fca38e..f375f5d3542 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -41,7 +41,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
diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c
index a37cbee8631..0699438d6f6 100644
--- a/contrib/spi/timetravel.c
+++ b/contrib/spi/timetravel.c
@@ -35,10 +35,10 @@ static int	nPlans = 0;
 typedef struct _TTOffList
 {
 	struct _TTOffList *next;
-	char		name[1];
+	char		name[FLEXIBLE_ARRAY_MEMBER];
 } TTOffList;
 
-static TTOffList TTOff = {NULL, {0}};
+static TTOffList *TTOff = NULL;
 
 static int	findTTStatus(char *name);
 static EPlan *find_plan(char *ident, EPlan **eplan, int *nplans);
@@ -428,10 +428,11 @@ set_timetravel(PG_FUNCTION_ARGS)
 	char	   *d;
 	char	   *s;
 	int32		ret;
-	TTOffList  *p,
+	TTOffList  *prev,
 			   *pp;
 
-	for (pp = (p = &TTOff)->next; pp; pp = (p = pp)->next)
+	prev = NULL;
+	for (pp = TTOff; pp; prev = pp, pp = pp->next)
 	{
 		if (namestrcmp(relname, pp->name) == 0)
 			break;
@@ -442,7 +443,10 @@ set_timetravel(PG_FUNCTION_ARGS)
 		if (on != 0)
 		{
 			/* turn ON */
-			p->next = pp->next;
+			if (prev)
+				prev->next = pp->next;
+			else
+				TTOff = pp->next;
 			free(pp);
 		}
 		ret = 0;
@@ -456,15 +460,18 @@ set_timetravel(PG_FUNCTION_ARGS)
 			s = rname = DatumGetCString(DirectFunctionCall1(nameout, NameGetDatum(relname)));
 			if (s)
 			{
-				pp = malloc(sizeof(TTOffList) + strlen(rname));
+				pp = malloc(offsetof(TTOffList, name) +strlen(rname) + 1);
 				if (pp)
 				{
 					pp->next = NULL;
-					p->next = pp;
 					d = pp->name;
 					while (*s)
 						*d++ = tolower((unsigned char) *s++);
 					*d = '\0';
+					if (prev)
+						prev->next = pp;
+					else
+						TTOff = pp;
 				}
 				pfree(rname);
 			}
@@ -486,7 +493,7 @@ get_timetravel(PG_FUNCTION_ARGS)
 	Name		relname = PG_GETARG_NAME(0);
 	TTOffList  *pp;
 
-	for (pp = TTOff.next; pp; pp = pp->next)
+	for (pp = TTOff; pp; pp = pp->next)
 	{
 		if (namestrcmp(relname, pp->name) == 0)
 			PG_RETURN_INT32(0);
@@ -499,7 +506,7 @@ findTTStatus(char *name)
 {
 	TTOffList  *pp;
 
-	for (pp = TTOff.next; pp; pp = pp->next)
+	for (pp = TTOff; pp; pp = pp->next)
 		if (pg_strcasecmp(name, pp->name) == 0)
 			return 0;
 	return 1;
diff --git a/src/backend/access/heap/syncscan.c b/src/backend/access/heap/syncscan.c
index ae7589abefd..266c3309c0b 100644
--- a/src/backend/access/heap/syncscan.c
+++ b/src/backend/access/heap/syncscan.c
@@ -103,10 +103,11 @@ typedef struct ss_scan_locations_t
 {
 	ss_lru_item_t *head;
 	ss_lru_item_t *tail;
-	ss_lru_item_t items[1];		/* SYNC_SCAN_NELEM items */
+	ss_lru_item_t items[FLEXIBLE_ARRAY_MEMBER]; /* SYNC_SCAN_NELEM items */
 } ss_scan_locations_t;
 
-#define SizeOfScanLocations(N) offsetof(ss_scan_locations_t, items[N])
+#define SizeOfScanLocations(N) \
+	(offsetof(ss_scan_locations_t, items) + (N) * sizeof(ss_lru_item_t))
 
 /* Pointer to struct in shared memory */
 static ss_scan_locations_t *scan_locations;
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index d73248ca504..2826b7e43c4 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -237,8 +237,8 @@ typedef struct AsyncQueueControl
 	QueuePosition tail;			/* the global tail is equivalent to the tail
 								 * of the "slowest" backend */
 	TimestampTz lastQueueFillWarn;		/* time of last queue-full msg */
-	QueueBackendStatus backend[1];		/* actually of length MaxBackends+1 */
-	/* DO NOT ADD FURTHER STRUCT MEMBERS HERE */
+	QueueBackendStatus backend[FLEXIBLE_ARRAY_MEMBER];
+	/* backend[0] is not used; used entries are from [1] to [MaxBackends] */
 } AsyncQueueControl;
 
 static AsyncQueueControl *asyncQueueControl;
@@ -303,7 +303,7 @@ typedef enum
 typedef struct
 {
 	ListenActionKind action;
-	char		channel[1];		/* actually, as long as needed */
+	char		channel[FLEXIBLE_ARRAY_MEMBER]; /* nul-terminated string */
 } ListenAction;
 
 static List *pendingActions = NIL;		/* list of ListenAction */
@@ -417,8 +417,8 @@ AsyncShmemSize(void)
 	Size		size;
 
 	/* This had better match AsyncShmemInit */
-	size = mul_size(MaxBackends, sizeof(QueueBackendStatus));
-	size = add_size(size, sizeof(AsyncQueueControl));
+	size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus));
+	size = add_size(size, offsetof(AsyncQueueControl, backend));
 
 	size = add_size(size, SimpleLruShmemSize(NUM_ASYNC_BUFFERS, 0));
 
@@ -438,12 +438,11 @@ AsyncShmemInit(void)
 	/*
 	 * Create or attach to the AsyncQueueControl structure.
 	 *
-	 * The used entries in the backend[] array run from 1 to MaxBackends.
-	 * sizeof(AsyncQueueControl) already includes space for the unused zero'th
-	 * entry, but we need to add on space for the used entries.
+	 * The used entries in the backend[] array run from 1 to MaxBackends; the
+	 * zero'th entry is unused but must be allocated.
 	 */
-	size = mul_size(MaxBackends, sizeof(QueueBackendStatus));
-	size = add_size(size, sizeof(AsyncQueueControl));
+	size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus));
+	size = add_size(size, offsetof(AsyncQueueControl, backend));
 
 	asyncQueueControl = (AsyncQueueControl *)
 		ShmemInitStruct("Async Queue Control", size, &found);
@@ -605,7 +604,8 @@ queue_listen(ListenActionKind action, const char *channel)
 	oldcontext = MemoryContextSwitchTo(CurTransactionContext);
 
 	/* space for terminating null is included in sizeof(ListenAction) */
-	actrec = (ListenAction *) palloc(sizeof(ListenAction) + strlen(channel));
+	actrec = (ListenAction *) palloc(offsetof(ListenAction, channel) +
+									 strlen(channel) + 1);
 	actrec->action = action;
 	strcpy(actrec->channel, channel);
 
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 346f8080494..28b050af0e2 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -2172,7 +2172,7 @@ typedef struct
 {
 	uint8		attribute;
 	uint8		length;
-	uint8		data[1];
+	uint8		data[FLEXIBLE_ARRAY_MEMBER];
 } radius_attribute;
 
 typedef struct
@@ -2220,7 +2220,6 @@ radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *dat
 			 "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
 			 type, len);
 		return;
-
 	}
 
 	attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
index 0d1cbd15531..f0d23d68582 100644
--- a/src/backend/storage/buffer/freelist.c
+++ b/src/backend/storage/buffer/freelist.c
@@ -93,7 +93,7 @@ typedef struct BufferAccessStrategyData
 	 * simplicity this is palloc'd together with the fixed fields of the
 	 * struct.
 	 */
-	Buffer		buffers[1];		/* VARIABLE SIZE ARRAY */
+	Buffer		buffers[FLEXIBLE_ARRAY_MEMBER];
 }	BufferAccessStrategyData;
 
 
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index bb3e604e671..81b85c0e420 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -184,12 +184,9 @@ typedef struct SISeg
 	SharedInvalidationMessage buffer[MAXNUMMESSAGES];
 
 	/*
-	 * Per-backend state info.
-	 *
-	 * We declare procState as 1 entry because C wants a fixed-size array, but
-	 * actually it is maxBackends entries long.
+	 * Per-backend invalidation state info (has MaxBackends entries).
 	 */
-	ProcState	procState[1];	/* reflects the invalidation state */
+	ProcState	procState[FLEXIBLE_ARRAY_MEMBER];
 } SISeg;
 
 static SISeg *shmInvalBuffer;	/* pointer to the shared inval buffer */
@@ -221,16 +218,12 @@ SInvalShmemSize(void)
 void
 CreateSharedInvalidationState(void)
 {
-	Size		size;
 	int			i;
 	bool		found;
 
 	/* Allocate space in shared memory */
-	size = offsetof(SISeg, procState);
-	size = add_size(size, mul_size(sizeof(ProcState), MaxBackends));
-
 	shmInvalBuffer = (SISeg *)
-		ShmemInitStruct("shmInvalBuffer", size, &found);
+		ShmemInitStruct("shmInvalBuffer", SInvalShmemSize(), &found);
 	if (found)
 		return;
 
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 1e7a176c60d..715917bab34 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -123,14 +123,14 @@ typedef int16 NumericDigit;
 struct NumericShort
 {
 	uint16		n_header;		/* Sign + display scale + weight */
-	NumericDigit n_data[1];		/* Digits */
+	NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
 };
 
 struct NumericLong
 {
 	uint16		n_sign_dscale;	/* Sign + display scale */
 	int16		n_weight;		/* Weight of 1st digit	*/
-	NumericDigit n_data[1];		/* Digits */
+	NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
 };
 
 union NumericChoice
@@ -1262,7 +1262,7 @@ numeric_floor(PG_FUNCTION_ARGS)
 /*
  * generate_series_numeric() -
  *
- *  Generate series of numeric.
+ *	Generate series of numeric.
  */
 Datum
 generate_series_numeric(PG_FUNCTION_ARGS)
@@ -1297,7 +1297,7 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
 		/* see if we were given an explicit step size */
 		if (PG_NARGS() == 3)
 		{
-			Numeric	step_num = PG_GETARG_NUMERIC(2);
+			Numeric		step_num = PG_GETARG_NUMERIC(2);
 
 			if (NUMERIC_IS_NAN(step_num))
 				ereport(ERROR,
@@ -1356,7 +1356,7 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
 		(fctx->step.sign == NUMERIC_NEG &&
 		 cmp_var(&fctx->current, &fctx->stop) >= 0))
 	{
-		Numeric	result = make_result(&fctx->current);
+		Numeric		result = make_result(&fctx->current);
 
 		/* switch to memory context appropriate for iteration calculation */
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index b56aa91bcb4..25132be441a 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -50,7 +50,7 @@ typedef struct
 {
 	int32		vl_len_;		/* varlena header (do not touch directly!) */
 	int32		flag;
-	char		data[1];
+	char		data[FLEXIBLE_ARRAY_MEMBER];
 } SignTSVector;
 
 #define ARRKEY		0x01
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index 3ac15f4d1f0..266a728ef6a 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -44,7 +44,7 @@ typedef struct StatEntry
 	struct StatEntry *left;
 	struct StatEntry *right;
 	uint32		lenlexeme;
-	char		lexeme[1];
+	char		lexeme[FLEXIBLE_ARRAY_MEMBER];
 } StatEntry;
 
 #define STATENTRYHDRSZ	(offsetof(StatEntry, lexeme))
diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
index 8c7fe7018ab..f973ef936c5 100644
--- a/src/backend/utils/adt/txid.c
+++ b/src/backend/utils/adt/txid.c
@@ -64,7 +64,8 @@ typedef struct
 	uint32		nxip;			/* number of txids in xip array */
 	txid		xmin;
 	txid		xmax;
-	txid		xip[1];			/* in-progress txids, xmin <= xip[i] < xmax */
+	/* in-progress txids, xmin <= xip[i] < xmax: */
+	txid		xip[FLEXIBLE_ARRAY_MEMBER];
 } TxidSnapshot;
 
 #define TXID_SNAPSHOT_SIZE(nxip) \
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 1b6932235cb..7476a26b791 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -51,12 +51,7 @@ typedef struct df_files
 	ino_t		inode;			/* Inode number of file */
 #endif
 	void	   *handle;			/* a handle for pg_dl* functions */
-	char		filename[1];	/* Full pathname of file */
-
-	/*
-	 * we allocate the block big enough for actual length of pathname.
-	 * filename[] must be last item in struct!
-	 */
+	char		filename[FLEXIBLE_ARRAY_MEMBER];		/* Full pathname of file */
 } DynamicFileList;
 
 static DynamicFileList *file_list = NULL;
@@ -217,13 +212,13 @@ internal_load_library(const char *libname)
 		 * File not loaded yet.
 		 */
 		file_scanner = (DynamicFileList *)
-			malloc(sizeof(DynamicFileList) + strlen(libname));
+			malloc(offsetof(DynamicFileList, filename) +strlen(libname) + 1);
 		if (file_scanner == NULL)
 			ereport(ERROR,
 					(errcode(ERRCODE_OUT_OF_MEMORY),
 					 errmsg("out of memory")));
 
-		MemSet(file_scanner, 0, sizeof(DynamicFileList));
+		MemSet(file_scanner, 0, offsetof(DynamicFileList, filename));
 		strcpy(file_scanner->filename, libname);
 		file_scanner->device = stat_buf.st_dev;
 #ifndef WIN32
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 21030423ed2..252ba220712 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -166,12 +166,9 @@ struct LogicalTapeSet
 	int			nFreeBlocks;	/* # of currently free blocks */
 	int			freeBlocksLen;	/* current allocated length of freeBlocks[] */
 
-	/*
-	 * tapes[] is declared size 1 since C wants a fixed size, but actually it
-	 * is of length nTapes.
-	 */
+	/* The array of logical tapes. */
 	int			nTapes;			/* # of logical tapes in set */
-	LogicalTape tapes[1];		/* must be last in struct! */
+	LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER];	/* has nTapes nentries */
 };
 
 static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
@@ -519,12 +516,11 @@ LogicalTapeSetCreate(int ntapes)
 	int			i;
 
 	/*
-	 * Create top-level struct including per-tape LogicalTape structs. First
-	 * LogicalTape struct is already counted in sizeof(LogicalTapeSet).
+	 * Create top-level struct including per-tape LogicalTape structs.
 	 */
 	Assert(ntapes > 0);
-	lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
-									(ntapes - 1) *sizeof(LogicalTape));
+	lts = (LogicalTapeSet *) palloc(offsetof(LogicalTapeSet, tapes) +
+									ntapes * sizeof(LogicalTape));
 	lts->pfile = BufFileCreateTemp(false);
 	lts->nFileBlocks = 0L;
 	lts->forgetFreeSpace = false;
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index 2b670e0d004..ca3bf051816 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -33,7 +33,7 @@ enum ARRAY_TYPE
 struct ECPGgeneric_varchar
 {
 	int			len;
-	char		arr[1];
+	char		arr[FLEXIBLE_ARRAY_MEMBER];
 };
 
 /*
-- 
GitLab