Change tsearch2 to not use the unsafe practice of creating functions
that return INTERNAL without also having INTERNAL arguments. Since the functions in question aren't meant to be called by hand anyway, I just redeclared them to take 'internal' instead of 'text'. Also add code to ProcedureCreate() to enforce the restriction, as I should have done to start with :-(
This commit is contained in:
parent
39e54e3208
commit
177af51c04
@ -1,7 +1,7 @@
|
|||||||
SET search_path = public;
|
SET search_path = public;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
HASINIT create function dinit_CFG_MODNAME(text)
|
HASINIT create function dinit_CFG_MODNAME(internal)
|
||||||
HASINIT returns internal
|
HASINIT returns internal
|
||||||
HASINIT as 'MODULE_PATHNAME'
|
HASINIT as 'MODULE_PATHNAME'
|
||||||
HASINIT language 'C';
|
HASINIT language 'C';
|
||||||
|
@ -44,7 +44,7 @@ CREATE FUNCTION set_curdict(text)
|
|||||||
with (isstrict);
|
with (isstrict);
|
||||||
|
|
||||||
--built-in dictionaries
|
--built-in dictionaries
|
||||||
CREATE FUNCTION dex_init(text)
|
CREATE FUNCTION dex_init(internal)
|
||||||
returns internal
|
returns internal
|
||||||
as 'MODULE_PATHNAME'
|
as 'MODULE_PATHNAME'
|
||||||
language 'C';
|
language 'C';
|
||||||
@ -57,13 +57,13 @@ CREATE FUNCTION dex_lexize(internal,internal,int4)
|
|||||||
|
|
||||||
insert into pg_ts_dict select
|
insert into pg_ts_dict select
|
||||||
'simple',
|
'simple',
|
||||||
'dex_init(text)',
|
'dex_init(internal)',
|
||||||
null,
|
null,
|
||||||
'dex_lexize(internal,internal,int4)',
|
'dex_lexize(internal,internal,int4)',
|
||||||
'Simple example of dictionary.'
|
'Simple example of dictionary.'
|
||||||
;
|
;
|
||||||
|
|
||||||
CREATE FUNCTION snb_en_init(text)
|
CREATE FUNCTION snb_en_init(internal)
|
||||||
returns internal
|
returns internal
|
||||||
as 'MODULE_PATHNAME'
|
as 'MODULE_PATHNAME'
|
||||||
language 'C';
|
language 'C';
|
||||||
@ -76,26 +76,26 @@ CREATE FUNCTION snb_lexize(internal,internal,int4)
|
|||||||
|
|
||||||
insert into pg_ts_dict select
|
insert into pg_ts_dict select
|
||||||
'en_stem',
|
'en_stem',
|
||||||
'snb_en_init(text)',
|
'snb_en_init(internal)',
|
||||||
'contrib/english.stop',
|
'contrib/english.stop',
|
||||||
'snb_lexize(internal,internal,int4)',
|
'snb_lexize(internal,internal,int4)',
|
||||||
'English Stemmer. Snowball.'
|
'English Stemmer. Snowball.'
|
||||||
;
|
;
|
||||||
|
|
||||||
CREATE FUNCTION snb_ru_init(text)
|
CREATE FUNCTION snb_ru_init(internal)
|
||||||
returns internal
|
returns internal
|
||||||
as 'MODULE_PATHNAME'
|
as 'MODULE_PATHNAME'
|
||||||
language 'C';
|
language 'C';
|
||||||
|
|
||||||
insert into pg_ts_dict select
|
insert into pg_ts_dict select
|
||||||
'ru_stem',
|
'ru_stem',
|
||||||
'snb_ru_init(text)',
|
'snb_ru_init(internal)',
|
||||||
'contrib/russian.stop',
|
'contrib/russian.stop',
|
||||||
'snb_lexize(internal,internal,int4)',
|
'snb_lexize(internal,internal,int4)',
|
||||||
'Russian Stemmer. Snowball.'
|
'Russian Stemmer. Snowball.'
|
||||||
;
|
;
|
||||||
|
|
||||||
CREATE FUNCTION spell_init(text)
|
CREATE FUNCTION spell_init(internal)
|
||||||
returns internal
|
returns internal
|
||||||
as 'MODULE_PATHNAME'
|
as 'MODULE_PATHNAME'
|
||||||
language 'C';
|
language 'C';
|
||||||
@ -108,13 +108,13 @@ CREATE FUNCTION spell_lexize(internal,internal,int4)
|
|||||||
|
|
||||||
insert into pg_ts_dict select
|
insert into pg_ts_dict select
|
||||||
'ispell_template',
|
'ispell_template',
|
||||||
'spell_init(text)',
|
'spell_init(internal)',
|
||||||
null,
|
null,
|
||||||
'spell_lexize(internal,internal,int4)',
|
'spell_lexize(internal,internal,int4)',
|
||||||
'ISpell interface. Must have .dict and .aff files'
|
'ISpell interface. Must have .dict and .aff files'
|
||||||
;
|
;
|
||||||
|
|
||||||
CREATE FUNCTION syn_init(text)
|
CREATE FUNCTION syn_init(internal)
|
||||||
returns internal
|
returns internal
|
||||||
as 'MODULE_PATHNAME'
|
as 'MODULE_PATHNAME'
|
||||||
language 'C';
|
language 'C';
|
||||||
@ -127,7 +127,7 @@ CREATE FUNCTION syn_lexize(internal,internal,int4)
|
|||||||
|
|
||||||
insert into pg_ts_dict select
|
insert into pg_ts_dict select
|
||||||
'synonym',
|
'synonym',
|
||||||
'syn_init(text)',
|
'syn_init(internal)',
|
||||||
null,
|
null,
|
||||||
'syn_lexize(internal,internal,int4)',
|
'syn_lexize(internal,internal,int4)',
|
||||||
'Example of synonym dictionary'
|
'Example of synonym dictionary'
|
||||||
|
@ -34,14 +34,14 @@ DROP FUNCTION lexize(text, text);
|
|||||||
DROP FUNCTION lexize(text);
|
DROP FUNCTION lexize(text);
|
||||||
DROP FUNCTION set_curdict(int);
|
DROP FUNCTION set_curdict(int);
|
||||||
DROP FUNCTION set_curdict(text);
|
DROP FUNCTION set_curdict(text);
|
||||||
DROP FUNCTION dex_init(text);
|
DROP FUNCTION dex_init(internal);
|
||||||
DROP FUNCTION dex_lexize(internal,internal,int4);
|
DROP FUNCTION dex_lexize(internal,internal,int4);
|
||||||
DROP FUNCTION snb_en_init(text);
|
DROP FUNCTION snb_en_init(internal);
|
||||||
DROP FUNCTION snb_lexize(internal,internal,int4);
|
DROP FUNCTION snb_lexize(internal,internal,int4);
|
||||||
DROP FUNCTION snb_ru_init(text);
|
DROP FUNCTION snb_ru_init(internal);
|
||||||
DROP FUNCTION spell_init(text);
|
DROP FUNCTION spell_init(internal);
|
||||||
DROP FUNCTION spell_lexize(internal,internal,int4);
|
DROP FUNCTION spell_lexize(internal,internal,int4);
|
||||||
DROP FUNCTION syn_init(text);
|
DROP FUNCTION syn_init(internal);
|
||||||
DROP FUNCTION syn_lexize(internal,internal,int4);
|
DROP FUNCTION syn_lexize(internal,internal,int4);
|
||||||
DROP FUNCTION set_curprs(int);
|
DROP FUNCTION set_curprs(int);
|
||||||
DROP FUNCTION set_curprs(text);
|
DROP FUNCTION set_curprs(text);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.128 2005/04/14 20:03:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.129 2005/05/03 16:51:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -81,6 +81,9 @@ ProcedureCreate(const char *procedureName,
|
|||||||
int allParamCount;
|
int allParamCount;
|
||||||
Oid *allParams;
|
Oid *allParams;
|
||||||
bool genericInParam = false;
|
bool genericInParam = false;
|
||||||
|
bool genericOutParam = false;
|
||||||
|
bool internalInParam = false;
|
||||||
|
bool internalOutParam = false;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
HeapTuple oldtup;
|
HeapTuple oldtup;
|
||||||
@ -133,43 +136,59 @@ ProcedureCreate(const char *procedureName,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not allow return type ANYARRAY or ANYELEMENT unless at least one
|
* Do not allow return type ANYARRAY or ANYELEMENT unless at least one
|
||||||
* input argument is also ANYARRAY or ANYELEMENT
|
* input argument is ANYARRAY or ANYELEMENT. Also, do not allow
|
||||||
|
* return type INTERNAL unless at least one input argument is INTERNAL.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < parameterCount; i++)
|
for (i = 0; i < parameterCount; i++)
|
||||||
{
|
{
|
||||||
if (parameterTypes->values[i] == ANYARRAYOID ||
|
switch (parameterTypes->values[i])
|
||||||
parameterTypes->values[i] == ANYELEMENTOID)
|
|
||||||
{
|
{
|
||||||
genericInParam = true;
|
case ANYARRAYOID:
|
||||||
break;
|
case ANYELEMENTOID:
|
||||||
|
genericInParam = true;
|
||||||
|
break;
|
||||||
|
case INTERNALOID:
|
||||||
|
internalInParam = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!genericInParam)
|
if (allParameterTypes != PointerGetDatum(NULL))
|
||||||
{
|
{
|
||||||
bool genericOutParam = false;
|
for (i = 0; i < allParamCount; i++)
|
||||||
|
|
||||||
if (allParameterTypes != PointerGetDatum(NULL))
|
|
||||||
{
|
{
|
||||||
for (i = 0; i < allParamCount; i++)
|
/*
|
||||||
|
* We don't bother to distinguish input and output params here,
|
||||||
|
* so if there is, say, just an input INTERNAL param then we will
|
||||||
|
* still set internalOutParam. This is OK since we don't really
|
||||||
|
* care.
|
||||||
|
*/
|
||||||
|
switch (allParams[i])
|
||||||
{
|
{
|
||||||
if (allParams[i] == ANYARRAYOID ||
|
case ANYARRAYOID:
|
||||||
allParams[i] == ANYELEMENTOID)
|
case ANYELEMENTOID:
|
||||||
{
|
|
||||||
genericOutParam = true;
|
genericOutParam = true;
|
||||||
break;
|
break;
|
||||||
}
|
case INTERNALOID:
|
||||||
|
internalOutParam = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnType == ANYARRAYOID || returnType == ANYELEMENTOID ||
|
|
||||||
genericOutParam)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
|
||||||
errmsg("cannot determine result data type"),
|
|
||||||
errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((returnType == ANYARRAYOID || returnType == ANYELEMENTOID ||
|
||||||
|
genericOutParam) && !genericInParam)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||||
|
errmsg("cannot determine result data type"),
|
||||||
|
errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type.")));
|
||||||
|
|
||||||
|
if ((returnType == INTERNALOID || internalOutParam) && !internalInParam)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||||
|
errmsg("unsafe use of INTERNAL pseudo-type"),
|
||||||
|
errdetail("A function returning \"internal\" must have at least one \"internal\" argument.")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* don't allow functions of complex types that have the same name as
|
* don't allow functions of complex types that have the same name as
|
||||||
* existing attributes of the type
|
* existing attributes of the type
|
||||||
|
Loading…
Reference in New Issue
Block a user