@@ -3315,19 +3315,13 @@ interval_mul(PG_FUNCTION_ARGS)
3315
3315
result = (Interval * ) palloc (sizeof (Interval ));
3316
3316
3317
3317
result_double = span -> month * factor ;
3318
- if (isnan (result_double ) ||
3319
- result_double > INT_MAX || result_double < INT_MIN )
3320
- ereport (ERROR ,
3321
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3322
- errmsg ("interval out of range" )));
3318
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3319
+ goto out_of_range ;
3323
3320
result -> month = (int32 ) result_double ;
3324
3321
3325
3322
result_double = span -> day * factor ;
3326
- if (isnan (result_double ) ||
3327
- result_double > INT_MAX || result_double < INT_MIN )
3328
- ereport (ERROR ,
3329
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3330
- errmsg ("interval out of range" )));
3323
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3324
+ goto out_of_range ;
3331
3325
result -> day = (int32 ) result_double ;
3332
3326
3333
3327
/*
@@ -3361,20 +3355,30 @@ interval_mul(PG_FUNCTION_ARGS)
3361
3355
*/
3362
3356
if (fabs (sec_remainder ) >= SECS_PER_DAY )
3363
3357
{
3364
- result -> day += (int ) (sec_remainder / SECS_PER_DAY );
3358
+ if (pg_add_s32_overflow (result -> day ,
3359
+ (int ) (sec_remainder / SECS_PER_DAY ),
3360
+ & result -> day ))
3361
+ goto out_of_range ;
3365
3362
sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
3366
3363
}
3367
3364
3368
3365
/* cascade units down */
3369
- result -> day += (int32 ) month_remainder_days ;
3366
+ if (pg_add_s32_overflow (result -> day , (int32 ) month_remainder_days ,
3367
+ & result -> day ))
3368
+ goto out_of_range ;
3370
3369
result_double = rint (span -> time * factor + sec_remainder * USECS_PER_SEC );
3371
3370
if (isnan (result_double ) || !FLOAT8_FITS_IN_INT64 (result_double ))
3372
- ereport (ERROR ,
3373
- (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3374
- errmsg ("interval out of range" )));
3371
+ goto out_of_range ;
3375
3372
result -> time = (int64 ) result_double ;
3376
3373
3377
3374
PG_RETURN_INTERVAL_P (result );
3375
+
3376
+ out_of_range :
3377
+ ereport (ERROR ,
3378
+ errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3379
+ errmsg ("interval out of range" ));
3380
+
3381
+ PG_RETURN_NULL (); /* keep compiler quiet */
3378
3382
}
3379
3383
3380
3384
Datum
@@ -3393,7 +3397,8 @@ interval_div(PG_FUNCTION_ARGS)
3393
3397
Interval * span = PG_GETARG_INTERVAL_P (0 );
3394
3398
float8 factor = PG_GETARG_FLOAT8 (1 );
3395
3399
double month_remainder_days ,
3396
- sec_remainder ;
3400
+ sec_remainder ,
3401
+ result_double ;
3397
3402
int32 orig_month = span -> month ,
3398
3403
orig_day = span -> day ;
3399
3404
Interval * result ;
@@ -3405,8 +3410,15 @@ interval_div(PG_FUNCTION_ARGS)
3405
3410
(errcode (ERRCODE_DIVISION_BY_ZERO ),
3406
3411
errmsg ("division by zero" )));
3407
3412
3408
- result -> month = (int32 ) (span -> month / factor );
3409
- result -> day = (int32 ) (span -> day / factor );
3413
+ result_double = span -> month / factor ;
3414
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3415
+ goto out_of_range ;
3416
+ result -> month = (int32 ) result_double ;
3417
+
3418
+ result_double = span -> day / factor ;
3419
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT32 (result_double ))
3420
+ goto out_of_range ;
3421
+ result -> day = (int32 ) result_double ;
3410
3422
3411
3423
/*
3412
3424
* Fractional months full days into days. See comment in interval_mul().
@@ -3418,15 +3430,30 @@ interval_div(PG_FUNCTION_ARGS)
3418
3430
sec_remainder = TSROUND (sec_remainder );
3419
3431
if (fabs (sec_remainder ) >= SECS_PER_DAY )
3420
3432
{
3421
- result -> day += (int ) (sec_remainder / SECS_PER_DAY );
3433
+ if (pg_add_s32_overflow (result -> day ,
3434
+ (int ) (sec_remainder / SECS_PER_DAY ),
3435
+ & result -> day ))
3436
+ goto out_of_range ;
3422
3437
sec_remainder -= (int ) (sec_remainder / SECS_PER_DAY ) * SECS_PER_DAY ;
3423
3438
}
3424
3439
3425
3440
/* cascade units down */
3426
- result -> day += (int32 ) month_remainder_days ;
3427
- result -> time = rint (span -> time / factor + sec_remainder * USECS_PER_SEC );
3441
+ if (pg_add_s32_overflow (result -> day , (int32 ) month_remainder_days ,
3442
+ & result -> day ))
3443
+ goto out_of_range ;
3444
+ result_double = rint (span -> time / factor + sec_remainder * USECS_PER_SEC );
3445
+ if (isnan (result_double ) || !FLOAT8_FITS_IN_INT64 (result_double ))
3446
+ goto out_of_range ;
3447
+ result -> time = (int64 ) result_double ;
3428
3448
3429
3449
PG_RETURN_INTERVAL_P (result );
3450
+
3451
+ out_of_range :
3452
+ ereport (ERROR ,
3453
+ errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
3454
+ errmsg ("interval out of range" ));
3455
+
3456
+ PG_RETURN_NULL (); /* keep compiler quiet */
3430
3457
}
3431
3458
3432
3459
0 commit comments