Summary
php_filter_encode_url() builds a 256-entry lookup table that decides which bytes FILTER_SANITIZE_ENCODED percent-encodes, but initialises only the first 255 entries. Entry 255 is read uninitialised, so whether the byte 0xFF is encoded or passed through depends on whatever happened to be on the stack.
Details
The table is filled with memset(tmp, 1, sizeof(tmp) - 1), which leaves tmp[255] untouched:
https://github.com/php/php-src/blob/php-8.5.9/ext/filter/sanitizing_filters.c#L73
The filter then consults tmp[*s] for every input byte, so for 0xFF the decision comes from uninitialised stack memory. Every other byte is handled deterministically.
The fix changes the memset() length to sizeof(tmp) so the whole table is initialised.
PoC