Problem/Motivation
Steps to reproduce the bug
- basic page request (without a destination argument) that results in 403 or 404 response
- default error page whose execution results in a call to drupal_goto()
Expected behavior: redirect to default error page
Actual behavior: redirect loop
This results in browser displaying something like the following:
The page isn't redirecting properly
Browser has detected that the server is redirecting the request for this address in a way that will never complete.
The code trail is as follows (for a 403 response):
menu_execute_active_handler()
- $router_item['access'] = FALSE;
- $page_callback_result = MENU_ACCESS_DENIED;
drupal_deliver_page()
drupal_deliver_html_page()
- case MENU_ACCESS_DENIED:
- $_GET['destination'] = $_GET['q'];
- above saves the invalid path to a key used later in drupal_goto()
- $path = drupal_get_normal_path(variable_get('site_403', ''));
- this $path is the default error page
- $return = menu_execute_active_handler($path, FALSE);
menu_execute_active_handler()
- drupal_alter('menu_site_status', $page_callback_result, $read_only_path);
- for the site that motivated this issue the error path is 'user/login'
user_menu_site_status_alter()
- because the user was logged in
- drupal_goto('user');
drupal_goto()
- if (isset($_GET['destination']) && !url_is_external($_GET['destination']))
- $destination = drupal_parse_url($_GET['destination']);
- $path = $destination['path'];
- and so we redirect to a known invalid path
Because drupal_deliver_html_page() set $_GET['destination'] to a page known to result in a 403 or 404 response, this causes a redirect loop. Why exactly would we want this code? Is there a use case for such? The comment on this statement reads:
Keep old path for reference, and to allow forms to redirect to it.
Why would a form want to redirect to a page known to result in a dead end? If we would like the path for reference, then put it in a different key in $_GET, not one that gets picked up by later code to hijack the whole error page handling process.
And lest someone question why the error path on a site is 'user/login' please do not let this interfere with understanding the bug in general sense (see "Steps to reproduce the bug" above).
Proposed resolution
Two choices:
- Remove the conditional block in drupal_deliver_html_page() that sets $_GET['destination'] to the known bad path.
- Set a different key in the $_GET array if the invalid path is truly needed for reference and let a contrib or custom module deal with it if desired in the call to
drupal_alter('drupal_goto', $path);.
Remaining tasks
Review, a test could be written, but not clear it is necessary.
User interface changes
None.
API changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | 2400511-4-check-destination_callback_result.patch | 2.76 KB | solotandem |
| #3 | 2400511-3-check-destination_callback_result.patch | 2.87 KB | solotandem |
| #1 | 2400511-1-check-destination_callback_result.patch | 2.24 KB | solotandem |
Comments
Comment #1
solotandem commentedAttached patch adds conditional logic to drupal_goto() that checks for new key in $_GET which indicates the callback result of the destination path. If result is bad, then do not override goto path with destination path.
Comment #3
solotandem commentedUnset the state variable when a valid menu callback is found.
Comment #4
solotandem commentedUpdated patch for drupal 7.38.
Comment #5
solide-echt commentedI can confirm this patch works with - at least for me using passwordless login and email registration - no negative side effects.
eric
Comment #6
cilefen commentedPlease can you expand the steps to reproduce in the issue summary. I think I understand them but not totally. An ordered list of instructions with examples would be great.
Comment #7
cilefen commentedPlease check if this is an issue with Drupal 8. If so, it must be fixed there first according to the backport policy. If it is, move it to branch 8.0.x-dev and tag it “Needs backport to D7”.
Comment #8
michfuer commentedThis is a related post https://drupal.stackexchange.com/questions/29384/direct-link-to-view-unp...
I verified this issues exists on
7.80using https://simplytest.me/Steps to reproduce are
/admin/config/system/site-informationto/user/loginThe reason I think this is still considered a bug is that core is actually trying to redirect to
/userviadrupal_goto('user');which the auth user does have access to. The outcome might not be ideal with a user served the /user page vs. a 403, but still that would be the behavior I would expect from the code.