Bug #79076 [NEW]: Unexpected Result when
| From: | ptmp727 at gmail dot com | Date: | Wed, 08 Jan 2020 02:22:56 +0000 |
| Subject: | Bug #79076 [NEW]: Unexpected Result when | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-224762@lists.php.net to get a copy of this message | ||
From: ptmp727 at gmail dot com
Operating system: macOS
PHP version: 7.3.13
Package: Session related
Bug Type: Bug
Bug description:Unexpected Result when
Description:
------------
This is the first time I am doing this. I am completing a project for
University so I am not very experienced so please accept my apologies if
I do not follow the proper protocol. Happy to provide any other
information.
Basically I am creating a module based MVC style framework with will
also work as a single page app and I have finally managed to get
everything to work.
I am using DOMDocument for templating and it is RUNNING UNEXPECTED CODE
and causing the script to produce bizarre results by deleting session
variables at runtime.
The app logic is very symmetric and follows the basic structure and
pseudocode:
app init,
validate request,
auth form function: All request methods except for 'GET' must have a
token and a form id field set in the session and must match.
If the request is get and if the session tokens are set, delete the
tokens (Ensures tokens are refreshed on every request), *** This is the
point of the bug ***
If Valid,
Request object uses the router to dispatch the request to a module class
and a method responses.
Now In this example we are using the /login route which has a form
component login,
Here is what is happening:
1) Initial request comes in for /login,
2) Request URL Is sanitized and Validated,
3) Auth::form() function is called:
Check if Request method is NOT 'GET',
If true validate the form,
ElseIf Session Tokens are set, delete them (Ensuring that tokens can be
regenerated on a new request)
works normally as the method is get and no tokens are set yet, the
function does not throw any errors (as expected)
4) Request is routed to the AuthModule and the login method
5) Login method uses a function to generate random token and save it in
the session and returns the login component,
6) Token is added to hidden form field
7) I use DOMDocument object to get the main template and append the
login component to the root element by cloning the node.
8) Whole response sent to browser.
//So far works as expected,
Now!
9) On Form submission,
An exception is thrown stating that the form token has not been set in
the session,
Even though I have verified that the session variable is valid and set
before the app terminates.
The request lifecycle of sending the form component works perfectly and
all session variables are set (checked by testing the session super
global in the app destructor method), but somehow on the next request
when the form is submitted, the form tokens are disappearing from the
session.
Some How point 3 else if condition even though evaluates to false, the
unset($_SESSION['tokens']) line of code SOMEHOW RUNS, I CANT UNDERSTAND
FOR THE LIFE OF ME.
If I uncomment the line of code which unsets the session, EVERYTHING
WORKS FINE
Also If I do not use the Dom document for templating and simply send the
component back there is no error.
Code samples:
//Checking the session variables at the start of the script
//Undefined variable notice
var_dump($_SESSION['tokens']);
//Foundation function calls the Auth::form function which checks the
tokens:
$app->foundation(function ($request, $response){
$response->capture(
$request->route()
);
});
//Auth class has a form function
public static function form(){
if($_SERVER['REQUEST_METHOD'] != 'GET'){
//Code to validate and check tokens here!
}elseif(asset($_SESSION['tokens'])){
//This line of code somehow runs even though the else if
condition fails,
//This problem only happens when I am using DOM Document for
templating
unset($_SESSION['tokens']);
}
}
//AuthModule class:
class AuthModule extends Module{
public function login(){
$token = Form::token('login'); //Creates session tokens
return $this->component('login.php', ['token' => $token]);
}
}
//Testing code in index.php at the end of the main app object destructor
method which shows session:
class App{
function __destruct(){
var_dump($_SESSION['tokens']);//Shows session variables
perfectly!
}
}
//At the start of the script:
//Checking the session variables at the start of the script
//Undefined variable notice
var_dump($_SESSION['tokens']);
Just to reiterate this problem only happens when using DOMDocument
templating, where I have to use:
libxml_use_internal_errors(true); and libxml_use_internal_errors(false);
to suppress errors.
I am sorry I do have a GitHub account but I did not want to upload the
project before it is ready, but for the purpose of testing I can upload
to GitHub,
I am working on my localhost so Im not sure how I can share my app and
project,
I do not have a URL yet,
If I uncomment the line of code in the Auth::form function which unsets
the session, some how the session tokens are not deleted.
I cannot understand why this is happening, especially as the unset line
of code has not even ran yet and the condition never evaluates to true
as the tokens are somehow never set in the session at run-time for the
next request after being set properly
PHP Version: 7.3.8,
ENV: Mac MAMP PRO
If anyone can provide an email, I am happy
Test script:
---------------
public function set_response()
{
$html = new HTMLDom($this->response);
$domelem = $html->body->firstChild;
$cloned = $this->importNode($domelem, true);
$this->app_root->appendChild($cloned);
$this->save_html();
}
public function capture($response)
{
if ($response === false) {
$this->not_found();
}elseif (is_string($response)) {
$dom = new MapDom($response);
$dom->set_response();
$this->response = $dom->get_response();
//When not using domdocument, it works perfectly:
//$this->response = $response;
}
}
Expected result:
----------------
The Session variables set in the previous request should be set at the
top of the script before the Auth::form deletes them (If they are set
and if the request method is get)
Actual result:
--------------
Session tokens are not defined at the top of the script.
--
Edit bug report at https://bugs.php.net/bug.php?id=79076&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=79076&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=79076&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=79076&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=79076&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=79076&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=79076&r=support
Expected behavior: https://bugs.php.net/fix.php?id=79076&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=79076&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=79076&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=79076&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=79076&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=79076&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=79076&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=79076&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=79076&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=79076&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=79076&r=mysqlcfg