mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Fix ALTER TABLE ADD COLUMN to disallow the same column types that are
disallowed by CREATE TABLE (eg, pseudo-types); also disallow these types from being introduced by the range-function syntax. While at it, allow CREATE TABLE to create zero-column tables, per recent pghackers discussion. I am back-patching this into 7.3 since failure to disallow pseudo-types is arguably a security hole.
This commit is contained in:
parent
88177f77b1
commit
260faf0b63
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.237 2002/12/12 20:35:08 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.238 2002/12/16 18:39:22 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -307,8 +307,8 @@ heap_storage_create(Relation rel)
|
||||
*
|
||||
* this is done in 6 steps:
|
||||
*
|
||||
* 1) CheckAttributeNames() is used to make certain the tuple
|
||||
* descriptor contains a valid set of attribute names
|
||||
* 1) CheckAttributeNamesTypes() is used to make certain the tuple
|
||||
* descriptor contains a valid set of attribute names and types
|
||||
*
|
||||
* 2) pg_class is opened and get_relname_relid()
|
||||
* performs a scan to ensure that no relation with the
|
||||
@ -334,20 +334,25 @@ heap_storage_create(Relation rel)
|
||||
*/
|
||||
|
||||
/* --------------------------------
|
||||
* CheckAttributeNames
|
||||
* CheckAttributeNamesTypes
|
||||
*
|
||||
* this is used to make certain the tuple descriptor contains a
|
||||
* valid set of attribute names. a problem simply generates
|
||||
* elog(ERROR) which aborts the current transaction.
|
||||
* valid set of attribute names and datatypes. a problem simply
|
||||
* generates elog(ERROR) which aborts the current transaction.
|
||||
* --------------------------------
|
||||
*/
|
||||
static void
|
||||
CheckAttributeNames(TupleDesc tupdesc, char relkind)
|
||||
void
|
||||
CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int natts = tupdesc->natts;
|
||||
|
||||
/* Sanity check on column count */
|
||||
if (natts < 0 || natts > MaxHeapAttributeNumber)
|
||||
elog(ERROR, "Number of columns is out of range (0 to %d)",
|
||||
MaxHeapAttributeNumber);
|
||||
|
||||
/*
|
||||
* first check for collision with system attribute names
|
||||
*
|
||||
@ -380,8 +385,29 @@ CheckAttributeNames(TupleDesc tupdesc, char relkind)
|
||||
}
|
||||
|
||||
/*
|
||||
* We also do some checking of the attribute types here.
|
||||
*
|
||||
* next check the attribute types
|
||||
*/
|
||||
for (i = 0; i < natts; i++)
|
||||
{
|
||||
CheckAttributeType(NameStr(tupdesc->attrs[i]->attname),
|
||||
tupdesc->attrs[i]->atttypid);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* CheckAttributeType
|
||||
*
|
||||
* Verify that the proposed datatype of an attribute is legal.
|
||||
* This is needed because there are types (and pseudo-types)
|
||||
* in the catalogs that we do not support as elements of real tuples.
|
||||
* --------------------------------
|
||||
*/
|
||||
void
|
||||
CheckAttributeType(const char *attname, Oid atttypid)
|
||||
{
|
||||
char att_typtype = get_typtype(atttypid);
|
||||
|
||||
/*
|
||||
* Warn user, but don't fail, if column to be created has UNKNOWN type
|
||||
* (usually as a result of a 'retrieve into' - jolly)
|
||||
*
|
||||
@ -390,28 +416,20 @@ CheckAttributeNames(TupleDesc tupdesc, char relkind)
|
||||
* all references to complex types, but for now there's still some
|
||||
* Berkeley-derived code that thinks it can do this...)
|
||||
*/
|
||||
for (i = 0; i < natts; i++)
|
||||
if (atttypid == UNKNOWNOID)
|
||||
elog(WARNING, "Attribute \"%s\" has an unknown type"
|
||||
"\n\tProceeding with relation creation anyway",
|
||||
attname);
|
||||
else if (att_typtype == 'p')
|
||||
elog(ERROR, "Attribute \"%s\" has pseudo-type %s",
|
||||
attname, format_type_be(atttypid));
|
||||
else if (att_typtype == 'c')
|
||||
{
|
||||
Oid att_type = tupdesc->attrs[i]->atttypid;
|
||||
char att_typtype = get_typtype(att_type);
|
||||
Oid typrelid = get_typ_typrelid(atttypid);
|
||||
|
||||
if (att_type == UNKNOWNOID)
|
||||
elog(WARNING, "Attribute \"%s\" has an unknown type"
|
||||
"\n\tProceeding with relation creation anyway",
|
||||
NameStr(tupdesc->attrs[i]->attname));
|
||||
if (att_typtype == 'p')
|
||||
elog(ERROR, "Attribute \"%s\" has pseudo-type %s",
|
||||
NameStr(tupdesc->attrs[i]->attname),
|
||||
format_type_be(att_type));
|
||||
if (att_typtype == 'c')
|
||||
{
|
||||
Oid typrelid = get_typ_typrelid(att_type);
|
||||
|
||||
if (get_rel_relkind(typrelid) == RELKIND_COMPOSITE_TYPE)
|
||||
elog(ERROR, "Attribute \"%s\" has composite type %s",
|
||||
NameStr(tupdesc->attrs[i]->attname),
|
||||
format_type_be(att_type));
|
||||
}
|
||||
if (get_rel_relkind(typrelid) == RELKIND_COMPOSITE_TYPE)
|
||||
elog(ERROR, "Attribute \"%s\" has composite type %s",
|
||||
attname, format_type_be(atttypid));
|
||||
}
|
||||
}
|
||||
|
||||
@ -689,11 +707,8 @@ heap_create_with_catalog(const char *relname,
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
|
||||
if (tupdesc->natts <= 0 || tupdesc->natts > MaxHeapAttributeNumber)
|
||||
elog(ERROR, "Number of columns is out of range (1 to %d)",
|
||||
MaxHeapAttributeNumber);
|
||||
|
||||
CheckAttributeNames(tupdesc, relkind);
|
||||
CheckAttributeNamesTypes(tupdesc, relkind);
|
||||
|
||||
if (get_relname_relid(relname, relnamespace))
|
||||
elog(ERROR, "Relation '%s' already exists", relname);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.61 2002/12/15 16:17:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.62 2002/12/16 18:39:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -125,7 +125,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
char relname[NAMEDATALEN];
|
||||
Oid namespaceId;
|
||||
List *schema = stmt->tableElts;
|
||||
int numberOfAttributes;
|
||||
Oid relationId;
|
||||
Relation rel;
|
||||
TupleDesc descriptor;
|
||||
@ -174,10 +173,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
stmt->relation->istemp,
|
||||
&inheritOids, &old_constraints, &parentHasOids);
|
||||
|
||||
numberOfAttributes = length(schema);
|
||||
if (numberOfAttributes <= 0)
|
||||
elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
|
||||
|
||||
/*
|
||||
* Create a relation descriptor from the relation schema and create
|
||||
* the relation. Note that in this stage only inherited (pre-cooked)
|
||||
@ -1800,6 +1795,9 @@ AlterTableAddColumn(Oid myrelid,
|
||||
typeTuple = typenameType(colDef->typename);
|
||||
tform = (Form_pg_type) GETSTRUCT(typeTuple);
|
||||
|
||||
/* make sure datatype is legal for a column */
|
||||
CheckAttributeType(colDef->colname, HeapTupleGetOid(typeTuple));
|
||||
|
||||
attributeTuple = heap_addheader(Natts_pg_attribute,
|
||||
false,
|
||||
ATTRIBUTE_TUPLE_SIZE,
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.102 2002/12/12 20:35:13 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.103 2002/12/16 18:39:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -16,6 +16,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/heap.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/tlist.h"
|
||||
@ -502,6 +503,18 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
elog(ERROR, "cannot use aggregate function in FROM function expression");
|
||||
}
|
||||
|
||||
/*
|
||||
* If a coldeflist is supplied, ensure it defines a legal set of names
|
||||
* (no duplicates) and datatypes (no pseudo-types, for instance).
|
||||
*/
|
||||
if (r->coldeflist)
|
||||
{
|
||||
TupleDesc tupdesc;
|
||||
|
||||
tupdesc = BuildDescForRelation(r->coldeflist);
|
||||
CheckAttributeNamesTypes(tupdesc, RELKIND_COMPOSITE_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, build an RTE for the function.
|
||||
*/
|
||||
|
7
src/backend/utils/cache/relcache.c
vendored
7
src/backend/utils/cache/relcache.c
vendored
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.182 2002/12/15 21:01:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.183 2002/12/16 18:39:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -570,7 +570,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
|
||||
* cases for attnum=1 that used to exist in fastgetattr() and
|
||||
* index_getattr().
|
||||
*/
|
||||
relation->rd_att->attrs[0]->attcacheoff = 0;
|
||||
if (relation->rd_rel->relnatts > 0)
|
||||
relation->rd_att->attrs[0]->attcacheoff = 0;
|
||||
|
||||
/*
|
||||
* Set up constraint/default info
|
||||
@ -2049,7 +2050,7 @@ RelationBuildLocalRelation(const char *relname,
|
||||
int i;
|
||||
bool has_not_null;
|
||||
|
||||
AssertArg(natts > 0);
|
||||
AssertArg(natts >= 0);
|
||||
|
||||
/*
|
||||
* switch to the cache context to create the relcache entry.
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: heap.h,v 1.59 2002/11/11 22:19:23 tgl Exp $
|
||||
* $Id: heap.h,v 1.60 2002/12/16 18:39:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -74,4 +74,8 @@ extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
|
||||
extern Form_pg_attribute SystemAttributeByName(const char *attname,
|
||||
bool relhasoids);
|
||||
|
||||
extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind);
|
||||
|
||||
extern void CheckAttributeType(const char *attname, Oid atttypid);
|
||||
|
||||
#endif /* HEAP_H */
|
||||
|
Loading…
Reference in New Issue
Block a user