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

Commit146604e

Browse files
committed
Add checks for interval overflow/underflow
New checks include input, month/day/time internal adjustments, addition,subtraction, multiplication, and negation. Also adjust docs tocorrectly specify interval size in bytes.Report from Rok Kralj
1 parent571addd commit146604e

File tree

4 files changed

+97
-7
lines changed

4 files changed

+97
-7
lines changed

‎doc/src/sgml/datatype.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1587,7 +1587,7 @@ SELECT E'\\xDEADBEEF';
15871587
</row>
15881588
<row>
15891589
<entry><type>interval [ <replaceable>fields</replaceable> ] [ (<replaceable>p</replaceable>) ]</type></entry>
1590-
<entry>12 bytes</entry>
1590+
<entry>16 bytes</entry>
15911591
<entry>time interval</entry>
15921592
<entry>-178000000 years</entry>
15931593
<entry>178000000 years</entry>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,9 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
29762976
type=DTK_MONTH;
29772977
if (*field[i]=='-')
29782978
val2=-val2;
2979+
if (((double)val*MONTHS_PER_YEAR+val2)>INT_MAX||
2980+
((double)val*MONTHS_PER_YEAR+val2)<INT_MIN)
2981+
returnDTERR_FIELD_OVERFLOW;
29792982
val=val*MONTHS_PER_YEAR+val2;
29802983
fval=0;
29812984
}

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

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@
4141
#error -ffast-math is known to break this code
4242
#endif
4343

44+
#defineSAMESIGN(a,b) (((a) < 0) == ((b) < 0))
45+
46+
#ifndefINT64_MAX
47+
#defineINT64_MAXINT64CONST(0x7FFFFFFFFFFFFFFF)
48+
#endif
49+
50+
#ifndefINT64_MIN
51+
#defineINT64_MIN(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
52+
#endif
4453

4554
/* Set at postmaster start */
4655
TimestampTzPgStartTime;
@@ -1694,7 +1703,11 @@ interval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec)
16941703
#ifdefHAVE_INT64_TIMESTAMP
16951704
tfrac=time /USECS_PER_HOUR;
16961705
time-=tfrac*USECS_PER_HOUR;
1697-
tm->tm_hour=tfrac;/* could overflow ... */
1706+
tm->tm_hour=tfrac;
1707+
if (!SAMESIGN(tm->tm_hour,tfrac))
1708+
ereport(ERROR,
1709+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1710+
errmsg("interval out of range")));
16981711
tfrac=time /USECS_PER_MINUTE;
16991712
time-=tfrac*USECS_PER_MINUTE;
17001713
tm->tm_min=tfrac;
@@ -1725,7 +1738,11 @@ interval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec)
17251738
int
17261739
tm2interval(structpg_tm*tm,fsec_tfsec,Interval*span)
17271740
{
1728-
span->month=tm->tm_year*MONTHS_PER_YEAR+tm->tm_mon;
1741+
doubletotal_months= (double)tm->tm_year*MONTHS_PER_YEAR+tm->tm_mon;
1742+
1743+
if (total_months>INT_MAX||total_months<INT_MIN)
1744+
return-1;
1745+
span->month=total_months;
17291746
span->day=tm->tm_mday;
17301747
#ifdefHAVE_INT64_TIMESTAMP
17311748
span->time= (((((tm->tm_hour*INT64CONST(60))+
@@ -2826,8 +2843,21 @@ interval_um(PG_FUNCTION_ARGS)
28262843
result= (Interval*)palloc(sizeof(Interval));
28272844

28282845
result->time=-interval->time;
2846+
/* overflow check copied from int4um */
2847+
if (interval->time!=0&&SAMESIGN(result->time,interval->time))
2848+
ereport(ERROR,
2849+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2850+
errmsg("interval out of range")));
28292851
result->day=-interval->day;
2852+
if (interval->day!=0&&SAMESIGN(result->day,interval->day))
2853+
ereport(ERROR,
2854+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2855+
errmsg("interval out of range")));
28302856
result->month=-interval->month;
2857+
if (interval->month!=0&&SAMESIGN(result->month,interval->month))
2858+
ereport(ERROR,
2859+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2860+
errmsg("interval out of range")));
28312861

28322862
PG_RETURN_INTERVAL_P(result);
28332863
}
@@ -2872,8 +2902,26 @@ interval_pl(PG_FUNCTION_ARGS)
28722902
result= (Interval*)palloc(sizeof(Interval));
28732903

28742904
result->month=span1->month+span2->month;
2905+
/* overflow check copied from int4pl */
2906+
if (SAMESIGN(span1->month,span2->month)&&
2907+
!SAMESIGN(result->month,span1->month))
2908+
ereport(ERROR,
2909+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2910+
errmsg("interval out of range")));
2911+
28752912
result->day=span1->day+span2->day;
2913+
if (SAMESIGN(span1->day,span2->day)&&
2914+
!SAMESIGN(result->day,span1->day))
2915+
ereport(ERROR,
2916+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2917+
errmsg("interval out of range")));
2918+
28762919
result->time=span1->time+span2->time;
2920+
if (SAMESIGN(span1->time,span2->time)&&
2921+
!SAMESIGN(result->time,span1->time))
2922+
ereport(ERROR,
2923+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2924+
errmsg("interval out of range")));
28772925

28782926
PG_RETURN_INTERVAL_P(result);
28792927
}
@@ -2888,8 +2936,27 @@ interval_mi(PG_FUNCTION_ARGS)
28882936
result= (Interval*)palloc(sizeof(Interval));
28892937

28902938
result->month=span1->month-span2->month;
2939+
/* overflow check copied from int4mi */
2940+
if (!SAMESIGN(span1->month,span2->month)&&
2941+
!SAMESIGN(result->month,span1->month))
2942+
ereport(ERROR,
2943+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2944+
errmsg("interval out of range")));
2945+
28912946
result->day=span1->day-span2->day;
2947+
if (!SAMESIGN(span1->day,span2->day)&&
2948+
!SAMESIGN(result->day,span1->day))
2949+
ereport(ERROR,
2950+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2951+
errmsg("interval out of range")));
2952+
28922953
result->time=span1->time-span2->time;
2954+
if (!SAMESIGN(span1->time,span2->time)&&
2955+
!SAMESIGN(result->time,span1->time))
2956+
ereport(ERROR,
2957+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2958+
errmsg("interval out of range")));
2959+
28932960

28942961
PG_RETURN_INTERVAL_P(result);
28952962
}
@@ -2906,15 +2973,27 @@ interval_mul(PG_FUNCTION_ARGS)
29062973
Interval*span=PG_GETARG_INTERVAL_P(0);
29072974
float8factor=PG_GETARG_FLOAT8(1);
29082975
doublemonth_remainder_days,
2909-
sec_remainder;
2976+
sec_remainder,
2977+
result_double;
29102978
int32orig_month=span->month,
29112979
orig_day=span->day;
29122980
Interval*result;
29132981

29142982
result= (Interval*)palloc(sizeof(Interval));
29152983

2916-
result->month= (int32) (span->month*factor);
2917-
result->day= (int32) (span->day*factor);
2984+
result_double=span->month*factor;
2985+
if (result_double>INT_MAX||result_double<INT_MIN)
2986+
ereport(ERROR,
2987+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2988+
errmsg("interval out of range")));
2989+
result->month= (int32)result_double;
2990+
2991+
result_double=span->day*factor;
2992+
if (result_double>INT_MAX||result_double<INT_MIN)
2993+
ereport(ERROR,
2994+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2995+
errmsg("interval out of range")));
2996+
result->day= (int32)result_double;
29182997

29192998
/*
29202999
* The above correctly handles the whole-number part of the month and day
@@ -2954,7 +3033,12 @@ interval_mul(PG_FUNCTION_ARGS)
29543033
/* cascade units down */
29553034
result->day+= (int32)month_remainder_days;
29563035
#ifdefHAVE_INT64_TIMESTAMP
2957-
result->time=rint(span->time*factor+sec_remainder*USECS_PER_SEC);
3036+
result_double=rint(span->time*factor+sec_remainder*USECS_PER_SEC);
3037+
if (result_double>INT64_MAX||result_double<INT64_MIN)
3038+
ereport(ERROR,
3039+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3040+
errmsg("interval out of range")));
3041+
result->time= (int64)result_double;
29583042
#else
29593043
result->time=span->time*factor+sec_remainder;
29603044
#endif

‎src/interfaces/ecpg/pgtypeslib/interval.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,9 @@ interval2tm(interval span, struct tm * tm, fsec_t *fsec)
10361036
staticint
10371037
tm2interval(structtm*tm,fsec_tfsec,interval*span)
10381038
{
1039+
if ((double)tm->tm_year*MONTHS_PER_YEAR+tm->tm_mon>INT_MAX||
1040+
(double)tm->tm_year*MONTHS_PER_YEAR+tm->tm_mon<INT_MIN)
1041+
return-1;
10391042
span->month=tm->tm_year*MONTHS_PER_YEAR+tm->tm_mon;
10401043
#ifdefHAVE_INT64_TIMESTAMP
10411044
span->time= (((((((tm->tm_mday*INT64CONST(24))+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp