diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-11-19 03:00:09 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-11-19 03:00:09 +0000 |
commit | 8ef289dba12f16f3692c235863a887672499a5d9 (patch) | |
tree | 819abde06463716dbbf505c444a69ec6858efe6a | |
parent | 25c00833cb694bea1c4fb3caeccbc9a1fb72d6f8 (diff) | |
download | postgresql-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.h | 26 | ||||
-rw-r--r-- | contrib/intarray/_int_bool.c | 2 | ||||
-rw-r--r-- | contrib/intarray/_int_gist.c | 28 | ||||
-rw-r--r-- | contrib/intarray/_int_op.c | 68 | ||||
-rw-r--r-- | contrib/intarray/_int_tool.c | 27 | ||||
-rw-r--r-- | contrib/intarray/_intbig_gist.c | 24 |
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--) |