1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-29 13:56:47 +03:00

Unbreak overflow test for attinhcount/coninhcount

Commit 90189eefc1e1 narrowed pg_attribute.attinhcount and
pg_constraint.coninhcount from 32 to 16 bits, but kept other related
structs with 32-bit wide fields: ColumnDef and CookedConstraint contain
an int 'inhcount' field which is itself checked for overflow on
increments, but there's no check that the values aren't above INT16_MAX
before assigning to the catalog columns.  This means that a creative
user can get a inconsistent table definition and override some
protections.

Fix it by changing those other structs to also use int16.

Also, modernize style by using pg_add_s16_overflow for overflow testing
instead of checking for negative values.

We also have Constraint.inhcount, which is here removed completely.
This was added by commit b0e96f311985 and not removed by its revert at
6f8bb7c1e961.  It is not needed by the upcoming not-null constraints
patch.

This is mostly academic, so we agreed not to backpatch to avoid ABI
problems.

Bump catversion because of the changes to parse nodes.

Co-authored-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Co-authored-by: 何建 (jian he) <jian.universality@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/202410081611.up4iyofb5ie7@alvherre.pgsql
This commit is contained in:
Álvaro Herrera 2024-10-10 17:41:01 +02:00
parent 1909835c28
commit fd64ed60b6
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
8 changed files with 32 additions and 32 deletions

View File

@ -102,7 +102,7 @@ static ObjectAddress AddNewRelationType(const char *typeName,
Oid new_array_type); Oid new_array_type);
static void RelationRemoveInheritance(Oid relid); static void RelationRemoveInheritance(Oid relid);
static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount, bool is_validated, bool is_local, int16 inhcount,
bool is_no_inherit, bool is_internal); bool is_no_inherit, bool is_internal);
static void StoreConstraints(Relation rel, List *cooked_constraints, static void StoreConstraints(Relation rel, List *cooked_constraints,
bool is_internal); bool is_internal);
@ -2072,7 +2072,7 @@ SetAttrMissing(Oid relid, char *attname, char *value)
*/ */
static Oid static Oid
StoreRelCheck(Relation rel, const char *ccname, Node *expr, StoreRelCheck(Relation rel, const char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount, bool is_validated, bool is_local, int16 inhcount,
bool is_no_inherit, bool is_internal) bool is_no_inherit, bool is_internal)
{ {
char *ccbin; char *ccbin;
@ -2624,10 +2624,8 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
{ {
if (is_local) if (is_local)
con->conislocal = true; con->conislocal = true;
else else if (pg_add_s16_overflow(con->coninhcount, 1,
con->coninhcount++; &con->coninhcount))
if (con->coninhcount < 0)
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));

View File

@ -1900,7 +1900,7 @@ index_constraint_create(Relation heapRelation,
bool islocal; bool islocal;
bool noinherit; bool noinherit;
bool is_without_overlaps; bool is_without_overlaps;
int inhcount; int16 inhcount;
deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0; deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0; initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;

View File

@ -27,6 +27,7 @@
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "common/int.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
@ -74,7 +75,7 @@ CreateConstraintEntry(const char *constraintName,
Node *conExpr, Node *conExpr,
const char *conBin, const char *conBin,
bool conIsLocal, bool conIsLocal,
int conInhCount, int16 conInhCount,
bool conNoInherit, bool conNoInherit,
bool conPeriod, bool conPeriod,
bool is_internal) bool is_internal)
@ -849,11 +850,12 @@ ConstraintSetParentConstraint(Oid childConstrId,
childConstrId); childConstrId);
constrForm->conislocal = false; constrForm->conislocal = false;
constrForm->coninhcount++; if (pg_add_s16_overflow(constrForm->coninhcount, 1,
if (constrForm->coninhcount < 0) &constrForm->coninhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));
constrForm->conparentid = parentConstrId; constrForm->conparentid = parentConstrId;
CatalogTupleUpdate(constrRel, &tuple->t_self, newtup); CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);

View File

@ -66,6 +66,7 @@
#include "commands/typecmds.h" #include "commands/typecmds.h"
#include "commands/user.h" #include "commands/user.h"
#include "commands/vacuum.h" #include "commands/vacuum.h"
#include "common/int.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "foreign/fdwapi.h" #include "foreign/fdwapi.h"
#include "foreign/foreign.h" #include "foreign/foreign.h"
@ -3044,8 +3045,8 @@ MergeCheckConstraint(List *constraints, const char *name, Node *expr)
if (equal(expr, ccon->expr)) if (equal(expr, ccon->expr))
{ {
/* OK to merge constraint with existing */ /* OK to merge constraint with existing */
ccon->inhcount++; if (pg_add_s16_overflow(ccon->inhcount, 1,
if (ccon->inhcount < 0) &ccon->inhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));
@ -3347,8 +3348,8 @@ MergeInheritedAttribute(List *inh_columns,
* Default and other constraints are handled by the caller. * Default and other constraints are handled by the caller.
*/ */
prevdef->inhcount++; if (pg_add_s16_overflow(prevdef->inhcount, 1,
if (prevdef->inhcount < 0) &prevdef->inhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));
@ -7089,8 +7090,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
get_collation_name(childatt->attcollation)))); get_collation_name(childatt->attcollation))));
/* Bump the existing child att's inhcount */ /* Bump the existing child att's inhcount */
childatt->attinhcount++; if (pg_add_s16_overflow(childatt->attinhcount, 1,
if (childatt->attinhcount < 0) &childatt->attinhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));
@ -10170,7 +10171,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
Oid constrOid; Oid constrOid;
char *conname; char *conname;
bool conislocal; bool conislocal;
int coninhcount; int16 coninhcount;
bool connoinherit; bool connoinherit;
Oid deleteTriggerOid, Oid deleteTriggerOid,
updateTriggerOid; updateTriggerOid;
@ -10549,9 +10550,9 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
NULL, NULL,
NULL, NULL,
NULL, NULL,
false, false, /* conIsLocal */
1, 1, /* conInhCount */
false, false, /* conNoInherit */
with_period, /* conPeriod */ with_period, /* conPeriod */
false); false);
@ -11076,8 +11077,8 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
NULL, NULL,
NULL, NULL,
NULL, NULL,
false, /* islocal */ false, /* conIsLocal */
1, /* inhcount */ 1, /* conInhCount */
false, /* conNoInherit */ false, /* conNoInherit */
with_period, /* conPeriod */ with_period, /* conPeriod */
true); true);
@ -15944,8 +15945,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart
* OK, bump the child column's inheritance count. (If we fail * OK, bump the child column's inheritance count. (If we fail
* later on, this change will just roll back.) * later on, this change will just roll back.)
*/ */
child_att->attinhcount++; if (pg_add_s16_overflow(child_att->attinhcount, 1,
if (child_att->attinhcount < 0) &child_att->attinhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));
@ -16075,8 +16076,9 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
*/ */
child_copy = heap_copytuple(child_tuple); child_copy = heap_copytuple(child_tuple);
child_con = (Form_pg_constraint) GETSTRUCT(child_copy); child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
child_con->coninhcount++;
if (child_con->coninhcount < 0) if (pg_add_s16_overflow(child_con->coninhcount, 1,
&child_con->coninhcount))
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents")); errmsg("too many inheritance parents"));

View File

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202410111 #define CATALOG_VERSION_NO 202410112
#endif #endif

View File

@ -41,7 +41,7 @@ typedef struct CookedConstraint
Node *expr; /* transformed default or check expr */ Node *expr; /* transformed default or check expr */
bool skip_validation; /* skip validation? (only for CHECK) */ bool skip_validation; /* skip validation? (only for CHECK) */
bool is_local; /* constraint has local (non-inherited) def */ bool is_local; /* constraint has local (non-inherited) def */
int inhcount; /* number of times constraint is inherited */ int16 inhcount; /* number of times constraint is inherited */
bool is_no_inherit; /* constraint has local def and cannot be bool is_no_inherit; /* constraint has local def and cannot be
* inherited */ * inherited */
} CookedConstraint; } CookedConstraint;

View File

@ -245,7 +245,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
Node *conExpr, Node *conExpr,
const char *conBin, const char *conBin,
bool conIsLocal, bool conIsLocal,
int conInhCount, int16 conInhCount,
bool conNoInherit, bool conNoInherit,
bool conPeriod, bool conPeriod,
bool is_internal); bool is_internal);

View File

@ -728,7 +728,7 @@ typedef struct ColumnDef
char *colname; /* name of column */ char *colname; /* name of column */
TypeName *typeName; /* type of column */ TypeName *typeName; /* type of column */
char *compression; /* compression method for column */ char *compression; /* compression method for column */
int inhcount; /* number of times column is inherited */ int16 inhcount; /* number of times column is inherited */
bool is_local; /* column has local (non-inherited) def'n */ bool is_local; /* column has local (non-inherited) def'n */
bool is_not_null; /* NOT NULL constraint specified? */ bool is_not_null; /* NOT NULL constraint specified? */
bool is_from_type; /* column definition came from table type */ bool is_from_type; /* column definition came from table type */
@ -2754,8 +2754,6 @@ typedef struct Constraint
char *cooked_expr; /* CHECK or DEFAULT expression, as char *cooked_expr; /* CHECK or DEFAULT expression, as
* nodeToString representation */ * nodeToString representation */
char generated_when; /* ALWAYS or BY DEFAULT */ char generated_when; /* ALWAYS or BY DEFAULT */
int inhcount; /* initial inheritance count to apply, for
* "raw" NOT NULL constraints */
bool nulls_not_distinct; /* null treatment for UNIQUE constraints */ bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
List *keys; /* String nodes naming referenced key List *keys; /* String nodes naming referenced key
* column(s); for UNIQUE/PK/NOT NULL */ * column(s); for UNIQUE/PK/NOT NULL */