Skip to content

Commit 8442cb1

Browse files
authored
Merge pull request #9139 from kenjis/session-sid-change
[4.6] feat: force PHP default 32 chars length at 4 bits to Session ID
2 parents dc45e42 + 703c273 commit 8442cb1

File tree

5 files changed

+84
-57
lines changed

5 files changed

+84
-57
lines changed

system/Debug/Exceptions.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ public function exceptionHandler(Throwable $exception)
209209
public function errorHandler(int $severity, string $message, ?string $file = null, ?int $line = null)
210210
{
211211
if ($this->isDeprecationError($severity)) {
212+
if ($this->isSessionSidDeprecationError($message, $file, $line)) {
213+
return true;
214+
}
215+
212216
if (! $this->config->logDeprecations || (bool) env('CODEIGNITER_SCREAM_DEPRECATIONS')) {
213217
throw new ErrorException($message, 0, $severity, $file, $line);
214218
}
@@ -223,6 +227,32 @@ public function errorHandler(int $severity, string $message, ?string $file = nul
223227
return false; // return false to propagate the error to PHP standard error handler
224228
}
225229

230+
/**
231+
* Handles session.sid_length and session.sid_bits_per_character deprecations
232+
* in PHP 8.4.
233+
*/
234+
private function isSessionSidDeprecationError(string $message, ?string $file = null, ?int $line = null): bool
235+
{
236+
if (
237+
PHP_VERSION_ID >= 80400
238+
&& str_contains($message, 'session.sid_')
239+
) {
240+
log_message(
241+
LogLevel::WARNING,
242+
'[DEPRECATED] {message} in {errFile} on line {errLine}.',
243+
[
244+
'message' => $message,
245+
'errFile' => clean_path($file ?? ''),
246+
'errLine' => $line ?? 0,
247+
]
248+
);
249+
250+
return true;
251+
}
252+
253+
return false;
254+
}
255+
226256
/**
227257
* Checks to see if any errors have happened during shutdown that
228258
* need to be caught and handle them.

system/Session/Handlers/FileHandler.php

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -309,32 +309,25 @@ public function gc($max_lifetime)
309309

310310
/**
311311
* Configure Session ID regular expression
312+
*
313+
* To make life easier, we force the PHP defaults. Because PHP9 forces them.
314+
* See https://wiki.php.net/rfc/deprecations_php_8_4#sessionsid_length_and_sessionsid_bits_per_character
312315
*/
313316
protected function configureSessionIDRegex()
314317
{
315318
$bitsPerCharacter = (int) ini_get('session.sid_bits_per_character');
316-
$SIDLength = (int) ini_get('session.sid_length');
317-
318-
if (($bits = $SIDLength * $bitsPerCharacter) < 160) {
319-
// Add as many more characters as necessary to reach at least 160 bits
320-
$SIDLength += (int) ceil((160 % $bits) / $bitsPerCharacter);
321-
ini_set('session.sid_length', (string) $SIDLength);
322-
}
323-
324-
switch ($bitsPerCharacter) {
325-
case 4:
326-
$this->sessionIDRegex = '[0-9a-f]';
327-
break;
319+
$sidLength = (int) ini_get('session.sid_length');
328320

329-
case 5:
330-
$this->sessionIDRegex = '[0-9a-v]';
331-
break;
332-
333-
case 6:
334-
$this->sessionIDRegex = '[0-9a-zA-Z,-]';
335-
break;
321+
// We force the PHP defaults.
322+
if (PHP_VERSION_ID < 90000) {
323+
if ($bitsPerCharacter !== 4) {
324+
ini_set('session.sid_bits_per_character', '4');
325+
}
326+
if ($sidLength !== 32) {
327+
ini_set('session.sid_length', '32');
328+
}
336329
}
337330

338-
$this->sessionIDRegex .= '{' . $SIDLength . '}';
331+
$this->sessionIDRegex = '[0-9a-f]{32}';
339332
}
340333
}

system/Session/Session.php

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -316,49 +316,25 @@ protected function configure()
316316
/**
317317
* Configure session ID length
318318
*
319-
* To make life easier, we used to force SHA-1 and 4 bits per
320-
* character on everyone. And of course, someone was unhappy.
321-
*
322-
* Then PHP 7.1 broke backwards-compatibility because ext/session
323-
* is such a mess that nobody wants to touch it with a pole stick,
324-
* and the one guy who does, nobody has the energy to argue with.
325-
*
326-
* So we were forced to make changes, and OF COURSE something was
327-
* going to break and now we have this pile of shit. -- Narf
319+
* To make life easier, we force the PHP defaults. Because PHP9 forces them.
320+
* See https://wiki.php.net/rfc/deprecations_php_8_4#sessionsid_length_and_sessionsid_bits_per_character
328321
*/
329322
protected function configureSidLength()
330323
{
331-
$bitsPerCharacter = (int) (ini_get('session.sid_bits_per_character') !== false
332-
? ini_get('session.sid_bits_per_character')
333-
: 4);
334-
335-
$sidLength = (int) (ini_get('session.sid_length') !== false
336-
? ini_get('session.sid_length')
337-
: 40);
338-
339-
if (($sidLength * $bitsPerCharacter) < 160) {
340-
$bits = ($sidLength * $bitsPerCharacter);
341-
// Add as many more characters as necessary to reach at least 160 bits
342-
$sidLength += (int) ceil((160 % $bits) / $bitsPerCharacter);
343-
ini_set('session.sid_length', (string) $sidLength);
344-
}
324+
$bitsPerCharacter = (int) ini_get('session.sid_bits_per_character');
325+
$sidLength = (int) ini_get('session.sid_length');
345326

346-
// Yes, 4,5,6 are the only known possible values as of 2016-10-27
347-
switch ($bitsPerCharacter) {
348-
case 4:
349-
$this->sidRegexp = '[0-9a-f]';
350-
break;
351-
352-
case 5:
353-
$this->sidRegexp = '[0-9a-v]';
354-
break;
355-
356-
case 6:
357-
$this->sidRegexp = '[0-9a-zA-Z,-]';
358-
break;
327+
// We force the PHP defaults.
328+
if (PHP_VERSION_ID < 90000) {
329+
if ($bitsPerCharacter !== 4) {
330+
ini_set('session.sid_bits_per_character', '4');
331+
}
332+
if ($sidLength !== 32) {
333+
ini_set('session.sid_length', '32');
334+
}
359335
}
360336

361-
$this->sidRegexp .= '{' . $sidLength . '}';
337+
$this->sidRegexp = '[0-9a-f]{32}';
362338
}
363339

364340
/**

user_guide_src/source/changelogs/v4.6.0.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ environment, this behavior has been fixed so that error details are displayed if
9090
With this fix, the error details are now displayed under the same conditions for
9191
both HTML requests and non-HTML requests.
9292

93+
Session ID (SID)
94+
----------------
95+
96+
Now ``Session`` library forces to use the PHP default 32 character SIDs, with 4
97+
bits of entropy per character.
98+
See :ref:`Upgrading Guide <upgrade-460-sid-change>` for details.
99+
93100
.. _v460-interface-changes:
94101

95102
Interface Changes

user_guide_src/source/installation/upgrade_460.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,27 @@ The following is an example of code that will no longer work:
126126

127127
.. literalinclude:: upgrade_460/001.php
128128

129+
.. _upgrade-460-sid-change:
130+
131+
Session ID (SID) Change
132+
=======================
133+
134+
Now :doc:`../libraries/sessions` forces to use the PHP default 32 character SIDs,
135+
with 4 bits of entropy per character. This change is to match the behavior of
136+
PHP 9.
137+
138+
In other words, the following settings are always used:
139+
140+
.. code-block:: ini
141+
142+
session.sid_bits_per_character = 4
143+
session.sid_length = 32
144+
145+
In previous versions, the PHP ini settings was respected. So this change may
146+
change your SID length.
147+
148+
If you cannot accept this change, customize the Session library.
149+
129150
Interface Changes
130151
=================
131152

0 commit comments

Comments
 (0)