diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 013b6f8..cfc2a69 100644
*** a/doc/src/sgml/ref/alter_function.sgml
--- b/doc/src/sgml/ref/alter_function.sgml
***************
*** 54,59 **** ALTER FUNCTION name ( [ [ lanpltrusted)
- {
- /* if trusted language, need USAGE privilege */
- AclResult aclresult;
-
- aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
- else
- {
- /* if untrusted language, must be superuser */
- if (!superuser())
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
-
languageValidator = languageStruct->lanvalidator;
ReleaseSysCache(languageTuple);
--- 896,905 ----
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
+ check_language_usage(languageTuple);
+
languageOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
languageValidator = languageStruct->lanvalidator;
ReleaseSysCache(languageTuple);
***************
*** 1312,1318 **** AlterFunction(AlterFunctionStmt *stmt)
--- 1327,1355 ----
if (volatility_item)
procForm->provolatile = interpret_func_volatility(volatility_item);
if (strict_item)
+ {
+ /*
+ * C-language functions that expect to be declared STRICT often omit
+ * NULL argument checks, crashing if they do receive a NULL. To
+ * protect such functions against less-privileged owners, clearing
+ * proisstrict requires the authority to define a new function of the
+ * same language.
+ */
+ if (!intVal(strict_item->arg))
+ {
+ HeapTuple langTuple;
+
+ langTuple = SearchSysCache1(LANGOID,
+ PointerGetDatum(procForm->prolang));
+ if (!HeapTupleIsValid(langTuple))
+ elog(ERROR, "cache lookup failed for language %u",
+ procForm->prolang);
+ check_language_usage(langTuple);
+ ReleaseSysCache(langTuple);
+ }
+
procForm->proisstrict = intVal(strict_item->arg);
+ }
if (security_def_item)
procForm->prosecdef = intVal(security_def_item->arg);
if (leakproof_item)
***************
*** 1974,2002 **** ExecuteDoStmt(DoStmt *stmt)
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
codeblock->langOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
codeblock->langIsTrusted = languageStruct->lanpltrusted;
- if (languageStruct->lanpltrusted)
- {
- /* if trusted language, need USAGE privilege */
- AclResult aclresult;
-
- aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
- ACL_USAGE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
- else
- {
- /* if untrusted language, must be superuser */
- if (!superuser())
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
-
/* get the handler function's OID */
laninline = languageStruct->laninline;
if (!OidIsValid(laninline))
--- 2011,2022 ----
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
+ check_language_usage(languageTuple);
+
codeblock->langOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
codeblock->langIsTrusted = languageStruct->lanpltrusted;
/* get the handler function's OID */
laninline = languageStruct->laninline;
if (!OidIsValid(laninline))