Problem/Motivation
Cron.php
does not check for maintenance mode correctly and causes drupal_deliver_html_page()
to call drupal_render_page()
with an integer argument under some circumstances.
The problem is when a site has a custom 403 page set, maintenance mode is active and cron.php
is accessed.
1. cron.php
will call drupal_access_denied()
.
2. drupal_access_denied()
will call drupal_deliver_html_page()
.
3. And drupal_deliver_html_page()
will fail to recognize the maintenance mode, as the $return
variable will have a value of MENU_SITE_OFFLINE
:
case MENU_ACCESS_DENIED:
// Print a 403 page.
drupal_add_http_header('Status', '403 Forbidden');
watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
// Make sure that the current path is not interpreted as external URL.
if (!url_is_external($_GET['q'])) {
$_GET['destination'] = $_GET['q'];
}
}
$path = drupal_get_normal_path(variable_get('site_403', ''));
if ($path && $path != $_GET['q']) {
// Custom 403 handler. Set the active item in case there are tabs to
// display or other dependencies on the path.
menu_set_active_item($path);
$return = menu_execute_active_handler($path, FALSE);
}
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
// Standard 403 handler.
drupal_set_title(t('Access denied'));
$return = t('You are not authorized to access this page.');
}
print drupal_render_page($return);
break;
This will cause errors:
Cannot use a scalar value as an array block.module:271
Invalid argument supplied for foreach() common.inc:6594
Cannot use a scalar value as an array common.inc:6051
Cannot use a scalar value as an array common.inc:6106
Steps to reproduce
Start with a clean site (ie. minimal profile), then:
- Switch on maintenance_mode
drush vset maintenance_mode 1
- Set a custom access denied page
drush vset site_403 'non-empty'
- Access the cron.php of your site
curl https://example.com/cron.php
The result is this set of errors:
Cannot use a scalar value as an array block.module:271
Invalid argument supplied for foreach() common.inc:6594
Cannot use a scalar value as an array common.inc:6051
Cannot use a scalar value as an array common.inc:6106
Depending on what othen modules you have activated there might be even more errors.
Proposed resolution
Fix the conditions in cron.php
to return drupal_site_offline()
instead of drupal_access_denied()
when the maintenance mode is active.
==== Original report ====
Summary
In drupal_deliver_html_page()
in some circumstances menu_execute_active_handler()
is called and its return value is directly passed to drupal_render_page()
even if it is an integer
Steps to reproduce
Start with a clean site (ie. minimal profile), then:
- Switch on maintenance_mode
drush vset maintenance_mode 1
- Set a custom access denied page
drush vset site_403 'non-empty'
- Access the cron.php of your site
curl https://example.com/cron.php
The result is this set of errors:
Cannot use a scalar value as an array block.module:271
Invalid argument supplied for foreach() common.inc:6594
Cannot use a scalar value as an array common.inc:6051
Cannot use a scalar value as an array common.inc:6106
Depending on what othen modules you have activated there might be even more errors.
Analysis
drupal_deliver_html_page()
checks only for MENU_NOT_FOUND
and MENU_ACCESS_DENIED
before passing the value to drupal_render_page()
. This is not sufficent.
Proposed solution
Check for is_int($return)
instead of just specific integers.