aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-11-18 02:38:24 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-11-18 02:38:24 +0000
commit1d0d8d3c38e4c5611769c0cd9dd9c0faeee57b84 (patch)
tree373157511529770d2581ad615f5432bf6cc70e7f /src/backend
parent3201b7f3d0657db9d5c29c3155eeae0f2066bf56 (diff)
downloadpostgresql-1d0d8d3c38e4c5611769c0cd9dd9c0faeee57b84.tar.gz
postgresql-1d0d8d3c38e4c5611769c0cd9dd9c0faeee57b84.zip
Mop-up for nulls-in-arrays patch: fix some places that access array
contents directly.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/adt/acl.c47
-rw-r--r--src/backend/utils/adt/varlena.c52
2 files changed, 76 insertions, 23 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index a1080b59f60..9282c417d01 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.128 2005/11/17 22:14:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.129 2005/11/18 02:38:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,6 +67,7 @@ static List *cached_membership_roles = NIL;
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 bool aclitem_match(const AclItem *a1, const AclItem *a2);
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
@@ -360,6 +361,26 @@ allocacl(int n)
}
/*
+ * Verify that an ACL array is acceptable (one-dimensional and has no nulls)
+ */
+static void
+check_acl(const Acl *acl)
+{
+ if (ARR_ELEMTYPE(acl) != ACLITEMOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("ACL array contains wrong datatype")));
+ if (ARR_NDIM(acl) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("ACL arrays must be one-dimensional")));
+ if (ARR_HASNULL(acl))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("ACL arrays must not contain nulls")));
+}
+
+/*
* aclitemin
* Allocates storage for, and fills in, a new AclItem given a string
* 's' that contains an ACL specification. See aclparse for details.
@@ -612,15 +633,8 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
int dst,
num;
- /* These checks for null input are probably dead code, but... */
- if (!old_acl || ACL_NUM(old_acl) < 0)
- old_acl = allocacl(0);
- if (!mod_aip)
- {
- new_acl = allocacl(ACL_NUM(old_acl));
- memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
- return new_acl;
- }
+ /* Caller probably already checked old_acl, but be safe */
+ check_acl(old_acl);
/* If granting grant options, check for circularity */
if (modechg != ACL_MODECHG_DEL &&
@@ -740,6 +754,8 @@ aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
targ,
num;
+ check_acl(old_acl);
+
/*
* Make a copy of the given ACL, substituting new owner ID for old
* wherever it appears as either grantor or grantee. Also note if the new
@@ -836,6 +852,8 @@ check_circularity(const Acl *old_acl, const AclItem *mod_aip,
num;
AclMode own_privs;
+ check_acl(old_acl);
+
/*
* For now, grant options can only be granted to roles, not PUBLIC.
* Otherwise we'd have to work a bit harder here.
@@ -916,6 +934,8 @@ recursive_revoke(Acl *acl,
int i,
num;
+ check_acl(acl);
+
/* The owner can never truly lose grant options, so short-circuit */
if (grantee == ownerId)
return acl;
@@ -1005,6 +1025,8 @@ aclmask(const Acl *acl, Oid roleid, Oid ownerId,
if (acl == NULL)
elog(ERROR, "null ACL");
+ check_acl(acl);
+
/* Quick exit for mask == 0 */
if (mask == 0)
return 0;
@@ -1091,6 +1113,8 @@ aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
if (acl == NULL)
elog(ERROR, "null ACL");
+ check_acl(acl);
+
/* Quick exit for mask == 0 */
if (mask == 0)
return 0;
@@ -1151,6 +1175,8 @@ aclmembers(const Acl *acl, Oid **roleids)
return 0;
}
+ check_acl(acl);
+
/* Allocate the worst-case space requirement */
list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
acldat = ACL_DAT(acl);
@@ -1240,6 +1266,7 @@ aclcontains(PG_FUNCTION_ARGS)
int i,
num;
+ check_acl(acl);
num = ACL_NUM(acl);
aidat = ACL_DAT(acl);
for (i = 0; i < num; ++i)
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 1f6c176f640..dd877c7d3f0 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.139 2005/10/29 00:31:51 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.140 2005/11/18 02:38:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2491,16 +2491,18 @@ array_to_text(PG_FUNCTION_ARGS)
int nitems,
*dims,
ndims;
- char *p;
Oid element_type;
int typlen;
bool typbyval;
char typalign;
StringInfo result_str = makeStringInfo();
+ bool printed = false;
+ char *p;
+ bits8 *bitmap;
+ int bitmask;
int i;
ArrayMetaState *my_extra;
- p = ARR_DATA_PTR(v);
ndims = ARR_NDIM(v);
dims = ARR_DIMS(v);
nitems = ArrayGetNItems(ndims, dims);
@@ -2522,7 +2524,7 @@ array_to_text(PG_FUNCTION_ARGS)
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
sizeof(ArrayMetaState));
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
+ my_extra->element_type = ~element_type;
}
if (my_extra->element_type != element_type)
@@ -2542,23 +2544,47 @@ array_to_text(PG_FUNCTION_ARGS)
typbyval = my_extra->typbyval;
typalign = my_extra->typalign;
+ p = ARR_DATA_PTR(v);
+ bitmap = ARR_NULLBITMAP(v);
+ bitmask = 1;
+
for (i = 0; i < nitems; i++)
{
Datum itemvalue;
char *value;
- itemvalue = fetch_att(p, typbyval, typlen);
+ /* Get source element, checking for NULL */
+ if (bitmap && (*bitmap & bitmask) == 0)
+ {
+ /* we ignore nulls */
+ }
+ else
+ {
+ itemvalue = fetch_att(p, typbyval, typlen);
- value = DatumGetCString(FunctionCall1(&my_extra->proc,
- itemvalue));
+ value = DatumGetCString(FunctionCall1(&my_extra->proc,
+ itemvalue));
- if (i > 0)
- appendStringInfo(result_str, "%s%s", fldsep, value);
- else
- appendStringInfoString(result_str, value);
+ if (printed)
+ appendStringInfo(result_str, "%s%s", fldsep, value);
+ else
+ appendStringInfoString(result_str, value);
+ printed = true;
+
+ p = att_addlength(p, typlen, PointerGetDatum(p));
+ p = (char *) att_align(p, typalign);
+ }
- p = att_addlength(p, typlen, PointerGetDatum(p));
- p = (char *) att_align(p, typalign);
+ /* advance bitmap pointer if any */
+ if (bitmap)
+ {
+ bitmask <<= 1;
+ if (bitmask == 0x100)
+ {
+ bitmap++;
+ bitmask = 1;
+ }
+ }
}
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));