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

Commite5d64fd

Browse files
committed
Tighten parsing of datetime input.
ParseFraction only expects to deal with fields that contain a decimalpoint and digit(s). However it's possible in some edge cases for itto be passed input that doesn't look like that. In particular theinput could look like a valid floating-point number, such as ".123e6".strtod() will happily eat that, possibly producing a result that isnot within the expected range 0..1, which can result in integeroverflow in the callers. That doesn't have any security consequences,but it's still not very desirable. Fix by checking that the inputhas the expected form.Similarly, DecodeNumberField only expects to deal with fields thatcontain a decimal point and digit(s), but it's sometimes abused toparse strings that might not look like that. This could result infailure to reject bogus input, yielding silly results. Again, fixby rejecting input that doesn't look as-expected. That decisionalso means that we can affirmatively answer the very old commentquestioning whether we couldn't save some duplicative code byusing ParseFractionalSecond here.While these changes should only reject input that nobody wouldconsider valid, it still doesn't seem like a change to make instable branches. Apply to HEAD only.Reported-by: Evgeniy Gorbanev <gorbanev.es@gmail.com>Author: Tom Lane <tgl@sss.pgh.pa.us>Discussion:https://postgr.es/m/1328335.1748371099@sss.pgh.pa.us
1 parentbe86ca1 commite5d64fd

File tree

3 files changed

+38
-19
lines changed

3 files changed

+38
-19
lines changed

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

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -702,9 +702,18 @@ ParseFraction(char *cp, double *frac)
702702
}
703703
else
704704
{
705+
/*
706+
* On the other hand, let's reject anything that's not digits after
707+
* the ".". strtod is happy with input like ".123e9", but that'd
708+
* break callers' expectation that the result is in 0..1. (It's quite
709+
* difficult to get here with such input, but not impossible.)
710+
*/
711+
if (strspn(cp+1,"0123456789")!=strlen(cp+1))
712+
returnDTERR_BAD_FORMAT;
713+
705714
errno=0;
706715
*frac=strtod(cp,&cp);
707-
/* check for parse failure */
716+
/* check for parse failure(probably redundant given prior check)*/
708717
if (*cp!='\0'||errno!=0)
709718
returnDTERR_BAD_FORMAT;
710719
}
@@ -2958,31 +2967,28 @@ DecodeNumberField(int len, char *str, int fmask,
29582967
{
29592968
char*cp;
29602969

2970+
/*
2971+
* This function was originally meant to cope only with DTK_NUMBER fields,
2972+
* but we now sometimes abuse it to parse (parts of) DTK_DATE fields,
2973+
* which can contain letters and other punctuation. Reject if it's not a
2974+
* valid DTK_NUMBER, that is digits and decimal point(s). (ParseFraction
2975+
* will reject if there's more than one decimal point.)
2976+
*/
2977+
if (strspn(str,"0123456789.")!=len)
2978+
returnDTERR_BAD_FORMAT;
2979+
29612980
/*
29622981
* Have a decimal point? Then this is a date or something with a seconds
29632982
* field...
29642983
*/
29652984
if ((cp=strchr(str,'.'))!=NULL)
29662985
{
2967-
/*
2968-
* Can we use ParseFractionalSecond here? Not clear whether trailing
2969-
* junk should be rejected ...
2970-
*/
2971-
if (cp[1]=='\0')
2972-
{
2973-
/* avoid assuming that strtod will accept "." */
2974-
*fsec=0;
2975-
}
2976-
else
2977-
{
2978-
doublefrac;
2986+
intdterr;
29792987

2980-
errno=0;
2981-
frac=strtod(cp,NULL);
2982-
if (errno!=0)
2983-
returnDTERR_BAD_FORMAT;
2984-
*fsec=rint(frac*1000000);
2985-
}
2988+
/* Convert the fraction and store at *fsec */
2989+
dterr=ParseFractionalSecond(cp,fsec);
2990+
if (dterr)
2991+
returndterr;
29862992
/* Now truncate off the fraction for further processing */
29872993
*cp='\0';
29882994
len=strlen(str);

‎src/test/regress/expected/horology.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,15 @@ SELECT timestamp with time zone 'Y2001M12D27H04MM05S06.789-08';
467467
ERROR: invalid input syntax for type timestamp with time zone: "Y2001M12D27H04MM05S06.789-08"
468468
LINE 1: SELECT timestamp with time zone 'Y2001M12D27H04MM05S06.789-0...
469469
^
470+
-- More examples we used to accept and should not
471+
SELECT timestamp with time zone 'J2452271 T X03456-08';
472+
ERROR: invalid input syntax for type timestamp with time zone: "J2452271 T X03456-08"
473+
LINE 1: SELECT timestamp with time zone 'J2452271 T X03456-08';
474+
^
475+
SELECT timestamp with time zone 'J2452271 T X03456.001e6-08';
476+
ERROR: invalid input syntax for type timestamp with time zone: "J2452271 T X03456.001e6-08"
477+
LINE 1: SELECT timestamp with time zone 'J2452271 T X03456.001e6-08'...
478+
^
470479
-- conflicting fields should throw errors
471480
SELECT date '1995-08-06 epoch';
472481
ERROR: invalid input syntax for type date: "1995-08-06 epoch"

‎src/test/regress/sql/horology.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ SELECT date 'J J 1520447';
102102
SELECTtimestamp with time zone'Y2001M12D27H04M05S06.789+08';
103103
SELECTtimestamp with time zone'Y2001M12D27H04MM05S06.789-08';
104104

105+
-- More examples we used to accept and should not
106+
SELECTtimestamp with time zone'J2452271 T X03456-08';
107+
SELECTtimestamp with time zone'J2452271 T X03456.001e6-08';
108+
105109
-- conflicting fields should throw errors
106110
SELECTdate'1995-08-06 epoch';
107111
SELECTdate'1995-08-06 infinity';

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp