@@ -3548,17 +3548,14 @@ interval_mul(PG_FUNCTION_ARGS)
3548
3548
* interval type has nothing equivalent to NaN.
3549
3549
*/
3550
3550
if (isnan (factor ))
3551
- ereport (ERROR ,
3552
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3553
- errmsg ("interval out of range" )));
3551
+ goto out_of_range ;
3554
3552
3555
3553
if (INTERVAL_NOT_FINITE (span ))
3556
3554
{
3557
3555
if (factor == 0.0 )
3558
- ereport (ERROR ,
3559
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3560
- errmsg ("interval out of range" )));
3561
- else if (factor < 0.0 )
3556
+ goto out_of_range ;
3557
+
3558
+ if (factor < 0.0 )
3562
3559
interval_um_internal (span , result );
3563
3560
else
3564
3561
memcpy (result , span , sizeof (Interval ));
@@ -3570,10 +3567,9 @@ interval_mul(PG_FUNCTION_ARGS)
3570
3567
int isign = interval_sign (span );
3571
3568
3572
3569
if (isign == 0 )
3573
- ereport (ERROR ,
3574
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3575
- errmsg ("interval out of range" )));
3576
- else if (factor * isign < 0 )
3570
+ goto out_of_range ;
3571
+
3572
+ if (factor * isign < 0 )
3577
3573
INTERVAL_NOBEGIN (result );
3578
3574
else
3579
3575
INTERVAL_NOEND (result );
@@ -3582,19 +3578,13 @@ interval_mul(PG_FUNCTION_ARGS)
3582
3578
}
3583
3579
3584
3580
result_double = span -> month * factor ;
3585
- if (isnan (result_double ) ||
3586
- result_double > INT_MAX || result_double < INT_MIN )
3587
- ereport (ERROR ,
3588
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3589
- errmsg ("interval out of range" )));
3581
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3582
+ goto out_of_range ;
3590
3583
result -> month = (int32 ) result_double ;
3591
3584
3592
3585
result_double = span -> day * factor ;
3593
- if (isnan (result_double ) ||
3594
- result_double > INT_MAX || result_double < INT_MIN )
3595
- ereport (ERROR ,
3596
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3597
- errmsg ("interval out of range" )));
3586
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3587
+ goto out_of_range ;
3598
3588
result -> day = (int32 ) result_double ;
3599
3589
3600
3590
/*
@@ -3628,25 +3618,33 @@ interval_mul(PG_FUNCTION_ARGS)
3628
3618
*/
3629
3619
if (fabs (sec_remainder ) >= SECS_PER_DAY )
3630
3620
{
3631
- result -> day += (int ) (sec_remainder / SECS_PER_DAY );
3621
+ if (pg_add_s32_overflow (result -> day ,
3622
+ (int ) (sec_remainder / SECS_PER_DAY ),
3623
+ & result -> day ))
3624
+ goto out_of_range ;
3632
3625
sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
3633
3626
}
3634
3627
3635
3628
/* cascade units down */
3636
- result -> day += (int32 ) month_remainder_days ;
3629
+ if (pg_add_s32_overflow (result -> day , (int32 ) month_remainder_days ,
3630
+ & result -> day ))
3631
+ goto out_of_range ;
3637
3632
result_double = rint (span -> time * factor + sec_remainder * USECS_PER_SEC );
3638
3633
if (isnan (result_double ) || !FLOAT8_FITS_IN_INT64 (result_double ))
3639
- ereport (ERROR ,
3640
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3641
- errmsg ("interval out of range" )));
3634
+ goto out_of_range ;
3642
3635
result -> time = (int64 ) result_double ;
3643
3636
3644
3637
if (INTERVAL_NOT_FINITE (result ))
3645
- ereport (ERROR ,
3646
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3647
- errmsg ("interval out of range" )));
3638
+ goto out_of_range ;
3648
3639
3649
3640
PG_RETURN_INTERVAL_P (result );
3641
+
3642
+ out_of_range :
3643
+ ereport (ERROR ,
3644
+ errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3645
+ errmsg ("interval out of range" ));
3646
+
3647
+ PG_RETURN_NULL (); /* keep compiler quiet */
3650
3648
}
3651
3649
3652
3650
Datum
@@ -3665,7 +3663,8 @@ interval_div(PG_FUNCTION_ARGS)
3665
3663
Interval * span = PG_GETARG_INTERVAL_P (0 );
3666
3664
float8 factor = PG_GETARG_FLOAT8 (1 );
3667
3665
double month_remainder_days ,
3668
- sec_remainder ;
3666
+ sec_remainder ,
3667
+ result_double ;
3669
3668
int32 orig_month = span -> month ,
3670
3669
orig_day = span -> day ;
3671
3670
Interval * result ;
@@ -3685,16 +3684,12 @@ interval_div(PG_FUNCTION_ARGS)
3685
3684
* by the regular division code, causing all fields to be set to zero.
3686
3685
*/
3687
3686
if (isnan (factor ))
3688
- ereport (ERROR ,
3689
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3690
- errmsg ("interval out of range" )));
3687
+ goto out_of_range ;
3691
3688
3692
3689
if (INTERVAL_NOT_FINITE (span ))
3693
3690
{
3694
3691
if (isinf (factor ))
3695
- ereport (ERROR ,
3696
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3697
- errmsg ("interval out of range" )));
3692
+ goto out_of_range ;
3698
3693
3699
3694
if (factor < 0.0 )
3700
3695
interval_um_internal (span , result );
@@ -3704,8 +3699,15 @@ interval_div(PG_FUNCTION_ARGS)
3704
3699
PG_RETURN_INTERVAL_P (result );
3705
3700
}
3706
3701
3707
- result -> month = (int32 ) (span -> month / factor );
3708
- result -> day = (int32 ) (span -> day / factor );
3702
+ result_double = span -> month / factor ;
3703
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3704
+ goto out_of_range ;
3705
+ result -> month = (int32 ) result_double ;
3706
+
3707
+ result_double = span -> day / factor ;
3708
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3709
+ goto out_of_range ;
3710
+ result -> day = (int32 ) result_double ;
3709
3711
3710
3712
/*
3711
3713
* Fractional months full days into days. See comment in interval_mul().
@@ -3717,20 +3719,33 @@ interval_div(PG_FUNCTION_ARGS)
3717
3719
sec_remainder = TSROUND (sec_remainder );
3718
3720
if (fabs (sec_remainder ) >= SECS_PER_DAY )
3719
3721
{
3720
- result -> day += (int ) (sec_remainder / SECS_PER_DAY );
3722
+ if (pg_add_s32_overflow (result -> day ,
3723
+ (int ) (sec_remainder / SECS_PER_DAY ),
3724
+ & result -> day ))
3725
+ goto out_of_range ;
3721
3726
sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
3722
3727
}
3723
3728
3724
3729
/* cascade units down */
3725
- result -> day += (int32 ) month_remainder_days ;
3726
- result -> time = rint (span -> time / factor + sec_remainder * USECS_PER_SEC );
3730
+ if (pg_add_s32_overflow (result -> day , (int32 ) month_remainder_days ,
3731
+ & result -> day ))
3732
+ goto out_of_range ;
3733
+ result_double = rint (span -> time / factor + sec_remainder * USECS_PER_SEC );
3734
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT64 (result_double ))
3735
+ goto out_of_range ;
3736
+ result -> time = (int64 ) result_double ;
3727
3737
3728
3738
if (INTERVAL_NOT_FINITE (result ))
3729
- ereport (ERROR ,
3730
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3731
- errmsg ("interval out of range" )));
3739
+ goto out_of_range ;
3732
3740
3733
3741
PG_RETURN_INTERVAL_P (result );
3742
+
3743
+ out_of_range :
3744
+ ereport (ERROR ,
3745
+ errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3746
+ errmsg ("interval out of range" ));
3747
+
3748
+ PG_RETURN_NULL (); /* keep compiler quiet */
3734
3749
}
3735
3750
3736
3751
0 commit comments