Skip to content

Commit

Permalink
Fix GH-14709 overflow on recurrences for DatePeriod::__construct
Browse files Browse the repository at this point in the history
  • Loading branch information
devnexen committed Dec 12, 2024
1 parent e7af08d commit d75ea22
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 10 deletions.
20 changes: 16 additions & 4 deletions ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -4903,19 +4903,31 @@ static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_en

static bool date_period_init_finish(php_period_obj *dpobj, zend_long options, zend_long recurrences)
{
if (dpobj->end == NULL && recurrences < 1) {
const zend_long max_recurrences = (INT_MAX - 8);

if (dpobj->end == NULL && (recurrences < 1 || recurrences > max_recurrences)) {
zend_string *func = get_active_function_or_method_name();
zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "%s(): Recurrence count must be greater than 0", ZSTR_VAL(func));
zend_throw_exception_ex(NULL, 0, "%s(): Recurrence count must be greater or equal to 1 and lower than " ZEND_LONG_FMT, ZSTR_VAL(func), max_recurrences + 1);
zend_string_release(func);
return false;
}


/* options */
dpobj->include_start_date = !(options & PHP_DATE_PERIOD_EXCLUDE_START_DATE);
dpobj->include_end_date = options & PHP_DATE_PERIOD_INCLUDE_END_DATE;

/* recurrrences */
dpobj->recurrences = recurrences + dpobj->include_start_date + dpobj->include_end_date;
/* recurrences */
recurrences += dpobj->include_start_date + dpobj->include_end_date;

if (UNEXPECTED(recurrences > max_recurrences)) {
zend_string *func = get_active_function_or_method_name();
zend_throw_exception_ex(NULL, 0, "%s(): Recurrence count must be greater or equal to 1 and lower than " ZEND_LONG_FMT " (including options)", ZSTR_VAL(func), max_recurrences + 1);
zend_string_release(func);
return false;
}

dpobj->recurrences = (int)recurrences;

dpobj->initialized = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ try {
}

?>
--EXPECT--
DatePeriod::__construct(): Recurrence count must be greater than 0
DatePeriod::__construct(): Recurrence count must be greater than 0
--EXPECTF--
DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d
DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d
6 changes: 3 additions & 3 deletions ext/date/tests/date_period_bad_iso_format.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ try {
}

?>
--EXPECT--
--EXPECTF--
DateMalformedPeriodStringException: DatePeriod::__construct(): ISO interval must contain a start date, "R4" given
DateMalformedPeriodStringException: DatePeriod::createFromISO8601String(): ISO interval must contain a start date, "R4" given
DateMalformedPeriodStringException: DatePeriod::__construct(): ISO interval must contain an interval, "R4/2012-07-01T00:00:00Z" given
DateMalformedPeriodStringException: DatePeriod::createFromISO8601String(): ISO interval must contain an interval, "R4/2012-07-01T00:00:00Z" given
DateMalformedPeriodStringException: DatePeriod::__construct(): Recurrence count must be greater than 0
DateMalformedPeriodStringException: DatePeriod::createFromISO8601String(): Recurrence count must be greater than 0
Exception: DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d
Exception: DatePeriod::createFromISO8601String(): Recurrence count must be greater or equal to 1 and lower than %d
22 changes: 22 additions & 0 deletions ext/date/tests/gh14709.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Bug GH-14709 overflow on reccurences parameter
--FILE--
<?php
$start = new DateTime('2018-12-31 00:00:00');
$interval = new DateInterval('P1M');

try {
new DatePeriod($start, $interval, 2147483640);
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
}

try {
new DatePeriod($start, $interval, 2147483639, DatePeriod::EXCLUDE_START_DATE | DatePeriod::INCLUDE_END_DATE);
} catch (Exception $e) {
echo $e->getMessage();
}
?>
--EXPECTF--
DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d
DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d (including options)

0 comments on commit d75ea22

Please sign in to comment.