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

Commit504af1f

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 parent4edbb26 commit504af1f

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
@@ -964,7 +964,6 @@ static const char *get_th(char *num, int type);
964964
staticchar*str_numth(char*dest,char*num,inttype);
965965
staticintadjust_partial_year_to_2020(intyear);
966966
staticintstrspace_len(char*str);
967-
staticintstrdigits_len(char*str);
968967
staticvoidfrom_char_set_mode(TmFromChar*tmfc,constFromCharDateModemode);
969968
staticvoidfrom_char_set_int(int*dest,constintvalue,constFormatNode*node);
970969
staticintfrom_char_parse_int_len(int*dest,char**src,constintlen,FormatNode*node);
@@ -1976,9 +1975,19 @@ asc_toupper_z(const char *buff)
19761975

19771976
/* ----------
19781977
* Skip TM / th in FROM_CHAR
1978+
*
1979+
* If S_THth is on, skip two chars, assuming there are two available
19791980
* ----------
19801981
*/
1981-
#defineSKIP_THth(_suf)(S_THth(_suf) ? 2 : 0)
1982+
#defineSKIP_THth(ptr,_suf) \
1983+
do { \
1984+
if (S_THth(_suf)) \
1985+
{ \
1986+
if (*(ptr)) (ptr)++; \
1987+
if (*(ptr)) (ptr)++; \
1988+
} \
1989+
} while (0)
1990+
19821991

19831992
#ifdefDEBUG_TO_FROM_CHAR
19841993
/* -----------
@@ -2086,23 +2095,6 @@ strspace_len(char *str)
20862095
returnlen;
20872096
}
20882097

2089-
staticint
2090-
strdigits_len(char*str)
2091-
{
2092-
char*p=str;
2093-
intlen;
2094-
2095-
len=strspace_len(str);
2096-
p+=len;
2097-
2098-
while (*p&&isdigit((unsignedchar)*p)&&len <=DCH_MAX_ITEM_SIZ)
2099-
{
2100-
len++;
2101-
p++;
2102-
}
2103-
returnlen;
2104-
}
2105-
21062098
/*
21072099
* Set the date mode of a from-char conversion.
21082100
*
@@ -3000,19 +2992,19 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30002992
caseDCH_HH12:
30012993
from_char_parse_int_len(&out->hh,&s,2,n);
30022994
out->clock=CLOCK_12_HOUR;
3003-
s+=SKIP_THth(n->suffix);
2995+
SKIP_THth(s,n->suffix);
30042996
break;
30052997
caseDCH_HH24:
30062998
from_char_parse_int_len(&out->hh,&s,2,n);
3007-
s+=SKIP_THth(n->suffix);
2999+
SKIP_THth(s,n->suffix);
30083000
break;
30093001
caseDCH_MI:
30103002
from_char_parse_int(&out->mi,&s,n);
3011-
s+=SKIP_THth(n->suffix);
3003+
SKIP_THth(s,n->suffix);
30123004
break;
30133005
caseDCH_SS:
30143006
from_char_parse_int(&out->ss,&s,n);
3015-
s+=SKIP_THth(n->suffix);
3007+
SKIP_THth(s,n->suffix);
30163008
break;
30173009
caseDCH_MS:/* millisecond */
30183010
len=from_char_parse_int_len(&out->ms,&s,3,n);
@@ -3023,7 +3015,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30233015
out->ms *=len==1 ?100 :
30243016
len==2 ?10 :1;
30253017

3026-
s+=SKIP_THth(n->suffix);
3018+
SKIP_THth(s,n->suffix);
30273019
break;
30283020
caseDCH_US:/* microsecond */
30293021
len=from_char_parse_int_len(&out->us,&s,6,n);
@@ -3034,11 +3026,11 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30343026
len==4 ?100 :
30353027
len==5 ?10 :1;
30363028

3037-
s+=SKIP_THth(n->suffix);
3029+
SKIP_THth(s,n->suffix);
30383030
break;
30393031
caseDCH_SSSS:
30403032
from_char_parse_int(&out->ssss,&s,n);
3041-
s+=SKIP_THth(n->suffix);
3033+
SKIP_THth(s,n->suffix);
30423034
break;
30433035
caseDCH_tz:
30443036
caseDCH_TZ:
@@ -3078,7 +3070,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30783070
break;
30793071
caseDCH_MM:
30803072
from_char_parse_int(&out->mm,&s,n);
3081-
s+=SKIP_THth(n->suffix);
3073+
SKIP_THth(s,n->suffix);
30823074
break;
30833075
caseDCH_DAY:
30843076
caseDCH_Day:
@@ -3098,31 +3090,31 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30983090
break;
30993091
caseDCH_DDD:
31003092
from_char_parse_int(&out->ddd,&s,n);
3101-
s+=SKIP_THth(n->suffix);
3093+
SKIP_THth(s,n->suffix);
31023094
break;
31033095
caseDCH_IDDD:
31043096
from_char_parse_int_len(&out->ddd,&s,3,n);
3105-
s+=SKIP_THth(n->suffix);
3097+
SKIP_THth(s,n->suffix);
31063098
break;
31073099
caseDCH_DD:
31083100
from_char_parse_int(&out->dd,&s,n);
3109-
s+=SKIP_THth(n->suffix);
3101+
SKIP_THth(s,n->suffix);
31103102
break;
31113103
caseDCH_D:
31123104
from_char_parse_int(&out->d,&s,n);
3113-
s+=SKIP_THth(n->suffix);
3105+
SKIP_THth(s,n->suffix);
31143106
break;
31153107
caseDCH_ID:
31163108
from_char_parse_int_len(&out->d,&s,1,n);
31173109
/* Shift numbering to match Gregorian where Sunday = 1 */
31183110
if (++out->d>7)
31193111
out->d=1;
3120-
s+=SKIP_THth(n->suffix);
3112+
SKIP_THth(s,n->suffix);
31213113
break;
31223114
caseDCH_WW:
31233115
caseDCH_IW:
31243116
from_char_parse_int(&out->ww,&s,n);
3125-
s+=SKIP_THth(n->suffix);
3117+
SKIP_THth(s,n->suffix);
31263118
break;
31273119
caseDCH_Q:
31283120

@@ -3137,55 +3129,57 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
31373129
* isn't stored anywhere in 'out'.
31383130
*/
31393131
from_char_parse_int((int*)NULL,&s,n);
3140-
s+=SKIP_THth(n->suffix);
3132+
SKIP_THth(s,n->suffix);
31413133
break;
31423134
caseDCH_CC:
31433135
from_char_parse_int(&out->cc,&s,n);
3144-
s+=SKIP_THth(n->suffix);
3136+
SKIP_THth(s,n->suffix);
31453137
break;
31463138
caseDCH_Y_YYY:
31473139
{
31483140
intmatched,
31493141
years,
3150-
millenia;
3142+
millenia,
3143+
nch;
31513144

3152-
matched=sscanf(s,"%d,%03d",&millenia,&years);
3153-
if (matched!=2)
3145+
matched=sscanf(s,"%d,%03d%n",&millenia,&years,&nch);
3146+
if (matched<2)
31543147
ereport(ERROR,
31553148
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
31563149
errmsg("invalid input string for \"Y,YYY\"")));
31573150
years+= (millenia*1000);
31583151
from_char_set_int(&out->year,years,n);
31593152
out->yysz=4;
3160-
s+=strdigits_len(s)+4+SKIP_THth(n->suffix);
3153+
s+=nch;
3154+
SKIP_THth(s,n->suffix);
31613155
}
31623156
break;
31633157
caseDCH_YYYY:
31643158
caseDCH_IYYY:
31653159
from_char_parse_int(&out->year,&s,n);
31663160
out->yysz=4;
3167-
s+=SKIP_THth(n->suffix);
3161+
SKIP_THth(s,n->suffix);
31683162
break;
31693163
caseDCH_YYY:
31703164
caseDCH_IYY:
31713165
if (from_char_parse_int(&out->year,&s,n)<4)
31723166
out->year=adjust_partial_year_to_2020(out->year);
31733167
out->yysz=3;
3174-
s+=SKIP_THth(n->suffix);
3168+
SKIP_THth(s,n->suffix);
31753169
break;
31763170
caseDCH_YY:
31773171
caseDCH_IY:
31783172
if (from_char_parse_int(&out->year,&s,n)<4)
31793173
out->year=adjust_partial_year_to_2020(out->year);
31803174
out->yysz=2;
3181-
s+=SKIP_THth(n->suffix);
3175+
SKIP_THth(s,n->suffix);
31823176
break;
31833177
caseDCH_Y:
31843178
caseDCH_I:
31853179
if (from_char_parse_int(&out->year,&s,n)<4)
31863180
out->year=adjust_partial_year_to_2020(out->year);
31873181
out->yysz=1;
3188-
s+=SKIP_THth(n->suffix);
3182+
SKIP_THth(s,n->suffix);
31893183
break;
31903184
caseDCH_RM:
31913185
from_char_seq_search(&value,&s,rm_months_upper,
@@ -3199,11 +3193,11 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
31993193
break;
32003194
caseDCH_W:
32013195
from_char_parse_int(&out->w,&s,n);
3202-
s+=SKIP_THth(n->suffix);
3196+
SKIP_THth(s,n->suffix);
32033197
break;
32043198
caseDCH_J:
32053199
from_char_parse_int(&out->j,&s,n);
3206-
s+=SKIP_THth(n->suffix);
3200+
SKIP_THth(s,n->suffix);
32073201
break;
32083202
}
32093203
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp