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

Commit7a362a1

Browse files
committed
Predict integer overflow to avoid buffer overruns.
Several functions, mostly type input functions, calculated an allocationsize such that the calculation wrapped to a small positive value whenarguments implied a sufficiently-large requirement. Writes past the endof the inadvertent small allocation followed shortly thereafter.Coverity identified the path_in() vulnerability; code inspection led tothe rest. In passing, add check_stack_depth() to prevent stack overflowin related functions.Back-patch to 8.4 (all supported versions). The non-comment hstorechanges touch code that did not exist in 8.4, so that part stops at 9.0.Noah Misch and Heikki Linnakangas, reviewed by Tom Lane.Security:CVE-2014-0064
1 parente4a4fa2 commit7a362a1

File tree

15 files changed

+177
-19
lines changed

15 files changed

+177
-19
lines changed

‎contrib/hstore/hstore.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,25 @@ typedef struct
4949
}HStore;
5050

5151
/*
52-
* it's not possible to get more than 2^28 items into an hstore,
53-
* so we reserve the top few bits of the size field. See hstore_compat.c
54-
* for one reason why.Some bits are left for future use here.
52+
* It's not possible to get more than 2^28 items into an hstore, so we reserve
53+
* the top few bits of the size field. See hstore_compat.c for one reason
54+
* why. Some bits are left for future use here. MaxAllocSize makes the
55+
* practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the
56+
* limit for an hstore full of 4-byte keys and null values. Therefore, we
57+
* don't explicitly check the format-imposed limit.
5558
*/
5659
#defineHS_FLAG_NEWVERSION 0x80000000
5760

5861
#defineHS_COUNT(hsp_) ((hsp_)->size_ & 0x0FFFFFFF)
5962
#defineHS_SETCOUNT(hsp_,c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
6063

6164

65+
/*
66+
* "x" comes from an existing HS_COUNT() (as discussed, <= INT_MAX/24) or a
67+
* Pairs array length (due to MaxAllocSize, <= INT_MAX/40). "lenstr" is no
68+
* more than INT_MAX, that extreme case arising in hstore_from_arrays().
69+
* Therefore, this calculation is limited to about INT_MAX / 5 + INT_MAX.
70+
*/
6271
#defineHSHRDSIZE(sizeof(HStore))
6372
#defineCALCDATASIZE(x,lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
6473

‎contrib/hstore/hstore_io.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include"utils/builtins.h"
1414
#include"utils/json.h"
1515
#include"utils/lsyscache.h"
16+
#include"utils/memutils.h"
1617
#include"utils/typcache.h"
1718

1819
#include"hstore.h"
@@ -439,6 +440,11 @@ hstore_recv(PG_FUNCTION_ARGS)
439440
PG_RETURN_POINTER(out);
440441
}
441442

443+
if (pcount<0||pcount>MaxAllocSize /sizeof(Pairs))
444+
ereport(ERROR,
445+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
446+
errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
447+
pcount, (int) (MaxAllocSize /sizeof(Pairs)))));
442448
pairs=palloc(pcount*sizeof(Pairs));
443449

444450
for (i=0;i<pcount;++i)
@@ -554,6 +560,13 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
554560
TEXTOID,-1, false,'i',
555561
&key_datums,&key_nulls,&key_count);
556562

563+
/* see discussion in hstoreArrayToPairs() */
564+
if (key_count>MaxAllocSize /sizeof(Pairs))
565+
ereport(ERROR,
566+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
567+
errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
568+
key_count, (int) (MaxAllocSize /sizeof(Pairs)))));
569+
557570
/* value_array might be NULL */
558571

559572
if (PG_ARGISNULL(1))
@@ -676,6 +689,13 @@ hstore_from_array(PG_FUNCTION_ARGS)
676689

677690
count=in_count /2;
678691

692+
/* see discussion in hstoreArrayToPairs() */
693+
if (count>MaxAllocSize /sizeof(Pairs))
694+
ereport(ERROR,
695+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
696+
errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
697+
count, (int) (MaxAllocSize /sizeof(Pairs)))));
698+
679699
pairs=palloc(count*sizeof(Pairs));
680700

681701
for (i=0;i<count;++i)
@@ -807,6 +827,7 @@ hstore_from_record(PG_FUNCTION_ARGS)
807827
my_extra->ncolumns=ncolumns;
808828
}
809829

830+
Assert(ncolumns <=MaxTupleAttributeNumber);/* thus, no overflow */
810831
pairs=palloc(ncolumns*sizeof(Pairs));
811832

812833
if (rec)

‎contrib/hstore/hstore_op.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include"catalog/pg_type.h"
99
#include"funcapi.h"
1010
#include"utils/builtins.h"
11+
#include"utils/memutils.h"
1112

1213
#include"hstore.h"
1314

@@ -90,6 +91,19 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
9091
returnNULL;
9192
}
9293

94+
/*
95+
* A text array uses at least eight bytes per element, so any overflow in
96+
* "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
97+
* However, credible improvements to the array format could invalidate
98+
* that assumption. Therefore, use an explicit check rather than relying
99+
* on palloc() to complain.
100+
*/
101+
if (key_count>MaxAllocSize /sizeof(Pairs))
102+
ereport(ERROR,
103+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
104+
errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
105+
key_count, (int) (MaxAllocSize /sizeof(Pairs)))));
106+
93107
key_pairs=palloc(sizeof(Pairs)*key_count);
94108

95109
for (i=0,j=0;i<key_count;i++)
@@ -648,6 +662,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
648662
PG_RETURN_POINTER(out);
649663
}
650664

665+
/* hstoreArrayToPairs() checked overflow */
651666
out_pairs=palloc(sizeof(Pairs)*nkeys);
652667
bufsiz=0;
653668

‎contrib/intarray/_int.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define___INT_H__
66

77
#include"utils/array.h"
8+
#include"utils/memutils.h"
89

910
/* number ranges for compression */
1011
#defineMAXNUMRANGE 100
@@ -137,6 +138,7 @@ typedef struct QUERYTYPE
137138

138139
#defineHDRSIZEQToffsetof(QUERYTYPE, items)
139140
#defineCOMPUTESIZE(size)( HDRSIZEQT + (size) * sizeof(ITEM) )
141+
#defineQUERYTYPEMAXITEMS((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
140142
#defineGETQUERY(x) ( (x)->items )
141143

142144
/* "type" codes for ITEM */

‎contrib/intarray/_int_bool.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ boolop(PG_FUNCTION_ARGS)
448448
staticvoid
449449
findoprnd(ITEM*ptr,int32*pos)
450450
{
451+
/* since this function recurses, it could be driven to stack overflow. */
452+
check_stack_depth();
453+
451454
#ifdefBS_DEBUG
452455
elog(DEBUG3, (ptr[*pos].type==OPR) ?
453456
"%d %c" :"%d %d",*pos,ptr[*pos].val);
@@ -508,7 +511,13 @@ bqarr_in(PG_FUNCTION_ARGS)
508511
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
509512
errmsg("empty query")));
510513

514+
if (state.num>QUERYTYPEMAXITEMS)
515+
ereport(ERROR,
516+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
517+
errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
518+
state.num, (int)QUERYTYPEMAXITEMS)));
511519
commonlen=COMPUTESIZE(state.num);
520+
512521
query= (QUERYTYPE*)palloc(commonlen);
513522
SET_VARSIZE(query,commonlen);
514523
query->size=state.num;

‎contrib/ltree/ltree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include"fmgr.h"
77
#include"tsearch/ts_locale.h"
8+
#include"utils/memutils.h"
89

910
typedefstruct
1011
{
@@ -111,6 +112,8 @@ typedef struct
111112

112113
#defineHDRSIZEQTMAXALIGN(VARHDRSZ + sizeof(int32))
113114
#defineCOMPUTESIZE(size,lenofoperand)( HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand) )
115+
#defineLTXTQUERY_TOO_BIG(size,lenofoperand) \
116+
((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM))
114117
#defineGETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
115118
#defineGETOPERAND(x)( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
116119

‎contrib/ltree/ltree_io.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include<ctype.h>
99

1010
#include"ltree.h"
11+
#include"utils/memutils.h"
1112
#include"crc32.h"
1213

1314
PG_FUNCTION_INFO_V1(ltree_in);
@@ -64,6 +65,11 @@ ltree_in(PG_FUNCTION_ARGS)
6465
ptr+=charlen;
6566
}
6667

68+
if (num+1>MaxAllocSize /sizeof(nodeitem))
69+
ereport(ERROR,
70+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
71+
errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
72+
num+1, (int) (MaxAllocSize /sizeof(nodeitem)))));
6773
list=lptr= (nodeitem*)palloc(sizeof(nodeitem)* (num+1));
6874
ptr=buf;
6975
while (*ptr)
@@ -228,6 +234,11 @@ lquery_in(PG_FUNCTION_ARGS)
228234
}
229235

230236
num++;
237+
if (num>MaxAllocSize /ITEMSIZE)
238+
ereport(ERROR,
239+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
240+
errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
241+
num, (int) (MaxAllocSize /ITEMSIZE))));
231242
curqlevel=tmpql= (lquery_level*)palloc0(ITEMSIZE*num);
232243
ptr=buf;
233244
while (*ptr)

‎contrib/ltree/ltxtquery_io.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include"crc32.h"
1111
#include"ltree.h"
12+
#include"miscadmin.h"
1213

1314
PG_FUNCTION_INFO_V1(ltxtq_in);
1415
Datumltxtq_in(PG_FUNCTION_ARGS);
@@ -212,6 +213,9 @@ makepol(QPRS_STATE *state)
212213
int32lenstack=0;
213214
uint16flag=0;
214215

216+
/* since this function recurses, it could be driven to stack overflow */
217+
check_stack_depth();
218+
215219
while ((type=gettoken_query(state,&val,&lenval,&strval,&flag))!=END)
216220
{
217221
switch (type)
@@ -276,6 +280,9 @@ makepol(QPRS_STATE *state)
276280
staticvoid
277281
findoprnd(ITEM*ptr,int32*pos)
278282
{
283+
/* since this function recurses, it could be driven to stack overflow. */
284+
check_stack_depth();
285+
279286
if (ptr[*pos].type==VAL||ptr[*pos].type==VALTRUE)
280287
{
281288
ptr[*pos].left=0;
@@ -340,8 +347,12 @@ queryin(char *buf)
340347
errmsg("syntax error"),
341348
errdetail("Empty query.")));
342349

343-
/* make finish struct */
350+
if (LTXTQUERY_TOO_BIG(state.num,state.sumlen))
351+
ereport(ERROR,
352+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
353+
errmsg("ltxtquery is too large")));
344354
commonlen=COMPUTESIZE(state.num,state.sumlen);
355+
345356
query= (ltxtquery*)palloc(commonlen);
346357
SET_VARSIZE(query,commonlen);
347358
query->size=state.num;

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ path_in(PG_FUNCTION_ARGS)
13981398
char*s;
13991399
intnpts;
14001400
intsize;
1401+
intbase_size;
14011402
intdepth=0;
14021403

14031404
if ((npts=pair_count(str,',')) <=0)
@@ -1416,7 +1417,15 @@ path_in(PG_FUNCTION_ARGS)
14161417
depth++;
14171418
}
14181419

1419-
size= offsetof(PATH,p[0])+sizeof(path->p[0])*npts;
1420+
base_size=sizeof(path->p[0])*npts;
1421+
size= offsetof(PATH,p[0])+base_size;
1422+
1423+
/* Check for integer overflow */
1424+
if (base_size /npts!=sizeof(path->p[0])||size <=base_size)
1425+
ereport(ERROR,
1426+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1427+
errmsg("too many points requested")));
1428+
14201429
path= (PATH*)palloc(size);
14211430

14221431
SET_VARSIZE(path,size);
@@ -3460,6 +3469,7 @@ poly_in(PG_FUNCTION_ARGS)
34603469
POLYGON*poly;
34613470
intnpts;
34623471
intsize;
3472+
intbase_size;
34633473
intisopen;
34643474
char*s;
34653475

@@ -3468,7 +3478,15 @@ poly_in(PG_FUNCTION_ARGS)
34683478
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
34693479
errmsg("invalid input syntax for type polygon: \"%s\"",str)));
34703480

3471-
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*npts;
3481+
base_size=sizeof(poly->p[0])*npts;
3482+
size= offsetof(POLYGON,p[0])+base_size;
3483+
3484+
/* Check for integer overflow */
3485+
if (base_size /npts!=sizeof(poly->p[0])||size <=base_size)
3486+
ereport(ERROR,
3487+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3488+
errmsg("too many points requested")));
3489+
34723490
poly= (POLYGON*)palloc0(size);/* zero any holes */
34733491

34743492
SET_VARSIZE(poly,size);
@@ -4374,6 +4392,10 @@ path_poly(PG_FUNCTION_ARGS)
43744392
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
43754393
errmsg("open path cannot be converted to polygon")));
43764394

4395+
/*
4396+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4397+
* just a small constant larger.
4398+
*/
43774399
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*path->npts;
43784400
poly= (POLYGON*)palloc(size);
43794401

@@ -4479,6 +4501,10 @@ poly_path(PG_FUNCTION_ARGS)
44794501
intsize;
44804502
inti;
44814503

4504+
/*
4505+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4506+
* smaller by a small constant.
4507+
*/
44824508
size= offsetof(PATH,p[0])+sizeof(path->p[0])*poly->npts;
44834509
path= (PATH*)palloc(size);
44844510

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,13 @@ parse_tsquery(char *buf,
514514
returnquery;
515515
}
516516

517-
/* Pack the QueryItems in the final TSQuery struct to return to caller */
517+
if (TSQUERY_TOO_BIG(list_length(state.polstr),state.sumlen))
518+
ereport(ERROR,
519+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
520+
errmsg("tsquery is too large")));
518521
commonlen=COMPUTESIZE(list_length(state.polstr),state.sumlen);
522+
523+
/* Pack the QueryItems in the final TSQuery struct to return to caller */
519524
query= (TSQuery)palloc0(commonlen);
520525
SET_VARSIZE(query,commonlen);
521526
query->size=list_length(state.polstr);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,11 @@ QTN2QT(QTNode *in)
333333
QTN2QTStatestate;
334334

335335
cntsize(in,&sumlen,&nnode);
336+
337+
if (TSQUERY_TOO_BIG(nnode,sumlen))
338+
ereport(ERROR,
339+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
340+
errmsg("tsquery is too large")));
336341
len=COMPUTESIZE(nnode,sumlen);
337342

338343
out= (TSQuery)palloc0(len);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp