Skip to content

Fix GH-14709 overflow on recurrences for DatePeriod::__construct #14710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

devnexen
Copy link
Member

No description provided.

@devnexen
Copy link
Member Author

Note : apparently needs adaptation with higher branches.

@devnexen devnexen changed the title Fix GH-14709 overflow on reccurences for DatePeriod::__construct Fix GH-14709 overflow on recurrences for DatePeriod::__construct Jun 29, 2024
@devnexen devnexen requested a review from nielsdos June 29, 2024 15:23
Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more or less right: recurrences is an int in _php_period_obj so we can't store a higher number. The issue isn't fully solved though because if include_start_date and include_end_date are set then you still get an integer overflow because you can add 2 to INT_MAX.

@nielsdos
Copy link
Member

From a technical PoV this is right and stops the undefined behaviour.
Me being pragmatic I think I would've just capped it at INT_MAX-2 because we don't lose much here. It would be a simpler patch.
I don't know what Derick prefers, I'm leaving the decision to him as this is his ext, not mine.

@devnexen
Copy link
Member Author

in fact I tried to separate to let know of the second edge case separately but yes it s not so urgent anyway we ll see :).

Copy link
Member

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with @nielsdos here — capping it at INT_MAX - 8 (in case we get further options), seems perfectly cromulent.

zend_string *func = get_active_function_or_method_name();
zend_throw_exception_ex(NULL, 0, "%s(): Recurrence count must be greater than 0", ZSTR_VAL(func));
zend_throw_exception_ex(NULL, 0, "%s(): Recurrence count must be between 1 and %d", ZSTR_VAL(func), INT_MAX);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

between 1 is ambiguous between > 1 or >= 1. Please be precise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's standard wording (and always refers to the closed interval). cc @Girgias

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have always used it to mean an inclusive range AFAIK.

Might help to have helper functions for this, similar to what I did for ValueErrors which are empty.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I revert back to the previous wording ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe wait a while on @derickr's opinion.

Bug GH-14709 overflow on reccurences parameter
--SKIPIF--
<?php
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is superfluous. Doesn't the test run fine on 32bit platforms, too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not recall why, usually I do not disable for 32 bits just like this. I ll give it a go in a bit later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems working indeed, might had been just a case I forgot to remove after code changes.

@cmb69
Copy link
Member

cmb69 commented Dec 3, 2024

This should not be applied to PHP-8.2 any longer.

@devnexen
Copy link
Member Author

devnexen commented Dec 3, 2024

Ah good point, time flies :)

Copy link
Member

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks OK as is, but please squash the commits first, and rebase for PHP 8.3.

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why you removed the specific extension here? We had an RFC for this:

https://wiki.php.net/rfc/datetime-exceptions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/extension/exception ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I see, going to fix these..

zend_string_release(func);
return false;
}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: No need to add empty lines


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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also use the specific extension here again.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the exception class, like in the other tests, by using:

echo $e::class, ': ', echo $e->getMessage() . PHP_EOL;

Copy link
Member

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but please address my last nit. And then also please squash before merging.

Exception: DatePeriod::createFromISO8601String(): Recurrence count must be greater or equal to 1 and lower than %d
DateMalformedPeriodStringException: DatePeriod::__construct(): Recurrence count must be greater or equal to 1 and lower than %d
DateMalformedPeriodStringException: DatePeriod::createFromISO8601String(): Recurrence count must be greater or equal to 1 and lower than %d

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extraneous line at end of file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Signed integer overflow in ext/date/php_date.c
5 participants