summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-11-19 03:00:09 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-11-19 03:00:09 +0000
commit8ef289dba12f16f3692c235863a887672499a5d9 (patch)
tree819abde06463716dbbf505c444a69ec6858efe6a
parent25c00833cb694bea1c4fb3caeccbc9a1fb72d6f8 (diff)
downloadpostgresql-8ef289dba12f16f3692c235863a887672499a5d9.tar.gz
Defend against nulls-in-arrays in contrib/intarray. I may have put in
more tests than strictly necessary, but did not feel like tracing call paths in detail ...
-rw-r--r--contrib/intarray/_int.h26
-rw-r--r--contrib/intarray/_int_bool.c2
-rw-r--r--contrib/intarray/_int_gist.c28
-rw-r--r--contrib/intarray/_int_op.c68
-rw-r--r--contrib/intarray/_int_tool.c27
-rw-r--r--contrib/intarray/_intbig_gist.c24
6 files changed, 131 insertions, 44 deletions
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index 702dfaade5..ec09b14973 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -19,13 +19,24 @@
/* useful macros for accessing int4 arrays */
#define ARRPTR(x) ( (int4 *) ARR_DATA_PTR(x) )
-#define ARRNELEMS(x) ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x))
+#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
-#define ARRISVOID(x) ( (x) ? ( ( ARR_NDIM(x) == NDIM ) ? ( ( ARRNELEMS( x ) ) ? 0 : 1 ) : ( ( ARR_NDIM(x) ) ? ( \
- ereport(ERROR, \
- (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
- errmsg("array must be one-dimensional, not %d dimensions", ARRNELEMS( x )))) \
- ,1) : 0 ) ) : 0 )
+/* reject arrays we can't handle; but allow a NULL or empty array */
+#define CHECKARRVALID(x) \
+ do { \
+ if (x) { \
+ if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
+ errmsg("array must be one-dimensional"))); \
+ if (ARR_HASNULL(x)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+ errmsg("array must not contain nulls"))); \
+ } \
+ } while(0)
+
+#define ARRISVOID(x) ((x) == NULL || ARRNELEMS(x) == 0)
#define SORT(x) \
do { \
@@ -52,9 +63,6 @@
typedef char BITVEC[SIGLEN];
typedef char *BITVECP;
-#define SIGPTR(x) ( (BITVECP) ARR_DATA_PTR(x) )
-
-
#define LOOPBYTE(a) \
for(i=0;i<SIGLEN;i++) {\
a;\
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 824dc5b677..8e0b913c01 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -309,6 +309,7 @@ execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
{
CHKVAL chkval;
+ CHECKARRVALID(array);
chkval.arrb = ARRPTR(array);
chkval.arre = chkval.arrb + ARRNELEMS(array);
return execute(
@@ -339,6 +340,7 @@ boolop(PG_FUNCTION_ARGS)
CHKVAL chkval;
bool result;
+ CHECKARRVALID(val);
if (ARRISVOID(val))
{
pfree(val);
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index c5f8818aa3..1e26bcef28 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -44,6 +44,7 @@ g_int_consistent(PG_FUNCTION_ARGS)
/* XXX are we sure it's safe to scribble on the query object here? */
/* XXX what about toasted input? */
/* sort query for fast search, key is already sorted */
+ CHECKARRVALID(query);
if (ARRISVOID(query))
PG_RETURN_BOOL(false);
PREPAREARR(query);
@@ -89,21 +90,30 @@ g_int_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
- int4 i;
- ArrayType *res;
- int totlen = 0,
+ int4 i,
*ptr;
+ ArrayType *res;
+ int totlen = 0;
for (i = 0; i < entryvec->n; i++)
- totlen += ARRNELEMS(GETENTRY(entryvec, i));
+ {
+ ArrayType *ent = GETENTRY(entryvec, i);
+
+ CHECKARRVALID(ent);
+ totlen += ARRNELEMS(ent);
+ }
res = new_intArrayType(totlen);
ptr = ARRPTR(res);
for (i = 0; i < entryvec->n; i++)
{
- memcpy(ptr, ARRPTR(GETENTRY(entryvec, i)), ARRNELEMS(GETENTRY(entryvec, i)) * sizeof(int4));
- ptr += ARRNELEMS(GETENTRY(entryvec, i));
+ ArrayType *ent = GETENTRY(entryvec, i);
+ int nel;
+
+ nel = ARRNELEMS(ent);
+ memcpy(ptr, ARRPTR(ent), nel * sizeof(int4));
+ ptr += nel;
}
QSORT(res, 1);
@@ -130,6 +140,7 @@ g_int_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
+ CHECKARRVALID(r);
PREPAREARR(r);
if (ARRNELEMS(r)>= 2 * MAXNUMRANGE)
@@ -147,6 +158,7 @@ g_int_compress(PG_FUNCTION_ARGS)
so now we work only with internal keys */
r = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ CHECKARRVALID(r);
if (ARRISVOID(r))
{
if (r != (ArrayType *) DatumGetPointer(entry->key))
@@ -207,6 +219,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ CHECKARRVALID(in);
if (ARRISVOID(in))
PG_RETURN_POINTER(entry);
@@ -280,6 +293,9 @@ g_int_same(PG_FUNCTION_ARGS)
int4 *da,
*db;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (n != ARRNELEMS(b))
{
*result = false;
diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c
index 70951bfd47..7a2065bc21 100644
--- a/contrib/intarray/_int_op.c
+++ b/contrib/intarray/_int_op.c
@@ -37,6 +37,8 @@ _int_contains(PG_FUNCTION_ARGS)
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
bool res;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
if (ARRISVOID(a) || ARRISVOID(b))
return FALSE;
@@ -71,9 +73,13 @@ _int_same(PG_FUNCTION_ARGS)
int *da,
*db;
bool result;
- bool avoid = ARRISVOID(a);
- bool bvoid = ARRISVOID(b);
+ bool avoid;
+ bool bvoid;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+ avoid = ARRISVOID(a);
+ bvoid = ARRISVOID(b);
if (avoid || bvoid)
return (avoid && bvoid) ? TRUE : FALSE;
@@ -112,6 +118,8 @@ _int_overlap(PG_FUNCTION_ARGS)
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
bool result;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
if (ARRISVOID(a) || ARRISVOID(b))
return FALSE;
@@ -133,6 +141,9 @@ _int_union(PG_FUNCTION_ARGS)
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
ArrayType *result;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (!ARRISVOID(a))
SORT(a);
if (!ARRISVOID(b))
@@ -155,6 +166,8 @@ _int_inter(PG_FUNCTION_ARGS)
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
ArrayType *result;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
if (ARRISVOID(a) || ARRISVOID(b))
PG_RETURN_POINTER(new_intArrayType(0));
@@ -197,12 +210,6 @@ Datum intarray_del_elem(PG_FUNCTION_ARGS);
Datum intset_union_elem(PG_FUNCTION_ARGS);
Datum intset_subtract(PG_FUNCTION_ARGS);
-#define QSORT(a, direction) \
-if (ARRNELEMS(a) > 1) \
- qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
- (direction) ? compASC : compDESC )
-
-
Datum
intset(PG_FUNCTION_ARGS)
{
@@ -213,7 +220,7 @@ Datum
icount(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- int32 count = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ int32 count = ARRNELEMS(a);
PG_FREE_IF_COPY(a, 0);
PG_RETURN_INT32(count);
@@ -228,6 +235,7 @@ sort(PG_FUNCTION_ARGS)
char *d = (dirstr) ? VARDATA(dirstr) : NULL;
int dir = -1;
+ CHECKARRVALID(a);
if (ARRISVOID(a) || ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
@@ -255,6 +263,7 @@ sort_asc(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ CHECKARRVALID(a);
if (ARRISVOID(a))
PG_RETURN_POINTER(a);
QSORT(a, 1);
@@ -266,6 +275,7 @@ sort_desc(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ CHECKARRVALID(a);
if (ARRISVOID(a))
PG_RETURN_POINTER(a);
QSORT(a, 0);
@@ -277,6 +287,7 @@ uniq(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ CHECKARRVALID(a);
if (ARRISVOID(a) || ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
a = _int_unique(a);
@@ -287,8 +298,10 @@ Datum
idx(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- int32 result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ int32 result;
+ CHECKARRVALID(a);
+ result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
if (result)
result = intarray_match_first(a, PG_GETARG_INT32(1));
PG_FREE_IF_COPY(a, 0);
@@ -305,6 +318,7 @@ subarray(PG_FUNCTION_ARGS)
int32 end = 0;
int32 c;
+ CHECKARRVALID(a);
if (ARRISVOID(a))
{
PG_FREE_IF_COPY(a, 0);
@@ -371,22 +385,29 @@ Datum
intarray_del_elem(PG_FUNCTION_ARGS)
{
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- int32 c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
- int32 *aa = ARRPTR(a);
+ int32 elem = PG_GETARG_INT32(1);
+ int32 c;
+ int32 *aa;
int32 n = 0,
i;
- int32 elem = PG_GETARG_INT32(1);
- for (i = 0; i < c; i++)
- if (aa[i] != elem)
+ CHECKARRVALID(a);
+ if (!ARRISVOID(a))
+ {
+ c = ARRNELEMS(a);
+ aa = ARRPTR(a);
+ for (i = 0; i < c; i++)
{
- if (i > n)
- aa[n++] = aa[i];
- else
- n++;
+ if (aa[i] != elem)
+ {
+ if (i > n)
+ aa[n++] = aa[i];
+ else
+ n++;
+ }
}
- if (c > 0)
a = resize_intArrayType(a, n);
+ }
PG_RETURN_POINTER(a);
}
@@ -408,8 +429,8 @@ intset_subtract(PG_FUNCTION_ARGS)
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
ArrayType *result;
- int32 ca = ARRISVOID(a);
- int32 cb = ARRISVOID(b);
+ int32 ca;
+ int32 cb;
int32 *aa,
*bb,
*r;
@@ -417,6 +438,9 @@ intset_subtract(PG_FUNCTION_ARGS)
i = 0,
k = 0;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
QSORT(a, 1);
a = _int_unique(a);
ca = ARRNELEMS(a);
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
index 13c5d1e9e2..480e16ed9f 100644
--- a/contrib/intarray/_int_tool.c
+++ b/contrib/intarray/_int_tool.c
@@ -12,6 +12,9 @@ inner_int_contains(ArrayType *a, ArrayType *b)
int *da,
*db;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (ARRISVOID(a) || ARRISVOID(b))
return FALSE;
@@ -46,6 +49,9 @@ inner_int_overlap(ArrayType *a, ArrayType *b)
int *da,
*db;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (ARRISVOID(a) || ARRISVOID(b))
return FALSE;
@@ -78,6 +84,9 @@ inner_int_union(ArrayType *a, ArrayType *b)
int i,
j;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (ARRISVOID(a) && ARRISVOID(b))
return new_intArrayType(0);
if (ARRISVOID(a))
@@ -130,6 +139,9 @@ inner_int_inter(ArrayType *a, ArrayType *b)
int i,
j;
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
if (ARRISVOID(a) || ARRISVOID(b))
return new_intArrayType(0);
@@ -243,7 +255,7 @@ copy_intArrayType(ArrayType *a)
ArrayType *r;
r = new_intArrayType(ARRNELEMS(a));
- memmove(r, a, VARSIZE(a));
+ memmove(r, a, VARSIZE(r));
return r;
}
@@ -270,6 +282,8 @@ _int_unique(ArrayType *r)
*data;
int num = ARRNELEMS(r);
+ CHECKARRVALID(r);
+
if (num < 2)
return r;
@@ -302,7 +316,10 @@ intarray_match_first(ArrayType *a, int32 elem)
c,
i;
- c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ CHECKARRVALID(a);
+ if (ARRISVOID(a))
+ return 0;
+ c = ARRNELEMS(a);
aa = ARRPTR(a);
for (i = 0; i < c; i++)
if (aa[i] == elem)
@@ -315,8 +332,10 @@ intarray_add_elem(ArrayType *a, int32 elem)
{
ArrayType *result;
int32 *r;
- int32 c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ int32 c;
+ CHECKARRVALID(a);
+ c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
result = new_intArrayType(c + 1);
r = ARRPTR(result);
if (c > 0)
@@ -332,6 +351,8 @@ intarray_concat_arrays(ArrayType *a, ArrayType *b)
int32 ac = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
int32 bc = (ARRISVOID(b)) ? 0 : ARRNELEMS(b);
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
result = new_intArrayType(ac + bc);
if (ac)
memcpy(ARRPTR(result), ARRPTR(a), ac * sizeof(int32));
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index 237281aec5..0064e450dd 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -66,6 +66,8 @@ _intbig_overlap(GISTTYPE * a, ArrayType *b)
int num = ARRNELEMS(b);
int4 *ptr = ARRPTR(b);
+ CHECKARRVALID(b);
+
while (num--)
{
if (GETBIT(GETSIGN(a), HASHVAL(*ptr)))
@@ -82,6 +84,8 @@ _intbig_contains(GISTTYPE * a, ArrayType *b)
int num = ARRNELEMS(b);
int4 *ptr = ARRPTR(b);
+ CHECKARRVALID(b);
+
while (num--)
{
if (!GETBIT(GETSIGN(a), HASHVAL(*ptr)))
@@ -136,10 +140,17 @@ g_intbig_compress(PG_FUNCTION_ARGS)
int num;
GISTTYPE *res = (GISTTYPE *) palloc(CALCGTSIZE(0));
- ARRISVOID(in);
-
- ptr = ARRPTR(in);
- num = ARRNELEMS(in);
+ CHECKARRVALID(in);
+ if (ARRISVOID(in))
+ {
+ ptr = NULL;
+ num = 0;
+ }
+ else
+ {
+ ptr = ARRPTR(in);
+ num = ARRNELEMS(in);
+ }
memset(res, 0, CALCGTSIZE(0));
res->len = CALCGTSIZE(0);
@@ -492,6 +503,7 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
}
/* XXX what about toasted input? */
+ CHECKARRVALID(query);
if (ARRISVOID(query))
return FALSE;
@@ -510,6 +522,8 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
+ CHECKARRVALID(query);
+
memset(qp, 0, sizeof(BITVEC));
while (num--)
@@ -546,6 +560,8 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
+ CHECKARRVALID(query);
+
memset(qp, 0, sizeof(BITVEC));
while (num--)