@@ -3548,17 +3548,14 @@ interval_mul(PG_FUNCTION_ARGS)
35483548 * interval type has nothing equivalent to NaN.
35493549 */
35503550 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 ;
35543552
35553553 if (INTERVAL_NOT_FINITE (span ))
35563554 {
35573555 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 )
35623559 interval_um_internal (span , result );
35633560 else
35643561 memcpy (result , span , sizeof (Interval ));
@@ -3570,10 +3567,9 @@ interval_mul(PG_FUNCTION_ARGS)
35703567 int isign = interval_sign (span );
35713568
35723569 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 )
35773573 INTERVAL_NOBEGIN (result );
35783574 else
35793575 INTERVAL_NOEND (result );
@@ -3582,19 +3578,13 @@ interval_mul(PG_FUNCTION_ARGS)
35823578 }
35833579
35843580 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 ;
35903583 result -> month = (int32 ) result_double ;
35913584
35923585 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 ;
35983588 result -> day = (int32 ) result_double ;
35993589
36003590 /*
@@ -3628,25 +3618,33 @@ interval_mul(PG_FUNCTION_ARGS)
36283618 */
36293619 if (fabs (sec_remainder ) >= SECS_PER_DAY )
36303620 {
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 ;
36323625 sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
36333626 }
36343627
36353628 /* 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 ;
36373632 result_double = rint (span -> time * factor + sec_remainder * USECS_PER_SEC );
36383633 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 ;
36423635 result -> time = (int64 ) result_double ;
36433636
36443637 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 ;
36483639
36493640 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 */
36503648}
36513649
36523650Datum
@@ -3665,7 +3663,8 @@ interval_div(PG_FUNCTION_ARGS)
36653663 Interval * span = PG_GETARG_INTERVAL_P (0 );
36663664 float8 factor = PG_GETARG_FLOAT8 (1 );
36673665 double month_remainder_days ,
3668- sec_remainder ;
3666+ sec_remainder ,
3667+ result_double ;
36693668 int32 orig_month = span -> month ,
36703669 orig_day = span -> day ;
36713670 Interval * result ;
@@ -3685,16 +3684,12 @@ interval_div(PG_FUNCTION_ARGS)
36853684 * by the regular division code, causing all fields to be set to zero.
36863685 */
36873686 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 ;
36913688
36923689 if (INTERVAL_NOT_FINITE (span ))
36933690 {
36943691 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 ;
36983693
36993694 if (factor < 0.0 )
37003695 interval_um_internal (span , result );
@@ -3704,8 +3699,15 @@ interval_div(PG_FUNCTION_ARGS)
37043699 PG_RETURN_INTERVAL_P (result );
37053700 }
37063701
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 ;
37093711
37103712 /*
37113713 * Fractional months full days into days. See comment in interval_mul().
@@ -3717,20 +3719,33 @@ interval_div(PG_FUNCTION_ARGS)
37173719 sec_remainder = TSROUND (sec_remainder );
37183720 if (fabs (sec_remainder ) >= SECS_PER_DAY )
37193721 {
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 ;
37213726 sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
37223727 }
37233728
37243729 /* 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 ;
37273737
37283738 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 ;
37323740
37333741 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 */
37343749}
37353750
37363751
0 commit comments