Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
session: use the session interfaces for the missing method check
  • Loading branch information
lazerg committed Aug 17, 2026
commit 0c963e49c8e256dc444cea7ec2c5dbec9f1bc59a
12 changes: 6 additions & 6 deletions ext/session/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -2935,12 +2935,12 @@ static PHP_GINIT_FUNCTION(ps)
ps_globals->random_seeded = false;
}

/* The interfaces listed after SessionHandlerInterface have not had their abstract methods
* inherited into the function table yet, so look them up in the interface list as well. */
static bool session_interfaces_declare_method(const zend_class_entry *ce, const char *name, size_t name_len)
/* Interfaces extending the given one are not flattened into ce->interfaces before they are
* themselves processed, so every entry has to be checked with instanceof. */
static bool session_interfaces_include(const zend_class_entry *ce, const zend_class_entry *iface)
{
for (uint32_t i = 0; i < ce->num_interfaces; i++) {
if (zend_hash_str_exists(&ce->interfaces[i]->function_table, name, name_len)) {
if (instanceof_function(ce->interfaces[i], iface)) {
return true;
}
}
Comment on lines +2942 to +2946

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd rather we iterate on ce->interfaces[i] and check that the CE is SessionIdInterface or SessionUpdateTimestampHandlerInterface rather than name checking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in a783cff. It iterates ce->interfaces[i] and uses instanceof_function() per entry, so an interface that extends SessionIdInterface or SessionUpdateTimestampHandlerInterface is still recognised before it has been flattened into the list.

One case this drops, which the name check covered: a class that gets the methods from an unrelated interface. implements OwnMethods, SessionHandlerInterface stays quiet, implements SessionHandlerInterface, OwnMethods now warns again. session_set_save_handler() accepts the methods there regardless of the interface, so the two rules differ. Tell me if you want that case back and I will restore the method lookup.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Considering the objective is to move the methods from those 2 interfaces to the "base" interface having another interface declare such a method is not something we should be supporting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, that keeps the check aligned with the migration path, so I have left the behaviour as you asked.

Correction on my earlier reply though: a783cff only carried the test move. I botched the staging and the session.c change never made it into that commit. It is in 0c963e4 now, so the diff you reviewed was still the old name lookup. Sorry for the noise.

Expand All @@ -2949,13 +2949,13 @@ static bool session_interfaces_declare_method(const zend_class_entry *ce, const

static int session_handler_interface_gets_implemented(zend_class_entry *self, zend_class_entry *class) {
if (!zend_hash_str_exists(&class->function_table, ZEND_STRL("create_sid"))
&& !session_interfaces_declare_method(class, ZEND_STRL("create_sid"))) {
&& !session_interfaces_include(class, php_session_id_iface_entry)) {
zend_error(E_WARNING,
"Class %s implementing SessionHandlerInterface is missing the create_sid() method which will be required in PHP 9.0",
ZSTR_VAL(class->name));
}
if (!zend_hash_str_exists(&class->function_table, ZEND_STRL("validateid"))
&& !session_interfaces_declare_method(class, ZEND_STRL("validateid"))) {
&& !session_interfaces_include(class, php_session_update_timestamp_iface_entry)) {
zend_error(E_WARNING,
"Class %s implementing SessionHandlerInterface is missing the validateId() method which will be required in PHP 9.0",
ZSTR_VAL(class->name));
Expand Down
7 changes: 2 additions & 5 deletions ext/session/tests/user_session_module/gh23328.phpt

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please move this test into the user_session_submodule subdirectory

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved to ext/session/tests/user_session_module/gh23328.phpt in a783cff.

Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ interface CombinedInterface extends SessionIdInterface, SessionUpdateTimestampHa
abstract class CombinedFirst implements CombinedInterface, SessionHandlerInterface {}
abstract class CombinedLast implements SessionHandlerInterface, CombinedInterface {}

interface OwnMethods {
public function create_sid(): string;
public function validateId(string $id): bool;
}
abstract class OwnMethodsLast implements SessionHandlerInterface, OwnMethods {}
interface NestedInterface extends CombinedInterface {}
abstract class NestedLast implements SessionHandlerInterface, NestedInterface {}

abstract class MissingBoth implements SessionHandlerInterface {}
abstract class MissingValidateId implements SessionHandlerInterface, SessionIdInterface {}
Expand Down
Loading