aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/acl.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-12-14 17:50:24 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-12-14 17:50:24 -0500
commit47f3f97fcdee28e3eb70cd2ebfd7b4899570b018 (patch)
tree443f2edbb1c19fe1925f87f30e0edf66bc557b30 /src/backend/utils/adt/acl.c
parent332741e73980401895e027eb697bb472860036fb (diff)
downloadpostgresql-47f3f97fcdee28e3eb70cd2ebfd7b4899570b018.tar.gz
postgresql-47f3f97fcdee28e3eb70cd2ebfd7b4899570b018.zip
Convert a few more datatype input functions to report errors softly.
Convert assorted internal-ish datatypes, namely aclitemin, int2vectorin, oidin, oidvectorin, pg_lsn_in, pg_snapshot_in, and tidin to the new style. (Some others you might expect to find in this group, such as cidin and xidin, need no changes because they never throw errors at all. That seems a little cheesy ... but it is not in the charter of this patch series to add new error conditions.) Amul Sul, minor mods by me Discussion: https://postgr.es/m/CAAJ_b97KeDWUdpTKGOaFYPv0OicjOu6EW+QYWj-Ywrgj_aEy1g@mail.gmail.com
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r--src/backend/utils/adt/acl.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index bba953cd6e0..d70b64a8cfe 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -81,11 +81,11 @@ static List *cached_roles[] = {NIL, NIL, NIL};
static uint32 cached_db_hash;
-static const char *getid(const char *s, char *n);
+static const char *getid(const char *s, char *n, Node *escontext);
static void putid(char *p, const char *s);
static Acl *allocacl(int n);
static void check_acl(const Acl *acl);
-static const char *aclparse(const char *s, AclItem *aip);
+static const char *aclparse(const char *s, AclItem *aip, Node *escontext);
static bool aclitem_match(const AclItem *a1, const AclItem *a2);
static int aclitemComparator(const void *arg1, const void *arg2);
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
@@ -135,9 +135,12 @@ static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue
* in 's', after any quotes. Also:
* - loads the identifier into 'n'. (If no identifier is found, 'n'
* contains an empty string.) 'n' must be NAMEDATALEN bytes.
+ *
+ * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
+ * in which case we log the error there and return NULL.
*/
static const char *
-getid(const char *s, char *n)
+getid(const char *s, char *n, Node *escontext)
{
int len = 0;
bool in_quotes = false;
@@ -169,7 +172,7 @@ getid(const char *s, char *n)
/* Add the character to the string */
if (len >= NAMEDATALEN - 1)
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_NAME_TOO_LONG),
errmsg("identifier too long"),
errdetail("Identifier must be less than %d characters.",
@@ -236,9 +239,12 @@ putid(char *p, const char *s)
* specification. Also:
* - loads the structure pointed to by 'aip' with the appropriate
* UID/GID, id type identifier and mode type values.
+ *
+ * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
+ * in which case we log the error there and return NULL.
*/
static const char *
-aclparse(const char *s, AclItem *aip)
+aclparse(const char *s, AclItem *aip, Node *escontext)
{
AclMode privs,
goption,
@@ -248,25 +254,30 @@ aclparse(const char *s, AclItem *aip)
Assert(s && aip);
- s = getid(s, name);
+ s = getid(s, name, escontext);
+ if (s == NULL)
+ return NULL;
if (*s != '=')
{
/* we just read a keyword, not a name */
if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("unrecognized key word: \"%s\"", name),
errhint("ACL key word must be \"group\" or \"user\".")));
- s = getid(s, name); /* move s to the name beyond the keyword */
+ /* move s to the name beyond the keyword */
+ s = getid(s, name, escontext);
+ if (s == NULL)
+ return NULL;
if (name[0] == '\0')
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing name"),
errhint("A name must follow the \"group\" or \"user\" key word.")));
}
if (*s != '=')
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing \"=\" sign")));
@@ -328,7 +339,7 @@ aclparse(const char *s, AclItem *aip)
read = 0;
break;
default:
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid mode character: must be one of \"%s\"",
ACL_ALL_RIGHTS_STR)));
@@ -340,7 +351,13 @@ aclparse(const char *s, AclItem *aip)
if (name[0] == '\0')
aip->ai_grantee = ACL_ID_PUBLIC;
else
- aip->ai_grantee = get_role_oid(name, false);
+ {
+ aip->ai_grantee = get_role_oid(name, true);
+ if (!OidIsValid(aip->ai_grantee))
+ ereturn(escontext, NULL,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role \"%s\" does not exist", name)));
+ }
/*
* XXX Allow a degree of backward compatibility by defaulting the grantor
@@ -348,12 +365,18 @@ aclparse(const char *s, AclItem *aip)
*/
if (*s == '/')
{
- s = getid(s + 1, name2);
+ s = getid(s + 1, name2, escontext);
+ if (s == NULL)
+ return NULL;
if (name2[0] == '\0')
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("a name must follow the \"/\" sign")));
- aip->ai_grantor = get_role_oid(name2, false);
+ aip->ai_grantor = get_role_oid(name2, true);
+ if (!OidIsValid(aip->ai_grantor))
+ ereturn(escontext, NULL,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role \"%s\" does not exist", name2)));
}
else
{
@@ -569,14 +592,19 @@ Datum
aclitemin(PG_FUNCTION_ARGS)
{
const char *s = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
AclItem *aip;
aip = (AclItem *) palloc(sizeof(AclItem));
- s = aclparse(s, aip);
+
+ s = aclparse(s, aip, escontext);
+ if (s == NULL)
+ PG_RETURN_NULL();
+
while (isspace((unsigned char) *s))
++s;
if (*s)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("extra garbage at the end of the ACL specification")));