Skip to content

Commit fd64ed6

Browse files
alvherrejianhe-fun
andcommitted
Unbreak overflow test for attinhcount/coninhcount
Commit 90189ee 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 b0e96f3 and not removed by its revert at 6f8bb7c. 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 <[email protected]> Co-authored-by: 何建 (jian he) <[email protected]> Reviewed-by: Tom Lane <[email protected]> Discussion: https://postgr.es/m/[email protected]
1 parent 1909835 commit fd64ed6

File tree

8 files changed

+32
-32
lines changed

8 files changed

+32
-32
lines changed

src/backend/catalog/heap.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static ObjectAddress AddNewRelationType(const char *typeName,
102102
Oid new_array_type);
103103
static void RelationRemoveInheritance(Oid relid);
104104
static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr,
105-
bool is_validated, bool is_local, int inhcount,
105+
bool is_validated, bool is_local, int16 inhcount,
106106
bool is_no_inherit, bool is_internal);
107107
static void StoreConstraints(Relation rel, List *cooked_constraints,
108108
bool is_internal);
@@ -2072,7 +2072,7 @@ SetAttrMissing(Oid relid, char *attname, char *value)
20722072
*/
20732073
static Oid
20742074
StoreRelCheck(Relation rel, const char *ccname, Node *expr,
2075-
bool is_validated, bool is_local, int inhcount,
2075+
bool is_validated, bool is_local, int16 inhcount,
20762076
bool is_no_inherit, bool is_internal)
20772077
{
20782078
char *ccbin;
@@ -2624,10 +2624,8 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
26242624
{
26252625
if (is_local)
26262626
con->conislocal = true;
2627-
else
2628-
con->coninhcount++;
2629-
2630-
if (con->coninhcount < 0)
2627+
else if (pg_add_s16_overflow(con->coninhcount, 1,
2628+
&con->coninhcount))
26312629
ereport(ERROR,
26322630
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
26332631
errmsg("too many inheritance parents"));

src/backend/catalog/index.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1900,7 +1900,7 @@ index_constraint_create(Relation heapRelation,
19001900
bool islocal;
19011901
bool noinherit;
19021902
bool is_without_overlaps;
1903-
int inhcount;
1903+
int16 inhcount;
19041904

19051905
deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
19061906
initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;

src/backend/catalog/pg_constraint.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "catalog/pg_operator.h"
2828
#include "catalog/pg_type.h"
2929
#include "commands/defrem.h"
30+
#include "common/int.h"
3031
#include "utils/array.h"
3132
#include "utils/builtins.h"
3233
#include "utils/fmgroids.h"
@@ -74,7 +75,7 @@ CreateConstraintEntry(const char *constraintName,
7475
Node *conExpr,
7576
const char *conBin,
7677
bool conIsLocal,
77-
int conInhCount,
78+
int16 conInhCount,
7879
bool conNoInherit,
7980
bool conPeriod,
8081
bool is_internal)
@@ -849,11 +850,12 @@ ConstraintSetParentConstraint(Oid childConstrId,
849850
childConstrId);
850851

851852
constrForm->conislocal = false;
852-
constrForm->coninhcount++;
853-
if (constrForm->coninhcount < 0)
853+
if (pg_add_s16_overflow(constrForm->coninhcount, 1,
854+
&constrForm->coninhcount))
854855
ereport(ERROR,
855856
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
856857
errmsg("too many inheritance parents"));
858+
857859
constrForm->conparentid = parentConstrId;
858860

859861
CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);

src/backend/commands/tablecmds.c

+18-16
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "commands/typecmds.h"
6767
#include "commands/user.h"
6868
#include "commands/vacuum.h"
69+
#include "common/int.h"
6970
#include "executor/executor.h"
7071
#include "foreign/fdwapi.h"
7172
#include "foreign/foreign.h"
@@ -3044,8 +3045,8 @@ MergeCheckConstraint(List *constraints, const char *name, Node *expr)
30443045
if (equal(expr, ccon->expr))
30453046
{
30463047
/* OK to merge constraint with existing */
3047-
ccon->inhcount++;
3048-
if (ccon->inhcount < 0)
3048+
if (pg_add_s16_overflow(ccon->inhcount, 1,
3049+
&ccon->inhcount))
30493050
ereport(ERROR,
30503051
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
30513052
errmsg("too many inheritance parents"));
@@ -3347,8 +3348,8 @@ MergeInheritedAttribute(List *inh_columns,
33473348
* Default and other constraints are handled by the caller.
33483349
*/
33493350

3350-
prevdef->inhcount++;
3351-
if (prevdef->inhcount < 0)
3351+
if (pg_add_s16_overflow(prevdef->inhcount, 1,
3352+
&prevdef->inhcount))
33523353
ereport(ERROR,
33533354
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
33543355
errmsg("too many inheritance parents"));
@@ -7089,8 +7090,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
70897090
get_collation_name(childatt->attcollation))));
70907091

70917092
/* Bump the existing child att's inhcount */
7092-
childatt->attinhcount++;
7093-
if (childatt->attinhcount < 0)
7093+
if (pg_add_s16_overflow(childatt->attinhcount, 1,
7094+
&childatt->attinhcount))
70947095
ereport(ERROR,
70957096
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
70967097
errmsg("too many inheritance parents"));
@@ -10170,7 +10171,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
1017010171
Oid constrOid;
1017110172
char *conname;
1017210173
bool conislocal;
10173-
int coninhcount;
10174+
int16 coninhcount;
1017410175
bool connoinherit;
1017510176
Oid deleteTriggerOid,
1017610177
updateTriggerOid;
@@ -10549,9 +10550,9 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
1054910550
NULL,
1055010551
NULL,
1055110552
NULL,
10552-
false,
10553-
1,
10554-
false,
10553+
false, /* conIsLocal */
10554+
1, /* conInhCount */
10555+
false, /* conNoInherit */
1055510556
with_period, /* conPeriod */
1055610557
false);
1055710558

@@ -11076,8 +11077,8 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
1107611077
NULL,
1107711078
NULL,
1107811079
NULL,
11079-
false, /* islocal */
11080-
1, /* inhcount */
11080+
false, /* conIsLocal */
11081+
1, /* conInhCount */
1108111082
false, /* conNoInherit */
1108211083
with_period, /* conPeriod */
1108311084
true);
@@ -15944,8 +15945,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart
1594415945
* OK, bump the child column's inheritance count. (If we fail
1594515946
* later on, this change will just roll back.)
1594615947
*/
15947-
child_att->attinhcount++;
15948-
if (child_att->attinhcount < 0)
15948+
if (pg_add_s16_overflow(child_att->attinhcount, 1,
15949+
&child_att->attinhcount))
1594915950
ereport(ERROR,
1595015951
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1595115952
errmsg("too many inheritance parents"));
@@ -16075,8 +16076,9 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
1607516076
*/
1607616077
child_copy = heap_copytuple(child_tuple);
1607716078
child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
16078-
child_con->coninhcount++;
16079-
if (child_con->coninhcount < 0)
16079+
16080+
if (pg_add_s16_overflow(child_con->coninhcount, 1,
16081+
&child_con->coninhcount))
1608016082
ereport(ERROR,
1608116083
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1608216084
errmsg("too many inheritance parents"));

src/include/catalog/catversion.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/* yyyymmddN */
60-
#define CATALOG_VERSION_NO 202410111
60+
#define CATALOG_VERSION_NO 202410112
6161

6262
#endif

src/include/catalog/heap.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ typedef struct CookedConstraint
4141
Node *expr; /* transformed default or check expr */
4242
bool skip_validation; /* skip validation? (only for CHECK) */
4343
bool is_local; /* constraint has local (non-inherited) def */
44-
int inhcount; /* number of times constraint is inherited */
44+
int16 inhcount; /* number of times constraint is inherited */
4545
bool is_no_inherit; /* constraint has local def and cannot be
4646
* inherited */
4747
} CookedConstraint;

src/include/catalog/pg_constraint.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
245245
Node *conExpr,
246246
const char *conBin,
247247
bool conIsLocal,
248-
int conInhCount,
248+
int16 conInhCount,
249249
bool conNoInherit,
250250
bool conPeriod,
251251
bool is_internal);

src/include/nodes/parsenodes.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ typedef struct ColumnDef
728728
char *colname; /* name of column */
729729
TypeName *typeName; /* type of column */
730730
char *compression; /* compression method for column */
731-
int inhcount; /* number of times column is inherited */
731+
int16 inhcount; /* number of times column is inherited */
732732
bool is_local; /* column has local (non-inherited) def'n */
733733
bool is_not_null; /* NOT NULL constraint specified? */
734734
bool is_from_type; /* column definition came from table type */
@@ -2754,8 +2754,6 @@ typedef struct Constraint
27542754
char *cooked_expr; /* CHECK or DEFAULT expression, as
27552755
* nodeToString representation */
27562756
char generated_when; /* ALWAYS or BY DEFAULT */
2757-
int inhcount; /* initial inheritance count to apply, for
2758-
* "raw" NOT NULL constraints */
27592757
bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
27602758
List *keys; /* String nodes naming referenced key
27612759
* column(s); for UNIQUE/PK/NOT NULL */

0 commit comments

Comments
 (0)