|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2018-05-20 17:19 UTC] tony at marston-home dot demon dot co dot uk
 Description: ------------ This error was introduced in 7.2 for no good reason. I have been using this technique since 2003 to enable a user to have multiple sessions on the same PC, each with its own name and ID. This now fails. I know that https://bugs.php.net/bug.php?id=75650 has declared that this not a bug, but I strongly disagree. Why was this change made? What was the reasoning? If this usage does not cause a problem in the engine then why is it now being disallowed? If this is someone's idea of "purity" then that someone needs a good talking to as this is overstepping the mark. Test script: --------------- session_start(); $old_name = session_name('NEWSESSION'); // with 7.2 this now returns FALSE session_regenerate_id(); … do something session_name($old_name); // with 7.2 this now fails as $old_name is FALSE Expected result: ---------------- I expect session_name() to do what it has been doing for the past 15 years, that is to return the existing session name while assigning a new one. The documentation clearly states "Get and/or set the current session name", and the "and/or" indicates that it should be able to do both at the same time. Actual result: -------------- session_name() returns FALSE instead of the current session name. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 11:00:01 2025 UTC | 
There is nothing in the documentation which says that you cannot use session_name() to change the name of a session that has already started. This is a legitimate thing to do if you want to access the same session data with a new name and id. Take the following code: $name1 = session_name(); // returns 'PHPSESSID' $id1 = session_id(); // returns empty string session_start(); $name2 = session_name(); // returns 'PHPSESSID' $id2 = session_id(); // returns non-empty string session_name('NEWSESSID'); $name3 = session_name(); // returns 'PHPSESSID' instead of 'NEWSESSID' session_regenerate_id(); -- restart script to use new session Note that as of 7.2 $name3 now contains the OLD name instead of the NEW name. If the problem was that it changed the session name but failed to return the existing name then the CORRECT fix would be to make it return the existing name AS WELL AS changing to the new name. Where was this "problem" ever reported as a bug? When was this change in behaviour ever discussed and voted upon by the internals group? This is a BC break which has not been documented anywhere, nor was it ever discussed on the internals group.>Not all changes to PHP require an RFC. This one was mentioned on the internals list by @yohgaki in mid October 2016 ("Fixing insane session_start() behaviors") and the discussion lasted for a couple days without any dissenting opinions offered. During the discussion on the internals list and on github, @yohgaki did mention that he _should_ have written an RFC on the subject, but never got around to doing so. Perhaps he could write one ex post facto to consolidate the whys and wherefores of this change and serve as a future citation reference.> I expect session_name() to do what it has been doing for the > past 15 years, that is to return the existing session name while > assigning a new one. It did not change the session name, though. > The documentation clearly states "Get and/or set the current > session name", and the "and/or" indicates that it should be able > to do both at the same time. The documentation also clearly states: | Thus, you need to call session_name() for every request (and | before session_start() or session_register() are called). And: | If name is given and function updates the session name, name of | the old session is returned. Since session_name('foo') does not update the name of the session if it has already been started, it *must* not return the name of the old session according to the documentation.> It did not change the session name, though. Yes it did. I stated using "session_name('newname')" as early as 2003 (and documented on my website in 2005). It kept on doing just that until it was broken in 7.2. > The documentation also clearly states: | Thus, you need to call session_name() for every request (and | before session_start() or session_register() are called). That means that you must follow a call to session_name() with a call to session_start() before the new name can take effect. It *DOES NOT* mean that you cannot call session_name('newname') while the current session is still active. > Since session_name('foo') does not update the name of the session > if it has already been started, it *must* not return the name of > the old session according to the documentation. The fact that "$oldname = session_name('newname')" did not work AS DOCUMENTED was a bug. The description for this function CLEARLY states the following: "session_name() returns the name of the current session. If name is given, session_name() will update the session name *AND* return the old session name. That clearly states that you should be able to both return the name of the current session *AND* set a new session name at the same time. It was *NEVER* necessary to close the current session before changing its name.This discussion hurts my brain; can it start over and be simplified? Example: session_start(); $old = session_name('foo'); Do I understand the change here? In that: * Before 7.2: $old = the current session name * 7.2: $old = false; and E_WARNING generated * Before 7.2: session name does not change to 'foo' as it's after session_start() * 7.2: same, session name does not change to 'foo' Also, curious, is the following also affected in PHP 7.2? I assume not: session_start(); $old = session_name(); // current session name If I understand it correctly then there was a BC break. The change probably saw it was silly to allow session_name('foo') in situations that the session name could not change, which I understand, now should the return value have also changed without official deprecation first? Probably. Returning false now means that the session name could not be changed when before it simply returned the current session name. FWIW, and if I understand the change here, I'd leave the change at this point although it's not an easy decision. Using session_name('foo') means the programmer expects 'foo' as the new session name as otherwise the bogus code should fail. I can't think of another use case or reason it should not fail but maybe others can.There are two uses for session_name: 1) Return the current session name. 2) Assign a new session name. According to the documentation for the last 20 years it should also be possible to do both, which implies that it is not necessary to close the current session before using session_name('newname'). The fact that it does not do that is a bug. Few people spotted it is simply because they generally want to do one or the other, but rarely both at the same time. The reason that I want to change the session name is that when I have a particular part of my enterprise application open in one browser window I sometimes want to open a second browser window (or even a third) so that I can look at another part of my application at the same time. In Internet Explorer the Ctrl+K key combination will produce a clone of the current tab in another tab. However, at this point they are both using the same session name and id, so I have a hyperlink on the screen which executes the following code: session_start(); // this uses the old name and id ... do stuff session_name('newname'); session_regenerate_id(); session_write_close(); … restart script so that it uses the new session name and old, … but leaves the old one alone. Since PHP 4 all the way up to 7.1 this worked as advertised. Since 7.2 the call to session_name('newname') does NOT change the session name because somebody decided that it was not proper to do so while a session was already active. That opinion differed from the documentation, therefore that opinion was wrong. The fact that I can workaround this newly generated BC break by moving a single line of code is not the issue. The important fact is that this BC break happened WITHOUT WARNING and without ever being documented or appearing in any change logs. I think that it is a sad day when somebody can decide that the documented behaviour of a 20 year old function does not fit it with their beliefs, so they go ahead and change it without following the correct procedure - raise RFC, discuss it on the internals list, then put it to a vote. If any Tom, Dick or Harry can now insert a BC break at any time without warning, then that sounds the death knell for the language. It will become so unreliable it will become unusable for anyone who expects to build an application with a long life.These are the five code samples that Yasuo sent me as "proof" of the broken behaviour with the session functions which his fix supposedly cures. Below each example is my response which shows that the problem actually lies with the code that calls those functions and not the functions themselves. Example #1 - Wrong write and/or crash> <?php session_start(); session_name('new_name'); session_commit(); // Save handler can write session data to wrong storage. There is no such thing as "wrong" storage in this case as session_commit() does NOT reference $session_name when calling the write() method in the session handler, it uses $session_id. This code does not change $session_id so the session data is put back in the same place from where it was read. Example #2 - Wrong name returned <?php session_start(); session_name('new_name'); // somewhere in the code $my_current_session_name = session_name(); // Wrong session name. session_start() uses old one. // This behavior can cause bug when user is distributing session storage accesses by session name. There are a number of glaring mistakes here: - Changing the value of session.name does not take effect until the next call to session_start(). When a session is started the value of session.name is provided in the $session_name argument in the open() method in the session handler. - No method or function has ever been provided which will return the value of $session_name which was used in the call to open(). - If the value of session.name is changed while a session is active that change is not communicated with the session handler and does not affect the session handler in any way as all read() and write() operations are performed using the $session_id. - If the session name is used to change the value in $save_path then it should be done in the open() method in the session handler where both $save_path and $session_name are provided as arguments. If these values need to be used in other methods then they should be stored as class properties and accessed using $this->varname. Example #3 - Wrong write and/or crash. Pattern 2. <?php session_start(); session_name('new_name'); // somewhere in the code session_regenerate_id(); // Save handler can write session data to wrong storage. // In worst cases, PHP crashes ?> Bad usage again. session_regenerate_id() will regenerate a new id for the CURRENT session, but this will be linked with the value of session.name which was available when the current session was started. The value 'new_name' will not take effect until the next call to session_start(), just as the manual says. Example #4 - Wrong write and/or crash. Pattern 3. <?php session_start(); session_name('new_name'); session_write(); // Save handler can write session data to wrong storage. // In worst cases, PHP crashes ?> This is the same as Example #1. Example #5 - Wrong write and/or crash. Pattern 4. + Bogus session_name() call. <?php session_start(); session_name('new_name'); // Save handler can write session data to wrong storage at the end of script execution. // In worst cases, PHP crashes // In addition, user wouldn't notice bogus session_name() call if there is no error. ?> This is a duplicate of #1 and #4. The session is started with a particular $session_id, and as that $session_id is never changed any updates to that session data will be written back using the same $session_id. A change in $session_name does not change the $session_id. The $session_name and $session_id are different entities which are accessed using different functions. They are only brought together when the cookie is accessed, which is either by session_start() or session_regenerate_id(). This code does nothing to cause 'new_name' to be written out as a cookie, therefore it simply disappears.