Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit467395b

Browse files
committed
Prevent integer overflows in array subscripting calculations.
While we were (mostly) careful about ensuring that the dimensions ofarrays aren't large enough to cause integer overflow, the lower boundvalues were generally not checked. This allows situations wherelower_bound + dimension overflows an integer. It seems that that'sharmless so far as array reading is concerned, except that arrayelements with subscripts notionally exceeding INT_MAX are inaccessible.However, it confuses various array-assignment logic, resulting in apotential for memory stomps.Fix by adding checks that array lower bounds aren't large enough tocause lower_bound + dimension to overflow. (Note: this results indisallowing cases where the last subscript position would be exactlyINT_MAX. In principle we could probably allow that, but there's a lotof code that computes lower_bound + dimension and would need adjustment.It seems doubtful that it's worth the trouble/risk to allow it.)Somewhat independently of that, array_set_element() was carelessabout possible overflow when checking the subscript of a fixed-lengtharray, creating a different route to memory stomps. Fix that too.Security:CVE-2021-32027
1 parent4c7ba55 commit467395b

File tree

5 files changed

+61
-16
lines changed

5 files changed

+61
-16
lines changed

‎src/backend/executor/execExprInterp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,10 @@ ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
28112811
lbs[i]=elem_lbs[i-1];
28122812
}
28132813

2814+
/* check for subscript overflow */
2815+
(void)ArrayGetNItems(ndims,dims);
2816+
ArrayCheckBounds(ndims,dims,lbs);
2817+
28142818
if (havenulls)
28152819
{
28162820
dataoffset=ARR_OVERHEAD_WITHNULLS(ndims,nitems);

‎src/backend/utils/adt/array_userfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ array_cat(PG_FUNCTION_ARGS)
411411

412412
/* Do this mainly for overflow checking */
413413
nitems=ArrayGetNItems(ndims,dims);
414+
ArrayCheckBounds(ndims,dims,lbs);
414415

415416
/* build the result array */
416417
ndatabytes=ndatabytes1+ndatabytes2;

‎src/backend/utils/adt/arrayfuncs.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ array_in(PG_FUNCTION_ARGS)
372372

373373
/* This checks for overflow of the array dimensions */
374374
nitems=ArrayGetNItems(ndim,dim);
375+
ArrayCheckBounds(ndim,dim,lBound);
376+
375377
/* Empty array? */
376378
if (nitems==0)
377379
PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type));
@@ -1321,24 +1323,11 @@ array_recv(PG_FUNCTION_ARGS)
13211323
{
13221324
dim[i]=pq_getmsgint(buf,4);
13231325
lBound[i]=pq_getmsgint(buf,4);
1324-
1325-
/*
1326-
* Check overflow of upper bound. (ArrayGetNItems() below checks that
1327-
* dim[i] >= 0)
1328-
*/
1329-
if (dim[i]!=0)
1330-
{
1331-
intub=lBound[i]+dim[i]-1;
1332-
1333-
if (lBound[i]>ub)
1334-
ereport(ERROR,
1335-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1336-
errmsg("integer out of range")));
1337-
}
13381326
}
13391327

13401328
/* This checks for overflow of array dimensions */
13411329
nitems=ArrayGetNItems(ndim,dim);
1330+
ArrayCheckBounds(ndim,dim,lBound);
13421331

13431332
/*
13441333
* We arrange to look up info about element type, including its receive
@@ -2243,7 +2232,7 @@ array_set_element(Datum arraydatum,
22432232
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
22442233
errmsg("wrong number of array subscripts")));
22452234

2246-
if (indx[0]<0||indx[0]*elmlen>=arraytyplen)
2235+
if (indx[0]<0||indx[0] >=arraytyplen /elmlen)
22472236
ereport(ERROR,
22482237
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
22492238
errmsg("array subscript out of range")));
@@ -2358,10 +2347,13 @@ array_set_element(Datum arraydatum,
23582347
}
23592348
}
23602349

2350+
/* This checks for overflow of the array dimensions */
2351+
newnitems=ArrayGetNItems(ndim,dim);
2352+
ArrayCheckBounds(ndim,dim,lb);
2353+
23612354
/*
23622355
* Compute sizes of items and areas to copy
23632356
*/
2364-
newnitems=ArrayGetNItems(ndim,dim);
23652357
if (newhasnulls)
23662358
overheadlen=ARR_OVERHEAD_WITHNULLS(ndim,newnitems);
23672359
else
@@ -2616,6 +2608,13 @@ array_set_element_expanded(Datum arraydatum,
26162608
}
26172609
}
26182610

2611+
/* Check for overflow of the array dimensions */
2612+
if (dimschanged)
2613+
{
2614+
(void)ArrayGetNItems(ndim,dim);
2615+
ArrayCheckBounds(ndim,dim,lb);
2616+
}
2617+
26192618
/* Now we can calculate linear offset of target item in array */
26202619
offset=ArrayGetOffset(nSubscripts,dim,lb,indx);
26212620

@@ -2934,6 +2933,7 @@ array_set_slice(Datum arraydatum,
29342933

29352934
/* Do this mainly to check for overflow */
29362935
nitems=ArrayGetNItems(ndim,dim);
2936+
ArrayCheckBounds(ndim,dim,lb);
29372937

29382938
/*
29392939
* Make sure source array has enough entries. Note we ignore the shape of
@@ -3348,7 +3348,9 @@ construct_md_array(Datum *elems,
33483348
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
33493349
ndims,MAXDIM)));
33503350

3351+
/* This checks for overflow of the array dimensions */
33513352
nelems=ArrayGetNItems(ndims,dims);
3353+
ArrayCheckBounds(ndims,dims,lbs);
33523354

33533355
/* if ndims <= 0 or any dims[i] == 0, return empty array */
33543356
if (nelems <=0)
@@ -5423,6 +5425,10 @@ makeArrayResultArr(ArrayBuildStateArr *astate,
54235425
intdataoffset,
54245426
nbytes;
54255427

5428+
/* Check for overflow of the array dimensions */
5429+
(void)ArrayGetNItems(astate->ndims,astate->dims);
5430+
ArrayCheckBounds(astate->ndims,astate->dims,astate->lbs);
5431+
54265432
/* Compute required space */
54275433
nbytes=astate->nbytes;
54285434
if (astate->nullbitmap!=NULL)
@@ -5852,7 +5858,9 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
58525858
lbsv=deflbs;
58535859
}
58545860

5861+
/* This checks for overflow of the array dimensions */
58555862
nitems=ArrayGetNItems(ndims,dimv);
5863+
ArrayCheckBounds(ndims,dimv,lbsv);
58565864

58575865
/* fast track for empty array */
58585866
if (nitems <=0)

‎src/backend/utils/adt/arrayutils.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include"postgres.h"
1717

1818
#include"catalog/pg_type.h"
19+
#include"common/int.h"
1920
#include"utils/array.h"
2021
#include"utils/builtins.h"
2122
#include"utils/memutils.h"
@@ -111,6 +112,36 @@ ArrayGetNItems(int ndim, const int *dims)
111112
return (int)ret;
112113
}
113114

115+
/*
116+
* Verify sanity of proposed lower-bound values for an array
117+
*
118+
* The lower-bound values must not be so large as to cause overflow when
119+
* calculating subscripts, e.g. lower bound 2147483640 with length 10
120+
* must be disallowed. We actually insist that dims[i] + lb[i] be
121+
* computable without overflow, meaning that an array with last subscript
122+
* equal to INT_MAX will be disallowed.
123+
*
124+
* It is assumed that the caller already called ArrayGetNItems, so that
125+
* overflowed (negative) dims[] values have been eliminated.
126+
*/
127+
void
128+
ArrayCheckBounds(intndim,constint*dims,constint*lb)
129+
{
130+
inti;
131+
132+
for (i=0;i<ndim;i++)
133+
{
134+
/* PG_USED_FOR_ASSERTS_ONLY prevents variable-isn't-read warnings */
135+
int32sumPG_USED_FOR_ASSERTS_ONLY;
136+
137+
if (pg_add_s32_overflow(dims[i],lb[i],&sum))
138+
ereport(ERROR,
139+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
140+
errmsg("array lower bound is too large: %d",
141+
lb[i])));
142+
}
143+
}
144+
114145
/*
115146
* Compute ranges (sub-array dimensions) for an array slice
116147
*

‎src/include/utils/array.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ extern void array_free_iterator(ArrayIterator iterator);
438438
externintArrayGetOffset(intn,constint*dim,constint*lb,constint*indx);
439439
externintArrayGetOffset0(intn,constint*tup,constint*scale);
440440
externintArrayGetNItems(intndim,constint*dims);
441+
externvoidArrayCheckBounds(intndim,constint*dims,constint*lb);
441442
externvoidmda_get_range(intn,int*span,constint*st,constint*endp);
442443
externvoidmda_get_prod(intn,constint*range,int*prod);
443444
externvoidmda_get_offset_values(intn,int*dist,constint*prod,constint*span);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp