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

Commit6faf795

Browse files
committed
Fix a passel of ancient bugs in to_char(), including two distinct buffer
overruns (neither of which seem likely to be exploitable as security holes,fortunately, since the provoker can't control the data written). One ofthese is due to choosing to stomp on the output of a called function, whichis bad news in any case; make it treat the called functions' results asread-only. Avoid some unnecessary palloc/pfree traffic too; it's notreally helpful to free small temporary objects, and again this is presumingmore than it ought to about the nature of the results of called functions.Per report from Patrick Welche and additional code-reading by Imad.
1 parent700eabb commit6faf795

File tree

1 file changed

+56
-94
lines changed

1 file changed

+56
-94
lines changed

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

Lines changed: 56 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.129 2007/02/27 23:48:08 tgl Exp $
4+
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.130 2007/06/29 01:51:35 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
@@ -74,6 +74,7 @@
7474
#include<unistd.h>
7575
#include<math.h>
7676
#include<float.h>
77+
#include<limits.h>
7778
#include<locale.h>
7879

7980
#include"utils/builtins.h"
@@ -112,8 +113,8 @@
112113
* More is in float.c
113114
* ----------
114115
*/
115-
#defineMAXFLOATWIDTH64
116-
#defineMAXDOUBLEWIDTH128
116+
#defineMAXFLOATWIDTH60
117+
#defineMAXDOUBLEWIDTH500
117118

118119

119120
/* ----------
@@ -958,13 +959,12 @@ static char *localize_month(int index);
958959
staticchar*localize_day_full(intindex);
959960
staticchar*localize_day(intindex);
960961

961-
/*
962-
* External (defined in oracle_compat.c
963-
*/
964962
#if defined(HAVE_WCSTOMBS)&& defined(HAVE_TOWLOWER)
965963
#defineUSE_WIDE_UPPER_LOWER
964+
/* externs are in oracle_compat.c */
966965
externchar*wstring_upper(char*str);
967966
externchar*wstring_lower(char*str);
967+
968968
staticchar*localized_str_toupper(char*buff);
969969
staticchar*localized_str_tolower(char*buff);
970970
#else
@@ -1510,7 +1510,7 @@ str_numth(char *dest, char *num, int type)
15101510
}
15111511

15121512
/* ----------
1513-
* Convert string to upper-string. Input string is modified in place.
1513+
* Convert string to upper case. Input string is modified in place.
15141514
* ----------
15151515
*/
15161516
staticchar*
@@ -1531,7 +1531,7 @@ str_toupper(char *buff)
15311531
}
15321532

15331533
/* ----------
1534-
* Convert string to lower-string. Input string is modified in place.
1534+
* Convert string to lower case. Input string is modified in place.
15351535
* ----------
15361536
*/
15371537
staticchar*
@@ -1553,7 +1553,8 @@ str_tolower(char *buff)
15531553

15541554
#ifdefUSE_WIDE_UPPER_LOWER
15551555
/* ----------
1556-
* Convert localized string to upper string. Input string is modified in place.
1556+
* Convert localized string to upper case.
1557+
* Input string may be modified in place ... or we might make a copy.
15571558
* ----------
15581559
*/
15591560
staticchar*
@@ -1579,7 +1580,8 @@ localized_str_toupper(char *buff)
15791580
}
15801581

15811582
/* ----------
1582-
* Convert localized string to upper string. Input string is modified in place.
1583+
* Convert localized string to lower case.
1584+
* Input string may be modified in place ... or we might make a copy.
15831585
* ----------
15841586
*/
15851587
staticchar*
@@ -2107,19 +2109,16 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
21072109
INVALID_FOR_INTERVAL;
21082110
if (is_to_char&&tmtcTzn(tmtc))
21092111
{
2110-
intsiz=strlen(tmtcTzn(tmtc));
2111-
21122112
if (arg==DCH_TZ)
21132113
strcpy(inout,tmtcTzn(tmtc));
21142114
else
21152115
{
2116-
char*p=palloc(siz);
2116+
char*p=pstrdup(tmtcTzn(tmtc));
21172117

2118-
strcpy(p,tmtcTzn(tmtc));
21192118
strcpy(inout,str_tolower(p));
21202119
pfree(p);
21212120
}
2122-
returnsiz;
2121+
returnstrlen(inout);
21232122
}
21242123
elseif (!is_to_char)
21252124
ereport(ERROR,
@@ -3624,7 +3623,7 @@ static char *
36243623
fill_str(char*str,intc,intmax)
36253624
{
36263625
memset(str,c,max);
3627-
*(str+max+1)='\0';
3626+
*(str+max)='\0';
36283627
returnstr;
36293628
}
36303629

@@ -4798,10 +4797,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
47984797
#defineNUM_TOCHAR_prepare \
47994798
do { \
48004799
len = VARSIZE(fmt) - VARHDRSZ;\
4801-
if (len <= 0)\
4800+
if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)\
48024801
return DirectFunctionCall1(textin, CStringGetDatum(""));\
4803-
result= (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
4804-
memset(result, 0, (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ ); \
4802+
result= (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);\
48054803
format= NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);\
48064804
} while (0)
48074805

@@ -4811,30 +4809,19 @@ do { \
48114809
*/
48124810
#defineNUM_TOCHAR_finish \
48134811
do { \
4814-
NUM_processor(format, &Num, VARDATA(result),\
4815-
numstr, plen, sign, true);\
4816-
pfree(orgnum);\
4812+
NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true);\
48174813
\
4818-
if (shouldFree)\
4819-
pfree(format);\
4814+
if (shouldFree)\
4815+
pfree(format);\
48204816
\
4821-
/*
4822-
* for result is allocated max memory, which current format-picture\
4823-
* needs, now it must be re-allocate to result real size\
4817+
/*\
4818+
* Convert null-terminated representation of result to standard text. \
4819+
* The result is usually much bigger than it needs to be, but there \
4820+
* seems little point in realloc'ing it smaller. \
48244821
*/\
4825-
if (!(len=strlen(VARDATA(result))))\
4826-
{\
4827-
pfree(result);\
4828-
PG_RETURN_NULL();\
4829-
}\
4830-
\
4831-
result_tmp=result;\
4832-
result= (text*)palloc(len+VARHDRSZ);\
4833-
\
4834-
memcpy(VARDATA(result),VARDATA(result_tmp),len);\
4835-
SET_VARSIZE(result,len+VARHDRSZ);\
4836-
pfree(result_tmp);\
4837-
}while(0)
4822+
len=strlen(VARDATA(result));\
4823+
SET_VARSIZE(result,len+VARHDRSZ); \
4824+
}while (0)
48384825

48394826
/* -------------------
48404827
* NUMERIC to_number() (convert string to numeric)
@@ -4856,7 +4843,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
48564843

48574844
len=VARSIZE(fmt)-VARHDRSZ;
48584845

4859-
if (len <=0)
4846+
if (len <=0||len >=INT_MAX/NUM_MAX_ITEM_SIZ)
48604847
PG_RETURN_NULL();
48614848

48624849
format=NUM_cache(len,&Num,VARDATA(fmt),&shouldFree);
@@ -4891,8 +4878,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
48914878
text*fmt=PG_GETARG_TEXT_P(1);
48924879
NUMDescNum;
48934880
FormatNode*format;
4894-
text*result,
4895-
*result_tmp;
4881+
text*result;
48964882
boolshouldFree;
48974883
intlen=0,
48984884
plen=0,
@@ -4915,7 +4901,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
49154901
numstr=orgnum=
49164902
int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
49174903
NumericGetDatum(x))));
4918-
pfree(x);
49194904
}
49204905
else
49214906
{
@@ -4934,9 +4919,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
49344919
val=DatumGetNumeric(DirectFunctionCall2(numeric_mul,
49354920
NumericGetDatum(value),
49364921
NumericGetDatum(x)));
4937-
pfree(x);
4938-
pfree(a);
4939-
pfree(b);
49404922
Num.pre+=Num.multi;
49414923
}
49424924

@@ -4945,10 +4927,9 @@ numeric_to_char(PG_FUNCTION_ARGS)
49454927
Int32GetDatum(Num.post)));
49464928
orgnum=DatumGetCString(DirectFunctionCall1(numeric_out,
49474929
NumericGetDatum(x)));
4948-
pfree(x);
49494930

49504931
if (*orgnum=='-')
4951-
{/* < 0 */
4932+
{
49524933
sign='-';
49534934
numstr=orgnum+1;
49544935
}
@@ -4966,13 +4947,10 @@ numeric_to_char(PG_FUNCTION_ARGS)
49664947
plen=Num.pre-len;
49674948
elseif (len>Num.pre)
49684949
{
4969-
fill_str(numstr,'#',Num.pre);
4950+
numstr= (char*)palloc(Num.pre+Num.post+2);
4951+
fill_str(numstr,'#',Num.pre+Num.post+1);
49704952
*(numstr+Num.pre)='.';
4971-
fill_str(numstr+1+Num.pre,'#',Num.post);
49724953
}
4973-
4974-
if (IS_MULTI(&Num))
4975-
pfree(val);
49764954
}
49774955

49784956
NUM_TOCHAR_finish;
@@ -4990,8 +4968,7 @@ int4_to_char(PG_FUNCTION_ARGS)
49904968
text*fmt=PG_GETARG_TEXT_P(1);
49914969
NUMDescNum;
49924970
FormatNode*format;
4993-
text*result,
4994-
*result_tmp;
4971+
text*result;
49954972
boolshouldFree;
49964973
intlen=0,
49974974
plen=0,
@@ -5019,40 +4996,34 @@ int4_to_char(PG_FUNCTION_ARGS)
50194996
orgnum=DatumGetCString(DirectFunctionCall1(int4out,
50204997
Int32GetDatum(value)));
50214998
}
5022-
len=strlen(orgnum);
50234999

50245000
if (*orgnum=='-')
5025-
{/* < 0 */
5001+
{
50265002
sign='-';
5027-
--len;
5003+
orgnum++;
50285004
}
50295005
else
50305006
sign='+';
5007+
len=strlen(orgnum);
50315008

50325009
if (Num.post)
50335010
{
5034-
inti;
5035-
50365011
numstr= (char*)palloc(len+Num.post+2);
5037-
strcpy(numstr,orgnum+ (*orgnum=='-' ?1 :0));
5012+
strcpy(numstr,orgnum);
50385013
*(numstr+len)='.';
5039-
5040-
for (i=len+1;i <=len+Num.post;i++)
5041-
*(numstr+i)='0';
5014+
memset(numstr+len+1,'0',Num.post);
50425015
*(numstr+len+Num.post+1)='\0';
5043-
pfree(orgnum);
5044-
orgnum=numstr;
50455016
}
50465017
else
5047-
numstr=orgnum+ (*orgnum=='-' ?1 :0);
5018+
numstr=orgnum;
50485019

50495020
if (Num.pre>len)
50505021
plen=Num.pre-len;
50515022
elseif (len>Num.pre)
50525023
{
5053-
fill_str(numstr,'#',Num.pre);
5024+
numstr= (char*)palloc(Num.pre+Num.post+2);
5025+
fill_str(numstr,'#',Num.pre+Num.post+1);
50545026
*(numstr+Num.pre)='.';
5055-
fill_str(numstr+1+Num.pre,'#',Num.post);
50565027
}
50575028
}
50585029

@@ -5071,8 +5042,7 @@ int8_to_char(PG_FUNCTION_ARGS)
50715042
text*fmt=PG_GETARG_TEXT_P(1);
50725043
NUMDescNum;
50735044
FormatNode*format;
5074-
text*result,
5075-
*result_tmp;
5045+
text*result;
50765046
boolshouldFree;
50775047
intlen=0,
50785048
plen=0,
@@ -5106,40 +5076,34 @@ int8_to_char(PG_FUNCTION_ARGS)
51065076

51075077
orgnum=DatumGetCString(DirectFunctionCall1(int8out,
51085078
Int64GetDatum(value)));
5109-
len=strlen(orgnum);
51105079

51115080
if (*orgnum=='-')
5112-
{/* < 0 */
5081+
{
51135082
sign='-';
5114-
--len;
5083+
orgnum++;
51155084
}
51165085
else
51175086
sign='+';
5087+
len=strlen(orgnum);
51185088

51195089
if (Num.post)
51205090
{
5121-
inti;
5122-
51235091
numstr= (char*)palloc(len+Num.post+2);
5124-
strcpy(numstr,orgnum+ (*orgnum=='-' ?1 :0));
5092+
strcpy(numstr,orgnum);
51255093
*(numstr+len)='.';
5126-
5127-
for (i=len+1;i <=len+Num.post;i++)
5128-
*(numstr+i)='0';
5094+
memset(numstr+len+1,'0',Num.post);
51295095
*(numstr+len+Num.post+1)='\0';
5130-
pfree(orgnum);
5131-
orgnum=numstr;
51325096
}
51335097
else
5134-
numstr=orgnum+ (*orgnum=='-' ?1 :0);
5098+
numstr=orgnum;
51355099

51365100
if (Num.pre>len)
51375101
plen=Num.pre-len;
51385102
elseif (len>Num.pre)
51395103
{
5140-
fill_str(numstr,'#',Num.pre);
5104+
numstr= (char*)palloc(Num.pre+Num.post+2);
5105+
fill_str(numstr,'#',Num.pre+Num.post+1);
51415106
*(numstr+Num.pre)='.';
5142-
fill_str(numstr+1+Num.pre,'#',Num.post);
51435107
}
51445108
}
51455109

@@ -5158,8 +5122,7 @@ float4_to_char(PG_FUNCTION_ARGS)
51585122
text*fmt=PG_GETARG_TEXT_P(1);
51595123
NUMDescNum;
51605124
FormatNode*format;
5161-
text*result,
5162-
*result_tmp;
5125+
text*result;
51635126
boolshouldFree;
51645127
intlen=0,
51655128
plen=0,
@@ -5214,9 +5177,9 @@ float4_to_char(PG_FUNCTION_ARGS)
52145177
plen=Num.pre-len;
52155178
elseif (len>Num.pre)
52165179
{
5217-
fill_str(numstr,'#',Num.pre);
5180+
numstr= (char*)palloc(Num.pre+Num.post+2);
5181+
fill_str(numstr,'#',Num.pre+Num.post+1);
52185182
*(numstr+Num.pre)='.';
5219-
fill_str(numstr+1+Num.pre,'#',Num.post);
52205183
}
52215184
}
52225185

@@ -5235,8 +5198,7 @@ float8_to_char(PG_FUNCTION_ARGS)
52355198
text*fmt=PG_GETARG_TEXT_P(1);
52365199
NUMDescNum;
52375200
FormatNode*format;
5238-
text*result,
5239-
*result_tmp;
5201+
text*result;
52405202
boolshouldFree;
52415203
intlen=0,
52425204
plen=0,
@@ -5289,9 +5251,9 @@ float8_to_char(PG_FUNCTION_ARGS)
52895251
plen=Num.pre-len;
52905252
elseif (len>Num.pre)
52915253
{
5292-
fill_str(numstr,'#',Num.pre);
5254+
numstr= (char*)palloc(Num.pre+Num.post+2);
5255+
fill_str(numstr,'#',Num.pre+Num.post+1);
52935256
*(numstr+Num.pre)='.';
5294-
fill_str(numstr+1+Num.pre,'#',Num.post);
52955257
}
52965258
}
52975259

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp