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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy