From 0e56a01c00737bab39f3b0a192767e9f3110ecda Mon Sep 17 00:00:00 2001 From: Amul Sul Date: Mon, 12 Dec 2022 11:18:23 +0530 Subject: [PATCH v1 01/14] Change aclitemin to allow non-throw error reporting --- src/backend/utils/adt/acl.c | 23 +++++++++++++-------- src/test/regress/expected/type_sanity.out | 25 +++++++++++++++++++++++ src/test/regress/sql/type_sanity.sql | 6 ++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index ed1b6a41cfb..8d0aa603aea 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -85,7 +85,7 @@ static const char *getid(const char *s, char *n); 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, @@ -238,7 +238,7 @@ putid(char *p, const char *s) * UID/GID, id type identifier and mode type values. */ static const char * -aclparse(const char *s, AclItem *aip) +aclparse(const char *s, AclItem *aip, Node *escontext) { AclMode privs, goption, @@ -253,20 +253,20 @@ aclparse(const char *s, AclItem *aip) { /* 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 */ 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"))); @@ -331,7 +331,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))); @@ -353,7 +353,7 @@ aclparse(const char *s, AclItem *aip) { s = getid(s + 1, name2); 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); @@ -572,14 +572,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); + + /* aclparse() returns NULL in case of soft-errors */ + if ((s = aclparse(s, aip, escontext)) == 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"))); diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index d3ac08c9ee3..b2bc0205a76 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -771,3 +771,28 @@ SELECT oid, typname, typtype, typelem, typarray -----+---------+---------+---------+---------- (0 rows) +-- test non-error-throwing API for some core types +SELECT pg_input_is_valid('pg_monitor=r/', 'aclitem'); + pg_input_is_valid +------------------- + f +(1 row) + +SELECT pg_input_error_message('pg_monitor=r/', 'aclitem'); + pg_input_error_message +--------------------------------- + a name must follow the "/" sign +(1 row) + +SELECT pg_input_is_valid('pg_monitor=rY', 'aclitem'); + pg_input_is_valid +------------------- + f +(1 row) + +SELECT pg_input_error_message('pg_monitor=rY', 'aclitem'); + pg_input_error_message +----------------------------------------------------------- + invalid mode character: must be one of "arwdDxtXUCTcsAvz" +(1 row) + diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index 5edc1f1f6ed..080ac15b6c8 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -590,3 +590,9 @@ SELECT oid, typname, typtype, typelem, typarray WHERE a.atttypid=t.oid AND a.attnum > 0 AND a.attrelid='tab_core_types'::regclass); + +-- test non-error-throwing API for some core types +SELECT pg_input_is_valid('pg_monitor=r/', 'aclitem'); +SELECT pg_input_error_message('pg_monitor=r/', 'aclitem'); +SELECT pg_input_is_valid('pg_monitor=rY', 'aclitem'); +SELECT pg_input_error_message('pg_monitor=rY', 'aclitem'); -- 2.18.0