agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH v2 2/2] Ensure comparison functions are transitive 208+ messages / 1 participants [nested] [flat]
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v2 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
* [PATCH v3 2/2] Ensure comparison functions are transitive @ 2024-02-06 13:53 Mats Kindahl <mats@timescale.com> 0 siblings, 0 replies; 208+ messages in thread From: Mats Kindahl @ 2024-02-06 13:53 UTC (permalink / raw) There are a few comparison functions to qsort() that are non-transitive because they can cause an overflow. Fix these functions to instead use normal comparisons and return -1, 0, or 1 explicitly. --- src/backend/access/spgist/spgtextproc.c | 2 +- src/backend/utils/cache/relcache.c | 9 ++++++--- src/bin/pg_upgrade/function.c | 10 ++++++---- src/bin/psql/crosstabview.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..e561bde63e 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,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 (aa->c > bb->c) - (aa->c < bb->c); } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..54682a0e60 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef) static int AttrDefaultCmp(const void *a, const void *b) { - const AttrDefault *ada = (const AttrDefault *) a; - const AttrDefault *adb = (const AttrDefault *) b; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; - return ada->adnum - adb->adnum; + /* ensure upcasting approach is transitive */ + Assert(sizeof(AttrNumber) == 2); + + return (int) ana - (int) anb; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..b421500bbb 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2) int slen1 = strlen(str1); int slen2 = strlen(str2); int cmp = strcmp(str1, str2); + int p1db = ((const LibraryInfo *) p1)->dbnum; + int p2db = ((const LibraryInfo *) p2)->dbnum; if (slen1 != slen2) - return slen1 - slen2; + return (slen1 > slen2) - (slen1 < slen2); + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + return (p1db > p2db) - (p1db < p2db); } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..7660f0ed4b 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b) static int rankCompare(const void *a, const void *b) { - return *((const int *) a) - *((const int *) b); + const int an = *(const int *) a; + const int bn = *(const int *) b; + + return (an > bn) - (an < bn); } -- 2.25.1 --T4sUOijqQbZv57TR-- ^ permalink raw reply [nested|flat] 208+ messages in thread
end of thread, other threads:[~2024-02-06 13:53 UTC | newest] Thread overview: 208+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v2 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com> 2024-02-06 13:53 [PATCH v3 2/2] Ensure comparison functions are transitive Mats Kindahl <mats@timescale.com>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox