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

Commit2c3203e

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 parentb9c3bb1 commit2c3203e

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
@@ -11,6 +11,7 @@
1111
#include"funcapi.h"
1212
#include"libpq/pqformat.h"
1313
#include"utils/lsyscache.h"
14+
#include"utils/memutils.h"
1415
#include"utils/typcache.h"
1516

1617
#include"hstore.h"
@@ -438,6 +439,11 @@ hstore_recv(PG_FUNCTION_ARGS)
438439
PG_RETURN_POINTER(out);
439440
}
440441

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

443449
for (i=0;i<pcount;++i)
@@ -553,6 +559,13 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
553559
TEXTOID,-1, false,'i',
554560
&key_datums,&key_nulls,&key_count);
555561

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

558571
if (PG_ARGISNULL(1))
@@ -675,6 +688,13 @@ hstore_from_array(PG_FUNCTION_ARGS)
675688

676689
count=in_count /2;
677690

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

680700
for (i=0;i<count;++i)
@@ -806,6 +826,7 @@ hstore_from_record(PG_FUNCTION_ARGS)
806826
my_extra->ncolumns=ncolumns;
807827
}
808828

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

811832
if (rec)

‎contrib/hstore/hstore_op.c

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

1314
#include"hstore.h"
1415

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

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

96110
for (i=0,j=0;i<key_count;i++)
@@ -645,6 +659,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
645659
PG_RETURN_POINTER(out);
646660
}
647661

662+
/* hstoreArrayToPairs() checked overflow */
648663
out_pairs=palloc(sizeof(Pairs)*nkeys);
649664
bufsiz=0;
650665

‎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
@@ -142,6 +143,7 @@ typedef struct
142143

143144
#defineHDRSIZEQT(VARHDRSZ + sizeof(int4))
144145
#defineCOMPUTESIZE(size)( HDRSIZEQT + size * sizeof(ITEM) )
146+
#defineQUERYTYPEMAXITEMS((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
145147
#defineGETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
146148

147149
#defineEND0

‎contrib/intarray/_int_bool.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ boolop(PG_FUNCTION_ARGS)
416416
staticvoid
417417
findoprnd(ITEM*ptr,int4*pos)
418418
{
419+
/* since this function recurses, it could be driven to stack overflow. */
420+
check_stack_depth();
421+
419422
#ifdefBS_DEBUG
420423
elog(DEBUG3, (ptr[*pos].type==OPR) ?
421424
"%d %c" :"%d %d",*pos,ptr[*pos].val);
@@ -476,7 +479,13 @@ bqarr_in(PG_FUNCTION_ARGS)
476479
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
477480
errmsg("empty query")));
478481

482+
if (state.num>QUERYTYPEMAXITEMS)
483+
ereport(ERROR,
484+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
485+
errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
486+
state.num, (int)QUERYTYPEMAXITEMS)));
479487
commonlen=COMPUTESIZE(state.num);
488+
480489
query= (QUERYTYPE*)palloc(commonlen);
481490
SET_VARSIZE(query,commonlen);
482491
query->size=state.num;

‎contrib/ltree/ltree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include"postgres.h"
77
#include"fmgr.h"
88
#include"tsearch/ts_locale.h"
9+
#include"utils/memutils.h"
910

1011
typedefstruct
1112
{
@@ -112,6 +113,8 @@ typedef struct
112113

113114
#defineHDRSIZEQTMAXALIGN(VARHDRSZ + sizeof(int4))
114115
#defineCOMPUTESIZE(size,lenofoperand)( HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand) )
116+
#defineLTXTQUERY_TOO_BIG(size,lenofoperand) \
117+
((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM))
115118
#defineGETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
116119
#defineGETOPERAND(x)( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
117120

‎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
@@ -517,8 +517,13 @@ parse_tsquery(char *buf,
517517
returnquery;
518518
}
519519

520-
/* Pack the QueryItems in the final TSQuery struct to return to caller */
520+
if (TSQUERY_TOO_BIG(list_length(state.polstr),state.sumlen))
521+
ereport(ERROR,
522+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
523+
errmsg("tsquery is too large")));
521524
commonlen=COMPUTESIZE(list_length(state.polstr),state.sumlen);
525+
526+
/* Pack the QueryItems in the final TSQuery struct to return to caller */
522527
query= (TSQuery)palloc0(commonlen);
523528
SET_VARSIZE(query,commonlen);
524529
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
@@ -334,6 +334,11 @@ QTN2QT(QTNode *in)
334334
QTN2QTStatestate;
335335

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

339344
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
@@ -444,20 +447,12 @@ txid_snapshot_recv(PG_FUNCTION_ARGS)
444447
txidlast=0;
445448
intnxip;
446449
inti;
447-
intavail;
448-
intexpect;
449450
txidxmin,
450451
xmax;
451452

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

463458
xmin=pq_getmsgint64(buf);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp