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

Commit12bbce1

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 parentf416622 commit12bbce1

File tree

15 files changed

+169
-19
lines changed

15 files changed

+169
-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
@@ -9,6 +9,7 @@
99
#include"funcapi.h"
1010
#include"libpq/pqformat.h"
1111
#include"utils/lsyscache.h"
12+
#include"utils/memutils.h"
1213
#include"utils/typcache.h"
1314

1415
#include"hstore.h"
@@ -437,6 +438,11 @@ hstore_recv(PG_FUNCTION_ARGS)
437438
PG_RETURN_POINTER(out);
438439
}
439440

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

442448
for (i=0;i<pcount;++i)
@@ -552,6 +558,13 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
552558
TEXTOID,-1, false,'i',
553559
&key_datums,&key_nulls,&key_count);
554560

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

557570
if (PG_ARGISNULL(1))
@@ -674,6 +687,13 @@ hstore_from_array(PG_FUNCTION_ARGS)
674687

675688
count=in_count /2;
676689

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

679699
for (i=0;i<count;++i)
@@ -805,6 +825,7 @@ hstore_from_record(PG_FUNCTION_ARGS)
805825
my_extra->ncolumns=ncolumns;
806826
}
807827

828+
Assert(ncolumns <=MaxTupleAttributeNumber);/* thus, no overflow */
808829
pairs=palloc(ncolumns*sizeof(Pairs));
809830

810831
if (rec)

‎contrib/hstore/hstore_op.c

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

1112
#include"hstore.h"
1213

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

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

94108
for (i=0,j=0;i<key_count;i++)
@@ -647,6 +661,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
647661
PG_RETURN_POINTER(out);
648662
}
649663

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

‎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
@@ -451,6 +451,9 @@ boolop(PG_FUNCTION_ARGS)
451451
staticvoid
452452
findoprnd(ITEM*ptr,int4*pos)
453453
{
454+
/* since this function recurses, it could be driven to stack overflow. */
455+
check_stack_depth();
456+
454457
#ifdefBS_DEBUG
455458
elog(DEBUG3, (ptr[*pos].type==OPR) ?
456459
"%d %c" :"%d %d",*pos,ptr[*pos].val);
@@ -511,7 +514,13 @@ bqarr_in(PG_FUNCTION_ARGS)
511514
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
512515
errmsg("empty query")));
513516

517+
if (state.num>QUERYTYPEMAXITEMS)
518+
ereport(ERROR,
519+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
520+
errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
521+
state.num, (int)QUERYTYPEMAXITEMS)));
514522
commonlen=COMPUTESIZE(state.num);
523+
515524
query= (QUERYTYPE*)palloc(commonlen);
516525
SET_VARSIZE(query,commonlen);
517526
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(int4))
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);
@@ -213,6 +214,9 @@ makepol(QPRS_STATE *state)
213214
int4lenstack=0;
214215
uint16flag=0;
215216

217+
/* since this function recurses, it could be driven to stack overflow */
218+
check_stack_depth();
219+
216220
while ((type=gettoken_query(state,&val,&lenval,&strval,&flag))!=END)
217221
{
218222
switch (type)
@@ -277,6 +281,9 @@ makepol(QPRS_STATE *state)
277281
staticvoid
278282
findoprnd(ITEM*ptr,int4*pos)
279283
{
284+
/* since this function recurses, it could be driven to stack overflow. */
285+
check_stack_depth();
286+
280287
if (ptr[*pos].type==VAL||ptr[*pos].type==VALTRUE)
281288
{
282289
ptr[*pos].left=0;
@@ -341,8 +348,12 @@ queryin(char *buf)
341348
errmsg("syntax error"),
342349
errdetail("Empty query.")));
343350

344-
/* make finish struct */
351+
if (LTXTQUERY_TOO_BIG(state.num,state.sumlen))
352+
ereport(ERROR,
353+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
354+
errmsg("ltxtquery is too large")));
345355
commonlen=COMPUTESIZE(state.num,state.sumlen);
356+
346357
query= (ltxtquery*)palloc(commonlen);
347358
SET_VARSIZE(query,commonlen);
348359
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
@@ -1403,6 +1403,7 @@ path_in(PG_FUNCTION_ARGS)
14031403
char*s;
14041404
intnpts;
14051405
intsize;
1406+
intbase_size;
14061407
intdepth=0;
14071408

14081409
if ((npts=pair_count(str,',')) <=0)
@@ -1421,7 +1422,15 @@ path_in(PG_FUNCTION_ARGS)
14211422
depth++;
14221423
}
14231424

1424-
size= offsetof(PATH,p[0])+sizeof(path->p[0])*npts;
1425+
base_size=sizeof(path->p[0])*npts;
1426+
size= offsetof(PATH,p[0])+base_size;
1427+
1428+
/* Check for integer overflow */
1429+
if (base_size /npts!=sizeof(path->p[0])||size <=base_size)
1430+
ereport(ERROR,
1431+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1432+
errmsg("too many points requested")));
1433+
14251434
path= (PATH*)palloc(size);
14261435

14271436
SET_VARSIZE(path,size);
@@ -3465,6 +3474,7 @@ poly_in(PG_FUNCTION_ARGS)
34653474
POLYGON*poly;
34663475
intnpts;
34673476
intsize;
3477+
intbase_size;
34683478
intisopen;
34693479
char*s;
34703480

@@ -3473,7 +3483,15 @@ poly_in(PG_FUNCTION_ARGS)
34733483
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
34743484
errmsg("invalid input syntax for type polygon: \"%s\"",str)));
34753485

3476-
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*npts;
3486+
base_size=sizeof(poly->p[0])*npts;
3487+
size= offsetof(POLYGON,p[0])+base_size;
3488+
3489+
/* Check for integer overflow */
3490+
if (base_size /npts!=sizeof(poly->p[0])||size <=base_size)
3491+
ereport(ERROR,
3492+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3493+
errmsg("too many points requested")));
3494+
34773495
poly= (POLYGON*)palloc0(size);/* zero any holes */
34783496

34793497
SET_VARSIZE(poly,size);
@@ -4379,6 +4397,10 @@ path_poly(PG_FUNCTION_ARGS)
43794397
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
43804398
errmsg("open path cannot be converted to polygon")));
43814399

4400+
/*
4401+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4402+
* just a small constant larger.
4403+
*/
43824404
size= offsetof(POLYGON,p[0])+sizeof(poly->p[0])*path->npts;
43834405
poly= (POLYGON*)palloc(size);
43844406

@@ -4484,6 +4506,10 @@ poly_path(PG_FUNCTION_ARGS)
44844506
intsize;
44854507
inti;
44864508

4509+
/*
4510+
* Never overflows: the old size fit in MaxAllocSize, and the new size is
4511+
* smaller by a small constant.
4512+
*/
44874513
size= offsetof(PATH,p[0])+sizeof(path->p[0])*poly->npts;
44884514
path= (PATH*)palloc(size);
44894515

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

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

518-
/* Pack the QueryItems in the final TSQuery struct to return to caller */
518+
if (TSQUERY_TOO_BIG(list_length(state.polstr),state.sumlen))
519+
ereport(ERROR,
520+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
521+
errmsg("tsquery is too large")));
519522
commonlen=COMPUTESIZE(list_length(state.polstr),state.sumlen);
523+
524+
/* Pack the QueryItems in the final TSQuery struct to return to caller */
520525
query= (TSQuery)palloc0(commonlen);
521526
SET_VARSIZE(query,commonlen);
522527
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);

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include"miscadmin.h"
2828
#include"libpq/pqformat.h"
2929
#include"utils/builtins.h"
30+
#include"utils/memutils.h"
3031
#include"utils/snapmgr.h"
3132

3233

@@ -66,6 +67,8 @@ typedef struct
6667

6768
#defineTXID_SNAPSHOT_SIZE(nxip) \
6869
(offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))
70+
#defineTXID_SNAPSHOT_MAX_NXIP \
71+
((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))
6972

7073
/*
7174
* Epoch values from xact.c
@@ -445,20 +448,12 @@ txid_snapshot_recv(PG_FUNCTION_ARGS)
445448
txidlast=0;
446449
intnxip;
447450
inti;
448-
intavail;
449-
intexpect;
450451
txidxmin,
451452
xmax;
452453

453-
/*
454-
* load nxip and check for nonsense.
455-
*
456-
* (nxip > avail) check is against int overflows in 'expect'.
457-
*/
454+
/* load and validate nxip */
458455
nxip=pq_getmsgint(buf,4);
459-
avail=buf->len-buf->cursor;
460-
expect=8+8+nxip*8;
461-
if (nxip<0||nxip>avail||expect>avail)
456+
if (nxip<0||nxip>TXID_SNAPSHOT_MAX_NXIP)
462457
gotobad_format;
463458

464459
xmin=pq_getmsgint64(buf);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp