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

Commit31400a6

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 parent4318dae commit31400a6

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
@@ -1366,6 +1366,7 @@ path_in(PG_FUNCTION_ARGS)
13661366
char*s;
13671367
intnpts;
13681368
intsize;
1369+
intbase_size;
13691370
intdepth=0;
13701371

13711372
if ((npts=pair_count(str,',')) <=0)
@@ -1384,7 +1385,15 @@ path_in(PG_FUNCTION_ARGS)
13841385
depth++;
13851386
}
13861387

1387-
size= offsetof(PATH,p[0])+sizeof(path->p[0])*npts;
1388+
base_size=sizeof(path->p[0])*npts;
1389+
size= offsetof(PATH,p[0])+base_size;
1390+
1391+
/* Check for integer overflow */
1392+
if (base_size /npts!=sizeof(path->p[0])||size <=base_size)
1393+
ereport(ERROR,
1394+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1395+
errmsg("too many points requested")));
1396+
13881397
path= (PATH*)palloc(size);
13891398

13901399
SET_VARSIZE(path,size);
@@ -3429,6 +3438,7 @@ poly_in(PG_FUNCTION_ARGS)
34293438
POLYGON*poly;
34303439
intnpts;
34313440
intsize;
3441+
intbase_size;
34323442
intisopen;
34333443
char*s;
34343444

@@ -3437,7 +3447,15 @@ poly_in(PG_FUNCTION_ARGS)
34373447
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
34383448
errmsg("invalid input syntax for type polygon: \"%s\"",str)));
34393449

3440-
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*npts;
3450+
base_size=sizeof(poly->p[0])*npts;
3451+
size= offsetof(POLYGON,p[0])+base_size;
3452+
3453+
/* Check for integer overflow */
3454+
if (base_size /npts!=sizeof(poly->p[0])||size <=base_size)
3455+
ereport(ERROR,
3456+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3457+
errmsg("too many points requested")));
3458+
34413459
poly= (POLYGON*)palloc0(size);/* zero any holes */
34423460

34433461
SET_VARSIZE(poly,size);
@@ -4343,6 +4361,10 @@ path_poly(PG_FUNCTION_ARGS)
43434361
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
43444362
errmsg("open path cannot be converted to polygon")));
43454363

4364+
/*
4365+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4366+
* just a small constant larger.
4367+
*/
43464368
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*path->npts;
43474369
poly= (POLYGON*)palloc(size);
43484370

@@ -4448,6 +4470,10 @@ poly_path(PG_FUNCTION_ARGS)
44484470
intsize;
44494471
inti;
44504472

4473+
/*
4474+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4475+
* smaller by a small constant.
4476+
*/
44514477
size= offsetof(PATH,p[0])+sizeof(path->p[0])*poly->npts;
44524478
path= (PATH*)palloc(size);
44534479

‎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