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

Commit462456d

Browse files
committed
Fix possible read past end of string in to_timestamp().
to_timestamp() handles the TH/th format codes by advancing over two inputcharacters, whatever those are. It failed to notice whether there weretwo characters available to be skipped, making it possible to advancethe pointer past the end of the input string and keep on parsing.A similar risk existed in the handling of "Y,YYY" format: it would advanceover three characters after the "," whether or not three characters wereavailable.In principle this might be exploitable to disclose contents of servermemory. But the security team concluded that it would be very hard to usethat way, because the parsing loop would stop upon hitting any zero byte,and TH/th format codes can't be consecutive --- they have to follow someother format code, which would have to match whatever data is there.So it seems impractical to examine memory very much beyond the end of theinput string via this bug; and the input string will always be in localmemory not in disk buffers, making it unlikely that anything veryinteresting is close to it in a predictable way. So this doesn't quiterise to the level of needing a CVE.Thanks to Wolf Roediger for reporting this bug.
1 parentd30c67a commit462456d

File tree

1 file changed

+39
-45
lines changed

1 file changed

+39
-45
lines changed

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

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,6 @@ static char *get_th(char *num, int type);
969969
staticchar*str_numth(char*dest,char*num,inttype);
970970
staticintadjust_partial_year_to_2020(intyear);
971971
staticintstrspace_len(char*str);
972-
staticintstrdigits_len(char*str);
973972
staticvoidfrom_char_set_mode(TmFromChar*tmfc,constFromCharDateModemode);
974973
staticvoidfrom_char_set_int(int*dest,constintvalue,constFormatNode*node);
975974
staticintfrom_char_parse_int_len(int*dest,char**src,constintlen,FormatNode*node);
@@ -1981,9 +1980,19 @@ asc_toupper_z(const char *buff)
19811980

19821981
/* ----------
19831982
* Skip TM / th in FROM_CHAR
1983+
*
1984+
* If S_THth is on, skip two chars, assuming there are two available
19841985
* ----------
19851986
*/
1986-
#defineSKIP_THth(_suf)(S_THth(_suf) ? 2 : 0)
1987+
#defineSKIP_THth(ptr,_suf) \
1988+
do { \
1989+
if (S_THth(_suf)) \
1990+
{ \
1991+
if (*(ptr)) (ptr)++; \
1992+
if (*(ptr)) (ptr)++; \
1993+
} \
1994+
} while (0)
1995+
19871996

19881997
#ifdefDEBUG_TO_FROM_CHAR
19891998
/* -----------
@@ -2091,23 +2100,6 @@ strspace_len(char *str)
20912100
returnlen;
20922101
}
20932102

2094-
staticint
2095-
strdigits_len(char*str)
2096-
{
2097-
char*p=str;
2098-
intlen;
2099-
2100-
len=strspace_len(str);
2101-
p+=len;
2102-
2103-
while (*p&&isdigit((unsignedchar)*p)&&len <=DCH_MAX_ITEM_SIZ)
2104-
{
2105-
len++;
2106-
p++;
2107-
}
2108-
returnlen;
2109-
}
2110-
21112103
/*
21122104
* Set the date mode of a from-char conversion.
21132105
*
@@ -2985,19 +2977,19 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
29852977
caseDCH_HH12:
29862978
from_char_parse_int_len(&out->hh,&s,2,n);
29872979
out->clock=CLOCK_12_HOUR;
2988-
s+=SKIP_THth(n->suffix);
2980+
SKIP_THth(s,n->suffix);
29892981
break;
29902982
caseDCH_HH24:
29912983
from_char_parse_int_len(&out->hh,&s,2,n);
2992-
s+=SKIP_THth(n->suffix);
2984+
SKIP_THth(s,n->suffix);
29932985
break;
29942986
caseDCH_MI:
29952987
from_char_parse_int(&out->mi,&s,n);
2996-
s+=SKIP_THth(n->suffix);
2988+
SKIP_THth(s,n->suffix);
29972989
break;
29982990
caseDCH_SS:
29992991
from_char_parse_int(&out->ss,&s,n);
3000-
s+=SKIP_THth(n->suffix);
2992+
SKIP_THth(s,n->suffix);
30012993
break;
30022994
caseDCH_MS:/* millisecond */
30032995
len=from_char_parse_int_len(&out->ms,&s,3,n);
@@ -3008,7 +3000,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30083000
out->ms *=len==1 ?100 :
30093001
len==2 ?10 :1;
30103002

3011-
s+=SKIP_THth(n->suffix);
3003+
SKIP_THth(s,n->suffix);
30123004
break;
30133005
caseDCH_US:/* microsecond */
30143006
len=from_char_parse_int_len(&out->us,&s,6,n);
@@ -3019,11 +3011,11 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30193011
len==4 ?100 :
30203012
len==5 ?10 :1;
30213013

3022-
s+=SKIP_THth(n->suffix);
3014+
SKIP_THth(s,n->suffix);
30233015
break;
30243016
caseDCH_SSSS:
30253017
from_char_parse_int(&out->ssss,&s,n);
3026-
s+=SKIP_THth(n->suffix);
3018+
SKIP_THth(s,n->suffix);
30273019
break;
30283020
caseDCH_tz:
30293021
caseDCH_TZ:
@@ -3062,7 +3054,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30623054
break;
30633055
caseDCH_MM:
30643056
from_char_parse_int(&out->mm,&s,n);
3065-
s+=SKIP_THth(n->suffix);
3057+
SKIP_THth(s,n->suffix);
30663058
break;
30673059
caseDCH_DAY:
30683060
caseDCH_Day:
@@ -3082,31 +3074,31 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30823074
break;
30833075
caseDCH_DDD:
30843076
from_char_parse_int(&out->ddd,&s,n);
3085-
s+=SKIP_THth(n->suffix);
3077+
SKIP_THth(s,n->suffix);
30863078
break;
30873079
caseDCH_IDDD:
30883080
from_char_parse_int_len(&out->ddd,&s,3,n);
3089-
s+=SKIP_THth(n->suffix);
3081+
SKIP_THth(s,n->suffix);
30903082
break;
30913083
caseDCH_DD:
30923084
from_char_parse_int(&out->dd,&s,n);
3093-
s+=SKIP_THth(n->suffix);
3085+
SKIP_THth(s,n->suffix);
30943086
break;
30953087
caseDCH_D:
30963088
from_char_parse_int(&out->d,&s,n);
3097-
s+=SKIP_THth(n->suffix);
3089+
SKIP_THth(s,n->suffix);
30983090
break;
30993091
caseDCH_ID:
31003092
from_char_parse_int_len(&out->d,&s,1,n);
31013093
/* Shift numbering to match Gregorian where Sunday = 1 */
31023094
if (++out->d>7)
31033095
out->d=1;
3104-
s+=SKIP_THth(n->suffix);
3096+
SKIP_THth(s,n->suffix);
31053097
break;
31063098
caseDCH_WW:
31073099
caseDCH_IW:
31083100
from_char_parse_int(&out->ww,&s,n);
3109-
s+=SKIP_THth(n->suffix);
3101+
SKIP_THth(s,n->suffix);
31103102
break;
31113103
caseDCH_Q:
31123104

@@ -3121,55 +3113,57 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
31213113
* isn't stored anywhere in 'out'.
31223114
*/
31233115
from_char_parse_int((int*)NULL,&s,n);
3124-
s+=SKIP_THth(n->suffix);
3116+
SKIP_THth(s,n->suffix);
31253117
break;
31263118
caseDCH_CC:
31273119
from_char_parse_int(&out->cc,&s,n);
3128-
s+=SKIP_THth(n->suffix);
3120+
SKIP_THth(s,n->suffix);
31293121
break;
31303122
caseDCH_Y_YYY:
31313123
{
31323124
intmatched,
31333125
years,
3134-
millenia;
3126+
millenia,
3127+
nch;
31353128

3136-
matched=sscanf(s,"%d,%03d",&millenia,&years);
3137-
if (matched!=2)
3129+
matched=sscanf(s,"%d,%03d%n",&millenia,&years,&nch);
3130+
if (matched<2)
31383131
ereport(ERROR,
31393132
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
31403133
errmsg("invalid input string for \"Y,YYY\"")));
31413134
years+= (millenia*1000);
31423135
from_char_set_int(&out->year,years,n);
31433136
out->yysz=4;
3144-
s+=strdigits_len(s)+4+SKIP_THth(n->suffix);
3137+
s+=nch;
3138+
SKIP_THth(s,n->suffix);
31453139
}
31463140
break;
31473141
caseDCH_YYYY:
31483142
caseDCH_IYYY:
31493143
from_char_parse_int(&out->year,&s,n);
31503144
out->yysz=4;
3151-
s+=SKIP_THth(n->suffix);
3145+
SKIP_THth(s,n->suffix);
31523146
break;
31533147
caseDCH_YYY:
31543148
caseDCH_IYY:
31553149
if (from_char_parse_int(&out->year,&s,n)<4)
31563150
out->year=adjust_partial_year_to_2020(out->year);
31573151
out->yysz=3;
3158-
s+=SKIP_THth(n->suffix);
3152+
SKIP_THth(s,n->suffix);
31593153
break;
31603154
caseDCH_YY:
31613155
caseDCH_IY:
31623156
if (from_char_parse_int(&out->year,&s,n)<4)
31633157
out->year=adjust_partial_year_to_2020(out->year);
31643158
out->yysz=2;
3165-
s+=SKIP_THth(n->suffix);
3159+
SKIP_THth(s,n->suffix);
31663160
break;
31673161
caseDCH_Y:
31683162
caseDCH_I:
31693163
if (from_char_parse_int(&out->year,&s,n)<4)
31703164
out->year=adjust_partial_year_to_2020(out->year);
31713165
out->yysz=1;
3172-
s+=SKIP_THth(n->suffix);
3166+
SKIP_THth(s,n->suffix);
31733167
break;
31743168
caseDCH_RM:
31753169
from_char_seq_search(&value,&s,rm_months_upper,
@@ -3183,11 +3177,11 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
31833177
break;
31843178
caseDCH_W:
31853179
from_char_parse_int(&out->w,&s,n);
3186-
s+=SKIP_THth(n->suffix);
3180+
SKIP_THth(s,n->suffix);
31873181
break;
31883182
caseDCH_J:
31893183
from_char_parse_int(&out->j,&s,n);
3190-
s+=SKIP_THth(n->suffix);
3184+
SKIP_THth(s,n->suffix);
31913185
break;
31923186
}
31933187
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp