On Mon, Feb 12, 2024 at 4:57 PM Nathan Bossart <nathandboss...@gmail.com> wrote:
> On Sun, Feb 11, 2024 at 03:44:42PM +0100, Mats Kindahl wrote: > > On Sat, Feb 10, 2024 at 9:53 PM Nathan Bossart <nathandboss...@gmail.com > > > > wrote: > >> and I think we should expand on some of the commentary in int.h. > >> For example, the comment at the top of int.h seems very tailored to the > >> existing functions and should probably be adjusted. > > > > > > I rewrote the beginning to the following, does that look good? > > > > * int.h > > * Routines to perform signed and unsigned integer arithmetics, > including > > * comparisons, in an overflow-safe way. > > > > > > > >> And the "comparison > >> routines for integers" comment might benefit from some additional > details > >> about the purpose and guarantees of the new functions. > >> > > > > I expanded that into the following. WDYT? > > > > > /*------------------------------------------------------------------------ > > * Comparison routines for integers. > > * > > * These routines are used to implement comparison functions for, e.g., > > * qsort(). They are designed to be efficient and not risk overflows in > > * internal computations that could cause strange results, such as > INT_MIN > > > * INT_MAX if you just return "lhs - rhs". > > > *------------------------------------------------------------------------ > > LGTM. I might editorialize a bit before committing, but I think your > proposed wording illustrates the thrust of the change. > Thanks Nathan, Here are the two fixed patches. Best wishes, Mats Kindahl > > -- > Nathan Bossart > Amazon Web Services: https://aws.amazon.com >
From b68f08b6afd62b75755e88f11a3ca31cfdce2645 Mon Sep 17 00:00:00 2001 From: Mats Kindahl <m...@timescale.com> Date: Fri, 9 Feb 2024 21:48:27 +0100 Subject: Use integer comparison functions Use overflow-safe integer functions when implementing qsort() comparison functions. --- contrib/hstore/hstore_gist.c | 3 ++- contrib/intarray/_intbig_gist.c | 3 ++- contrib/pg_stat_statements/pg_stat_statements.c | 8 ++------ contrib/pg_trgm/trgm_op.c | 8 ++------ src/backend/access/nbtree/nbtinsert.c | 8 ++------ src/backend/access/nbtree/nbtpage.c | 10 +++------- src/backend/access/nbtree/nbtsplitloc.c | 8 ++------ src/backend/access/spgist/spgdoinsert.c | 5 ++--- src/backend/access/spgist/spgtextproc.c | 3 ++- src/backend/backup/basebackup_incremental.c | 8 ++------ src/backend/backup/walsummary.c | 7 ++----- src/backend/catalog/heap.c | 8 ++------ src/backend/nodes/list.c | 13 +++---------- src/backend/nodes/tidbitmap.c | 7 ++----- src/backend/parser/parse_agg.c | 7 ++++--- src/backend/postmaster/autovacuum.c | 6 ++---- src/backend/replication/logical/reorderbuffer.c | 7 ++----- src/backend/replication/syncrep.c | 8 ++------ src/backend/utils/adt/oid.c | 7 ++----- src/backend/utils/adt/tsgistidx.c | 10 +++------- src/backend/utils/adt/tsquery_gist.c | 6 ++---- src/backend/utils/adt/tsvector.c | 5 ++--- src/backend/utils/adt/tsvector_op.c | 5 ++--- src/backend/utils/adt/xid.c | 7 ++----- src/backend/utils/cache/relcache.c | 3 ++- src/backend/utils/cache/syscache.c | 5 ++--- src/backend/utils/cache/typcache.c | 8 ++------ src/backend/utils/resowner/resowner.c | 10 ++-------- src/bin/pg_dump/pg_dump_sort.c | 7 ++----- src/bin/pg_upgrade/function.c | 13 +++++++------ src/bin/pg_walsummary/pg_walsummary.c | 8 ++------ src/bin/psql/crosstabview.c | 3 ++- src/include/access/gin_private.h | 8 ++------ 33 files changed, 76 insertions(+), 156 deletions(-) diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c index fe343739eb..1079f25bf7 100644 --- a/contrib/hstore/hstore_gist.c +++ b/contrib/hstore/hstore_gist.c @@ -7,6 +7,7 @@ #include "access/reloptions.h" #include "access/stratnum.h" #include "catalog/pg_type.h" +#include "common/int.h" #include "hstore.h" #include "utils/pg_crc.h" @@ -356,7 +357,7 @@ typedef struct static int comparecost(const void *a, const void *b) { - return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost; + return pg_cmp_s32(((const SPLITCOST *) a)->cost, ((const SPLITCOST *) b)->cost); } diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c index 8c6c4b5d05..aef9e13dcc 100644 --- a/contrib/intarray/_intbig_gist.c +++ b/contrib/intarray/_intbig_gist.c @@ -9,6 +9,7 @@ #include "access/gist.h" #include "access/reloptions.h" #include "access/stratnum.h" +#include "common/int.h" #include "port/pg_bitutils.h" #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key)) @@ -312,7 +313,7 @@ typedef struct static int comparecost(const void *a, const void *b) { - return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost; + return pg_cmp_s32(((const SPLITCOST *) a)->cost, ((const SPLITCOST *) b)->cost); } diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 8c6a3a2d08..67cec865ba 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -50,6 +50,7 @@ #include "access/parallel.h" #include "catalog/pg_authid.h" #include "common/hashfn.h" +#include "common/int.h" #include "executor/instrument.h" #include "funcapi.h" #include "jit/jit.h" @@ -3007,10 +3008,5 @@ comp_location(const void *a, const void *b) int l = ((const LocationLen *) a)->location; int r = ((const LocationLen *) b)->location; - if (l < r) - return -1; - else if (l > r) - return +1; - else - return 0; + return pg_cmp_s32(l, r); } diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c index 49d4497b4f..c509d15ee4 100644 --- a/contrib/pg_trgm/trgm_op.c +++ b/contrib/pg_trgm/trgm_op.c @@ -6,6 +6,7 @@ #include <ctype.h> #include "catalog/pg_type.h" +#include "common/int.h" #include "lib/qunique.h" #include "miscadmin.h" #include "trgm.h" @@ -433,12 +434,7 @@ comp_ptrgm(const void *v1, const void *v2) if (cmp != 0) return cmp; - if (p1->index < p2->index) - return -1; - else if (p1->index == p2->index) - return 0; - else - return 1; + return pg_cmp_s32(p1->index, p2->index); } /* diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 709edd1c17..9cfe4cc094 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -20,6 +20,7 @@ #include "access/transam.h" #include "access/xloginsert.h" #include "common/pg_prng.h" +#include "common/int.h" #include "lib/qunique.h" #include "miscadmin.h" #include "storage/lmgr.h" @@ -3013,10 +3014,5 @@ _bt_blk_cmp(const void *arg1, const void *arg2) BlockNumber b1 = *((BlockNumber *) arg1); BlockNumber b2 = *((BlockNumber *) arg2); - if (b1 < b2) - return -1; - else if (b1 > b2) - return 1; - - return 0; + return pg_cmp_u32(b1, b2); } diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 567bade9f4..0f712cea57 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -28,6 +28,7 @@ #include "access/transam.h" #include "access/xlog.h" #include "access/xloginsert.h" +#include "common/int.h" #include "miscadmin.h" #include "storage/indexfsm.h" #include "storage/lmgr.h" @@ -1466,14 +1467,9 @@ _bt_delitems_cmp(const void *a, const void *b) TM_IndexDelete *indexdelete1 = (TM_IndexDelete *) a; TM_IndexDelete *indexdelete2 = (TM_IndexDelete *) b; - if (indexdelete1->id > indexdelete2->id) - return 1; - if (indexdelete1->id < indexdelete2->id) - return -1; + Assert(pg_cmp_s16(indexdelete1->id, indexdelete2->id) != 0); - Assert(false); - - return 0; + return pg_cmp_s16(indexdelete1->id, indexdelete2->id); } /* diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c index d0b1d82578..0bcc8e90ae 100644 --- a/src/backend/access/nbtree/nbtsplitloc.c +++ b/src/backend/access/nbtree/nbtsplitloc.c @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/nbtree.h" +#include "common/int.h" #include "storage/lmgr.h" typedef enum @@ -596,12 +597,7 @@ _bt_splitcmp(const void *arg1, const void *arg2) SplitPoint *split1 = (SplitPoint *) arg1; SplitPoint *split2 = (SplitPoint *) arg2; - if (split1->curdelta > split2->curdelta) - return 1; - if (split1->curdelta < split2->curdelta) - return -1; - - return 0; + return pg_cmp_s16(split1->curdelta, split2->curdelta); } /* diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c index bb063c858d..8695370139 100644 --- a/src/backend/access/spgist/spgdoinsert.c +++ b/src/backend/access/spgist/spgdoinsert.c @@ -20,6 +20,7 @@ #include "access/spgxlog.h" #include "access/xloginsert.h" #include "common/pg_prng.h" +#include "common/int.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/rel.h" @@ -110,9 +111,7 @@ addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset) static int cmpOffsetNumbers(const void *a, const void *b) { - if (*(const OffsetNumber *) a == *(const OffsetNumber *) b) - return 0; - return (*(const OffsetNumber *) a > *(const OffsetNumber *) b) ? 1 : -1; + return pg_cmp_u16(*(const OffsetNumber *) a, *(const OffsetNumber *) b); } /* diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d5db5225a9 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -40,6 +40,7 @@ #include "postgres.h" #include "access/spgist.h" +#include "common/int.h" #include "catalog/pg_type.h" #include "mb/pg_wchar.h" #include "utils/builtins.h" @@ -325,7 +326,7 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + return pg_cmp_s16(aa->c, bb->c); } Datum diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c index 0504c465db..d08dfb740b 100644 --- a/src/backend/backup/basebackup_incremental.c +++ b/src/backend/backup/basebackup_incremental.c @@ -27,6 +27,7 @@ #include "common/blkreftable.h" #include "common/parse_manifest.h" #include "common/hashfn.h" +#include "common/int.h" #include "postmaster/walsummarizer.h" #define BLOCKS_PER_READ 512 @@ -994,10 +995,5 @@ compare_block_numbers(const void *a, const void *b) BlockNumber aa = *(BlockNumber *) a; BlockNumber bb = *(BlockNumber *) b; - if (aa > bb) - return 1; - else if (aa == bb) - return 0; - else - return -1; + return pg_cmp_u32(aa,bb); } diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c index 867870aaad..4d047e1c02 100644 --- a/src/backend/backup/walsummary.c +++ b/src/backend/backup/walsummary.c @@ -17,6 +17,7 @@ #include "access/xlog_internal.h" #include "backup/walsummary.h" +#include "common/int.h" #include "utils/wait_event.h" static bool IsWalSummaryFilename(char *filename); @@ -355,9 +356,5 @@ ListComparatorForWalSummaryFiles(const ListCell *a, const ListCell *b) WalSummaryFile *ws1 = lfirst(a); WalSummaryFile *ws2 = lfirst(b); - if (ws1->start_lsn < ws2->start_lsn) - return -1; - if (ws1->start_lsn > ws2->start_lsn) - return 1; - return 0; + return pg_cmp_u64(ws1->start_lsn, ws2->start_lsn); } diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index c73f7bcd01..f8145d4cf5 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -56,6 +56,7 @@ #include "catalog/storage.h" #include "commands/tablecmds.h" #include "commands/typecmds.h" +#include "common/int.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" @@ -2758,12 +2759,7 @@ list_cookedconstr_attnum_cmp(const ListCell *p1, const ListCell *p2) { AttrNumber v1 = ((CookedConstraint *) lfirst(p1))->attnum; AttrNumber v2 = ((CookedConstraint *) lfirst(p2))->attnum; - - if (v1 < v2) - return -1; - if (v1 > v2) - return 1; - return 0; + return pg_cmp_s16(v1, v2); } /* diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index 957186bef5..e2615ab105 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -17,6 +17,7 @@ */ #include "postgres.h" +#include "common/int.h" #include "nodes/pg_list.h" #include "port/pg_bitutils.h" #include "utils/memdebug.h" @@ -1692,11 +1693,7 @@ list_int_cmp(const ListCell *p1, const ListCell *p2) int v1 = lfirst_int(p1); int v2 = lfirst_int(p2); - if (v1 < v2) - return -1; - if (v1 > v2) - return 1; - return 0; + return pg_cmp_s32(v1, v2); } /* @@ -1708,9 +1705,5 @@ list_oid_cmp(const ListCell *p1, const ListCell *p2) Oid v1 = lfirst_oid(p1); Oid v2 = lfirst_oid(p2); - if (v1 < v2) - return -1; - if (v1 > v2) - return 1; - return 0; + return pg_cmp_u32(v1, v2); } diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index 0f4850065f..79e54ba111 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -42,6 +42,7 @@ #include "access/htup_details.h" #include "common/hashfn.h" +#include "common/int.h" #include "nodes/bitmapset.h" #include "nodes/tidbitmap.h" #include "storage/lwlock.h" @@ -1425,11 +1426,7 @@ tbm_comparator(const void *left, const void *right) BlockNumber l = (*((PagetableEntry *const *) left))->blockno; BlockNumber r = (*((PagetableEntry *const *) right))->blockno; - if (l < r) - return -1; - else if (l > r) - return 1; - return 0; + return pg_cmp_u32(l,r); } /* diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 7b211a7743..a50d799f03 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -18,6 +18,7 @@ #include "catalog/pg_aggregate.h" #include "catalog/pg_constraint.h" #include "catalog/pg_type.h" +#include "common/int.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" @@ -1757,10 +1758,10 @@ expand_groupingset_node(GroupingSet *gs) static int cmp_list_len_asc(const ListCell *a, const ListCell *b) { - int la = list_length((const List *) lfirst(a)); - int lb = list_length((const List *) lfirst(b)); + size_t la = list_length((const List *) lfirst(a)); + size_t lb = list_length((const List *) lfirst(b)); - return (la > lb) ? 1 : (la == lb) ? 0 : -1; + return pg_cmp_size(la, lb); } /* list_sort comparator to sort sub-lists by length and contents */ diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 2c3099f76f..483244254f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -78,6 +78,7 @@ #include "catalog/pg_database.h" #include "commands/dbcommands.h" #include "commands/vacuum.h" +#include "common/int.h" #include "lib/ilist.h" #include "libpq/pqsignal.h" #include "miscadmin.h" @@ -1119,10 +1120,7 @@ rebuild_database_list(Oid newdb) static int db_comparator(const void *a, const void *b) { - if (((const avl_dbase *) a)->adl_score == ((const avl_dbase *) b)->adl_score) - return 0; - else - return (((const avl_dbase *) a)->adl_score < ((const avl_dbase *) b)->adl_score) ? 1 : -1; + return pg_cmp_s32(((const avl_dbase *) a)->adl_score, ((const avl_dbase *) b)->adl_score); } /* diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index bbf0966182..5446df3c64 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -91,6 +91,7 @@ #include "access/xact.h" #include "access/xlog_internal.h" #include "catalog/catalog.h" +#include "common/int.h" #include "lib/binaryheap.h" #include "miscadmin.h" #include "pgstat.h" @@ -5119,11 +5120,7 @@ file_sort_by_lsn(const ListCell *a_p, const ListCell *b_p) RewriteMappingFile *a = (RewriteMappingFile *) lfirst(a_p); RewriteMappingFile *b = (RewriteMappingFile *) lfirst(b_p); - if (a->lsn < b->lsn) - return -1; - else if (a->lsn > b->lsn) - return 1; - return 0; + return pg_cmp_u64(a->lsn, b->lsn); } /* diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 2e6493aaaa..bfcd8fa13e 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -75,6 +75,7 @@ #include <unistd.h> #include "access/xact.h" +#include "common/int.h" #include "miscadmin.h" #include "pgstat.h" #include "replication/syncrep.h" @@ -698,12 +699,7 @@ cmp_lsn(const void *a, const void *b) XLogRecPtr lsn1 = *((const XLogRecPtr *) a); XLogRecPtr lsn2 = *((const XLogRecPtr *) b); - if (lsn1 > lsn2) - return -1; - else if (lsn1 == lsn2) - return 0; - else - return 1; + return pg_cmp_u64(lsn2, lsn1); } /* diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 62bcfc5b56..56fb1fd77c 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -18,6 +18,7 @@ #include <limits.h> #include "catalog/pg_type.h" +#include "common/int.h" #include "libpq/pqformat.h" #include "nodes/miscnodes.h" #include "nodes/value.h" @@ -259,11 +260,7 @@ oid_cmp(const void *p1, const void *p2) Oid v1 = *((const Oid *) p1); Oid v2 = *((const Oid *) p2); - if (v1 < v2) - return -1; - if (v1 > v2) - return 1; - return 0; + return pg_cmp_u32(v1, v2); } diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c index a62b285365..225f0d49cb 100644 --- a/src/backend/utils/adt/tsgistidx.c +++ b/src/backend/utils/adt/tsgistidx.c @@ -17,6 +17,7 @@ #include "access/gist.h" #include "access/heaptoast.h" #include "access/reloptions.h" +#include "common/int.h" #include "lib/qunique.h" #include "port/pg_bitutils.h" #include "tsearch/ts_utils.h" @@ -136,9 +137,7 @@ compareint(const void *va, const void *vb) int32 a = *((const int32 *) va); int32 b = *((const int32 *) vb); - if (a == b) - return 0; - return (a > b) ? 1 : -1; + return pg_cmp_s32(a,b); } static void @@ -598,10 +597,7 @@ comparecost(const void *va, const void *vb) const SPLITCOST *a = (const SPLITCOST *) va; const SPLITCOST *b = (const SPLITCOST *) vb; - if (a->cost == b->cost) - return 0; - else - return (a->cost > b->cost) ? 1 : -1; + return pg_cmp_s32(a->cost, b->cost); } diff --git a/src/backend/utils/adt/tsquery_gist.c b/src/backend/utils/adt/tsquery_gist.c index f0b1c81c81..0b3355f7fe 100644 --- a/src/backend/utils/adt/tsquery_gist.c +++ b/src/backend/utils/adt/tsquery_gist.c @@ -16,6 +16,7 @@ #include "access/gist.h" #include "access/stratnum.h" +#include "common/int.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" @@ -156,10 +157,7 @@ typedef struct static int comparecost(const void *a, const void *b) { - if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost) - return 0; - else - return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1; + return pg_cmp_s32(((const SPLITCOST *) a)->cost, ((const SPLITCOST *) b)->cost); } #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) ) diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c index fb7b7c712a..10bc4f2234 100644 --- a/src/backend/utils/adt/tsvector.c +++ b/src/backend/utils/adt/tsvector.c @@ -14,6 +14,7 @@ #include "postgres.h" +#include "common/int.h" #include "libpq/pqformat.h" #include "nodes/miscnodes.h" #include "tsearch/ts_locale.h" @@ -37,9 +38,7 @@ compareWordEntryPos(const void *a, const void *b) int apos = WEP_GETPOS(*(const WordEntryPos *) a); int bpos = WEP_GETPOS(*(const WordEntryPos *) b); - if (apos == bpos) - return 0; - return (apos > bpos) ? 1 : -1; + return pg_cmp_s32(apos, bpos); } /* diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 71386d0a1f..70bdc09dd7 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -19,6 +19,7 @@ #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "commands/trigger.h" +#include "common/int.h" #include "executor/spi.h" #include "funcapi.h" #include "lib/qunique.h" @@ -435,9 +436,7 @@ compare_int(const void *va, const void *vb) int a = *((const int *) va); int b = *((const int *) vb); - if (a == b) - return 0; - return (a > b) ? 1 : -1; + return pg_cmp_s32(a,b); } static int diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c index 63adf5668b..ae273b1961 100644 --- a/src/backend/utils/adt/xid.c +++ b/src/backend/utils/adt/xid.c @@ -19,6 +19,7 @@ #include "access/multixact.h" #include "access/transam.h" #include "access/xact.h" +#include "common/int.h" #include "libpq/pqformat.h" #include "utils/builtins.h" #include "utils/xid8.h" @@ -140,11 +141,7 @@ xidComparator(const void *arg1, const void *arg2) TransactionId xid1 = *(const TransactionId *) arg1; TransactionId xid2 = *(const TransactionId *) arg2; - if (xid1 > xid2) - return 1; - if (xid1 < xid2) - return -1; - return 0; + return pg_cmp_u32(xid1, xid2); } /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..50acae4529 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -69,6 +69,7 @@ #include "commands/policy.h" #include "commands/publicationcmds.h" #include "commands/trigger.h" +#include "common/int.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -4520,7 +4521,7 @@ AttrDefaultCmp(const void *a, const void *b) const AttrDefault *ada = (const AttrDefault *) a; const AttrDefault *adb = (const AttrDefault *) b; - return ada->adnum - adb->adnum; + return pg_cmp_s16(ada->adnum, adb->adnum); } /* diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 162855b158..a7c9c23399 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -29,6 +29,7 @@ #include "catalog/pg_shdepend_d.h" #include "catalog/pg_shdescription_d.h" #include "catalog/pg_shseclabel_d.h" +#include "common/int.h" #include "lib/qunique.h" #include "utils/catcache.h" #include "utils/lsyscache.h" @@ -676,7 +677,5 @@ oid_compare(const void *a, const void *b) Oid oa = *((const Oid *) a); Oid ob = *((const Oid *) b); - if (oa == ob) - return 0; - return (oa > ob) ? 1 : -1; + return pg_cmp_u32(oa, ob); } diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 84fc83cb11..2842bde907 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -57,6 +57,7 @@ #include "catalog/pg_range.h" #include "catalog/pg_type.h" #include "commands/defrem.h" +#include "common/int.h" #include "executor/executor.h" #include "lib/dshash.h" #include "optimizer/optimizer.h" @@ -2722,12 +2723,7 @@ enum_oid_cmp(const void *left, const void *right) const EnumItem *l = (const EnumItem *) left; const EnumItem *r = (const EnumItem *) right; - if (l->enum_oid < r->enum_oid) - return -1; - else if (l->enum_oid > r->enum_oid) - return 1; - else - return 0; + return pg_cmp_u32(l->enum_oid, r->enum_oid); } /* diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index aa199b23ff..ab9343bc5c 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -46,6 +46,7 @@ #include "postgres.h" #include "common/hashfn.h" +#include "common/int.h" #include "storage/ipc.h" #include "storage/predicate.h" #include "storage/proc.h" @@ -264,14 +265,7 @@ resource_priority_cmp(const void *a, const void *b) /* Note: reverse order */ if (ra->kind->release_phase == rb->kind->release_phase) - { - if (ra->kind->release_priority == rb->kind->release_priority) - return 0; - else if (ra->kind->release_priority > rb->kind->release_priority) - return -1; - else - return 1; - } + return pg_cmp_u32(rb->kind->release_priority, ra->kind->release_priority); else if (ra->kind->release_phase > rb->kind->release_phase) return -1; else diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index f358dd22b9..8ee8a42781 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -16,6 +16,7 @@ #include "postgres_fe.h" #include "catalog/pg_class_d.h" +#include "common/int.h" #include "lib/binaryheap.h" #include "pg_backup_archiver.h" #include "pg_backup_utils.h" @@ -1504,9 +1505,5 @@ int_cmp(void *a, void *b, void *arg) int ai = (int) (intptr_t) a; int bi = (int) (intptr_t) b; - if (ai < bi) - return -1; - if (ai > bi) - return 1; - return 0; + return pg_cmp_s32(ai, bi); } diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..3cbe2e5f1c 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -11,6 +11,7 @@ #include "access/transam.h" #include "catalog/pg_language_d.h" +#include "common/int.h" #include "pg_upgrade.h" /* @@ -29,17 +30,17 @@ library_name_compare(const void *p1, const void *p2) { const char *str1 = ((const LibraryInfo *) p1)->name; const char *str2 = ((const LibraryInfo *) p2)->name; - int slen1 = strlen(str1); - int slen2 = strlen(str2); + size_t slen1 = strlen(str1); + size_t slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int lhsdb = ((const LibraryInfo *) p1)->dbnum; + int rhsdb = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return pg_cmp_size(slen1, slen2); if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + return pg_cmp_s32(lhsdb, rhsdb); } diff --git a/src/bin/pg_walsummary/pg_walsummary.c b/src/bin/pg_walsummary/pg_walsummary.c index 1341c83c69..39f77d159b 100644 --- a/src/bin/pg_walsummary/pg_walsummary.c +++ b/src/bin/pg_walsummary/pg_walsummary.c @@ -17,6 +17,7 @@ #include "common/blkreftable.h" #include "common/logging.h" +#include "common/int.h" #include "fe_utils/option_utils.h" #include "lib/stringinfo.h" #include "getopt_long.h" @@ -219,12 +220,7 @@ compare_block_numbers(const void *a, const void *b) BlockNumber aa = *(BlockNumber *) a; BlockNumber bb = *(BlockNumber *) b; - if (aa > bb) - return 1; - else if (aa == bb) - return 0; - else - return -1; + return pg_cmp_u32(aa, bb); } /* diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..305ed4ab0a 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -8,6 +8,7 @@ #include "postgres_fe.h" #include "common.h" +#include "common/int.h" #include "common/logging.h" #include "crosstabview.h" #include "pqexpbuffer.h" @@ -709,5 +710,5 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + return pg_cmp_s32(*(const int *) a, *(const int *) b); } diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 51d0c74a6b..3013a44bae 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -14,6 +14,7 @@ #include "access/gin.h" #include "access/ginblock.h" #include "access/itup.h" +#include "common/int.h" #include "catalog/pg_am_d.h" #include "fmgr.h" #include "lib/rbtree.h" @@ -489,12 +490,7 @@ ginCompareItemPointers(ItemPointer a, ItemPointer b) uint64 ia = (uint64) GinItemPointerGetBlockNumber(a) << 32 | GinItemPointerGetOffsetNumber(a); uint64 ib = (uint64) GinItemPointerGetBlockNumber(b) << 32 | GinItemPointerGetOffsetNumber(b); - if (ia == ib) - return 0; - else if (ia > ib) - return 1; - else - return -1; + return pg_cmp_u64(ia, ib); } extern int ginTraverseLock(Buffer buffer, bool searchMode); -- 2.34.1
From c7e912f36f193b299a42c6e98dc31a78d9957395 Mon Sep 17 00:00:00 2001 From: Mats Kindahl <m...@timescale.com> Date: Fri, 9 Feb 2024 21:24:42 +0100 Subject: Add integer comparison functions Introduce functions pg_cmp_xyz() that will standardize integer comparison for implementing comparison function for qsort(). The functions will returns negative, 0, or positive integer without risking overflow as a result of subtracting the two integers, which is otherwise a common pattern for implementing this. For integer sizes less than sizeof(int) we can use normal subtraction, which is faster, but for integers with size greater than or equal to sizeof(int) we need to handle this differently. --- src/include/common/int.h | 55 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/include/common/int.h b/src/include/common/int.h index fedf7b3999..03afc04b2e 100644 --- a/src/include/common/int.h +++ b/src/include/common/int.h @@ -1,7 +1,8 @@ /*------------------------------------------------------------------------- * * int.h - * Routines to perform integer math, while checking for overflows. + * Routines to perform signed and unsigned integer arithmetics, including + * comparisons, in an overflow-safe way. * * The routines in this file are intended to be well defined C, without * relying on compiler flags like -fwrapv. @@ -438,4 +439,56 @@ pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result) #endif } +/*------------------------------------------------------------------------ + * Comparison routines for integers. + * + * These routines are used to implement comparison functions for, e.g., + * qsort(). They are designed to be efficient and not risk overflows in + * internal computations that could cause strange results, such as INT_MIN > + * INT_MAX if you just return "lhs - rhs". + *------------------------------------------------------------------------ + */ + +static inline int +pg_cmp_s16(int16 a, int16 b) +{ + return (int32)a - (int32)b; +} + +static inline int +pg_cmp_u16(uint16 a, uint16 b) +{ + return (int32)a - (int32)b; +} + +static inline int +pg_cmp_s32(int32 a, int32 b) +{ + return (a > b) - (a < b); /* Comparison operators return int 0 or 1 */ +} + +static inline int +pg_cmp_u32(uint32 a, uint32 b) +{ + return (a > b) - (a < b); /* Comparison operators return int 0 or 1 */ +} + +static inline int +pg_cmp_s64(int64 a, int64 b) +{ + return (a > b) - (a < b); /* Comparison operators return int 0 or 1 */ +} + +static inline int +pg_cmp_u64(uint64 a, uint64 b) +{ + return (a > b) - (a < b); /* Comparison operators return int 0 or 1 */ +} + +static inline int +pg_cmp_size(size_t a, size_t b) +{ + return (a > b) - (a < b); /* Comparison operators return int 0 or 1 */ +} + #endif /* COMMON_INT_H */ -- 2.34.1