Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8ef289d

Browse files
committed
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 ...
1 parent 25c0083 commit 8ef289d

File tree

6 files changed

+131
-44
lines changed

6 files changed

+131
-44
lines changed

contrib/intarray/_int.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,24 @@
1919

2020
/* useful macros for accessing int4 arrays */
2121
#define ARRPTR(x) ( (int4 *) ARR_DATA_PTR(x) )
22-
#define ARRNELEMS(x) ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x))
22+
#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
2323

24-
#define ARRISVOID(x) ( (x) ? ( ( ARR_NDIM(x) == NDIM ) ? ( ( ARRNELEMS( x ) ) ? 0 : 1 ) : ( ( ARR_NDIM(x) ) ? ( \
25-
ereport(ERROR, \
26-
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
27-
errmsg("array must be one-dimensional, not %d dimensions", ARRNELEMS( x )))) \
28-
,1) : 0 ) ) : 0 )
24+
/* reject arrays we can't handle; but allow a NULL or empty array */
25+
#define CHECKARRVALID(x) \
26+
do { \
27+
if (x) { \
28+
if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
29+
ereport(ERROR, \
30+
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
31+
errmsg("array must be one-dimensional"))); \
32+
if (ARR_HASNULL(x)) \
33+
ereport(ERROR, \
34+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
35+
errmsg("array must not contain nulls"))); \
36+
} \
37+
} while(0)
38+
39+
#define ARRISVOID(x) ((x) == NULL || ARRNELEMS(x) == 0)
2940

3041
#define SORT(x) \
3142
do { \
@@ -52,9 +63,6 @@
5263
typedef char BITVEC[SIGLEN];
5364
typedef char *BITVECP;
5465

55-
#define SIGPTR(x) ( (BITVECP) ARR_DATA_PTR(x) )
56-
57-
5866
#define LOOPBYTE(a) \
5967
for(i=0;i<SIGLEN;i++) {\
6068
a;\

contrib/intarray/_int_bool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
309309
{
310310
CHKVAL chkval;
311311

312+
CHECKARRVALID(array);
312313
chkval.arrb = ARRPTR(array);
313314
chkval.arre = chkval.arrb + ARRNELEMS(array);
314315
return execute(
@@ -339,6 +340,7 @@ boolop(PG_FUNCTION_ARGS)
339340
CHKVAL chkval;
340341
bool result;
341342

343+
CHECKARRVALID(val);
342344
if (ARRISVOID(val))
343345
{
344346
pfree(val);

contrib/intarray/_int_gist.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ g_int_consistent(PG_FUNCTION_ARGS)
4444
/* XXX are we sure it's safe to scribble on the query object here? */
4545
/* XXX what about toasted input? */
4646
/* sort query for fast search, key is already sorted */
47+
CHECKARRVALID(query);
4748
if (ARRISVOID(query))
4849
PG_RETURN_BOOL(false);
4950
PREPAREARR(query);
@@ -89,21 +90,30 @@ g_int_union(PG_FUNCTION_ARGS)
8990
{
9091
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
9192
int *size = (int *) PG_GETARG_POINTER(1);
92-
int4 i;
93-
ArrayType *res;
94-
int totlen = 0,
93+
int4 i,
9594
*ptr;
95+
ArrayType *res;
96+
int totlen = 0;
9697

9798
for (i = 0; i < entryvec->n; i++)
98-
totlen += ARRNELEMS(GETENTRY(entryvec, i));
99+
{
100+
ArrayType *ent = GETENTRY(entryvec, i);
101+
102+
CHECKARRVALID(ent);
103+
totlen += ARRNELEMS(ent);
104+
}
99105

100106
res = new_intArrayType(totlen);
101107
ptr = ARRPTR(res);
102108

103109
for (i = 0; i < entryvec->n; i++)
104110
{
105-
memcpy(ptr, ARRPTR(GETENTRY(entryvec, i)), ARRNELEMS(GETENTRY(entryvec, i)) * sizeof(int4));
106-
ptr += ARRNELEMS(GETENTRY(entryvec, i));
111+
ArrayType *ent = GETENTRY(entryvec, i);
112+
int nel;
113+
114+
nel = ARRNELEMS(ent);
115+
memcpy(ptr, ARRPTR(ent), nel * sizeof(int4));
116+
ptr += nel;
107117
}
108118

109119
QSORT(res, 1);
@@ -130,6 +140,7 @@ g_int_compress(PG_FUNCTION_ARGS)
130140
if (entry->leafkey)
131141
{
132142
r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
143+
CHECKARRVALID(r);
133144
PREPAREARR(r);
134145

135146
if (ARRNELEMS(r)>= 2 * MAXNUMRANGE)
@@ -147,6 +158,7 @@ g_int_compress(PG_FUNCTION_ARGS)
147158
so now we work only with internal keys */
148159

149160
r = (ArrayType *) PG_DETOAST_DATUM(entry->key);
161+
CHECKARRVALID(r);
150162
if (ARRISVOID(r))
151163
{
152164
if (r != (ArrayType *) DatumGetPointer(entry->key))
@@ -207,6 +219,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
207219

208220
in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
209221

222+
CHECKARRVALID(in);
210223
if (ARRISVOID(in))
211224
PG_RETURN_POINTER(entry);
212225

@@ -280,6 +293,9 @@ g_int_same(PG_FUNCTION_ARGS)
280293
int4 *da,
281294
*db;
282295

296+
CHECKARRVALID(a);
297+
CHECKARRVALID(b);
298+
283299
if (n != ARRNELEMS(b))
284300
{
285301
*result = false;

contrib/intarray/_int_op.c

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ _int_contains(PG_FUNCTION_ARGS)
3737
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
3838
bool res;
3939

40+
CHECKARRVALID(a);
41+
CHECKARRVALID(b);
4042
if (ARRISVOID(a) || ARRISVOID(b))
4143
return FALSE;
4244

@@ -71,9 +73,13 @@ _int_same(PG_FUNCTION_ARGS)
7173
int *da,
7274
*db;
7375
bool result;
74-
bool avoid = ARRISVOID(a);
75-
bool bvoid = ARRISVOID(b);
76+
bool avoid;
77+
bool bvoid;
7678

79+
CHECKARRVALID(a);
80+
CHECKARRVALID(b);
81+
avoid = ARRISVOID(a);
82+
bvoid = ARRISVOID(b);
7783
if (avoid || bvoid)
7884
return (avoid && bvoid) ? TRUE : FALSE;
7985

@@ -112,6 +118,8 @@ _int_overlap(PG_FUNCTION_ARGS)
112118
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
113119
bool result;
114120

121+
CHECKARRVALID(a);
122+
CHECKARRVALID(b);
115123
if (ARRISVOID(a) || ARRISVOID(b))
116124
return FALSE;
117125

@@ -133,6 +141,9 @@ _int_union(PG_FUNCTION_ARGS)
133141
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
134142
ArrayType *result;
135143

144+
CHECKARRVALID(a);
145+
CHECKARRVALID(b);
146+
136147
if (!ARRISVOID(a))
137148
SORT(a);
138149
if (!ARRISVOID(b))
@@ -155,6 +166,8 @@ _int_inter(PG_FUNCTION_ARGS)
155166
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
156167
ArrayType *result;
157168

169+
CHECKARRVALID(a);
170+
CHECKARRVALID(b);
158171
if (ARRISVOID(a) || ARRISVOID(b))
159172
PG_RETURN_POINTER(new_intArrayType(0));
160173

@@ -197,12 +210,6 @@ Datum intarray_del_elem(PG_FUNCTION_ARGS);
197210
Datum intset_union_elem(PG_FUNCTION_ARGS);
198211
Datum intset_subtract(PG_FUNCTION_ARGS);
199212

200-
#define QSORT(a, direction) \
201-
if (ARRNELEMS(a) > 1) \
202-
qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
203-
(direction) ? compASC : compDESC )
204-
205-
206213
Datum
207214
intset(PG_FUNCTION_ARGS)
208215
{
@@ -213,7 +220,7 @@ Datum
213220
icount(PG_FUNCTION_ARGS)
214221
{
215222
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
216-
int32 count = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
223+
int32 count = ARRNELEMS(a);
217224

218225
PG_FREE_IF_COPY(a, 0);
219226
PG_RETURN_INT32(count);
@@ -228,6 +235,7 @@ sort(PG_FUNCTION_ARGS)
228235
char *d = (dirstr) ? VARDATA(dirstr) : NULL;
229236
int dir = -1;
230237

238+
CHECKARRVALID(a);
231239
if (ARRISVOID(a) || ARRNELEMS(a) < 2)
232240
PG_RETURN_POINTER(a);
233241

@@ -255,6 +263,7 @@ sort_asc(PG_FUNCTION_ARGS)
255263
{
256264
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
257265

266+
CHECKARRVALID(a);
258267
if (ARRISVOID(a))
259268
PG_RETURN_POINTER(a);
260269
QSORT(a, 1);
@@ -266,6 +275,7 @@ sort_desc(PG_FUNCTION_ARGS)
266275
{
267276
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
268277

278+
CHECKARRVALID(a);
269279
if (ARRISVOID(a))
270280
PG_RETURN_POINTER(a);
271281
QSORT(a, 0);
@@ -277,6 +287,7 @@ uniq(PG_FUNCTION_ARGS)
277287
{
278288
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
279289

290+
CHECKARRVALID(a);
280291
if (ARRISVOID(a) || ARRNELEMS(a) < 2)
281292
PG_RETURN_POINTER(a);
282293
a = _int_unique(a);
@@ -287,8 +298,10 @@ Datum
287298
idx(PG_FUNCTION_ARGS)
288299
{
289300
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
290-
int32 result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
301+
int32 result;
291302

303+
CHECKARRVALID(a);
304+
result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
292305
if (result)
293306
result = intarray_match_first(a, PG_GETARG_INT32(1));
294307
PG_FREE_IF_COPY(a, 0);
@@ -305,6 +318,7 @@ subarray(PG_FUNCTION_ARGS)
305318
int32 end = 0;
306319
int32 c;
307320

321+
CHECKARRVALID(a);
308322
if (ARRISVOID(a))
309323
{
310324
PG_FREE_IF_COPY(a, 0);
@@ -371,22 +385,29 @@ Datum
371385
intarray_del_elem(PG_FUNCTION_ARGS)
372386
{
373387
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
374-
int32 c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
375-
int32 *aa = ARRPTR(a);
388+
int32 elem = PG_GETARG_INT32(1);
389+
int32 c;
390+
int32 *aa;
376391
int32 n = 0,
377392
i;
378-
int32 elem = PG_GETARG_INT32(1);
379393

380-
for (i = 0; i < c; i++)
381-
if (aa[i] != elem)
394+
CHECKARRVALID(a);
395+
if (!ARRISVOID(a))
396+
{
397+
c = ARRNELEMS(a);
398+
aa = ARRPTR(a);
399+
for (i = 0; i < c; i++)
382400
{
383-
if (i > n)
384-
aa[n++] = aa[i];
385-
else
386-
n++;
401+
if (aa[i] != elem)
402+
{
403+
if (i > n)
404+
aa[n++] = aa[i];
405+
else
406+
n++;
407+
}
387408
}
388-
if (c > 0)
389409
a = resize_intArrayType(a, n);
410+
}
390411
PG_RETURN_POINTER(a);
391412
}
392413

@@ -408,15 +429,18 @@ intset_subtract(PG_FUNCTION_ARGS)
408429
ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
409430
ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
410431
ArrayType *result;
411-
int32 ca = ARRISVOID(a);
412-
int32 cb = ARRISVOID(b);
432+
int32 ca;
433+
int32 cb;
413434
int32 *aa,
414435
*bb,
415436
*r;
416437
int32 n = 0,
417438
i = 0,
418439
k = 0;
419440

441+
CHECKARRVALID(a);
442+
CHECKARRVALID(b);
443+
420444
QSORT(a, 1);
421445
a = _int_unique(a);
422446
ca = ARRNELEMS(a);

0 commit comments

Comments
 (0)