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))