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