Closed
Description
Description
I think I've found a regression that was introduced in php-8.1.18. The following test case completes in 8.1.17, but hangs silently in 8.1.18 or any greater version. The use case is that I'm going through a really large render array in Drupal and leaving bread crumbs so that I can later find them in a RecursiveCallbackFilterIterator
to break out of infinite loops.
The following simplified test case:
<?php
class RecursiveFilterTest {
public function traverse(array $variables): array {
$array_iterator = new \RecursiveArrayIterator($variables);
$filter_iterator = new \RecursiveCallbackFilterIterator($array_iterator, [
$this, 'isCyclic',
]);
$recursive_iterator = new \RecursiveIteratorIterator($filter_iterator, \RecursiveIteratorIterator::SELF_FIRST);
$recursive_iterator->setMaxDepth(20);
foreach ($recursive_iterator as $value) {
// Does stuff here...
// Avoid recursion by marking where we've been.
if (\is_object($value)) {
$value->{'#override_mode_breadcrumb'} = TRUE;
}
if (\is_array($value)) {
$value['#override_mode_breadcrumb'] = TRUE;
}
}
return \iterator_to_array($recursive_iterator);
}
public function isCyclic($current, string $key, \RecursiveArrayIterator $iterator): bool {
// Skip closures.
if ($current instanceof \Closure) {
return FALSE;
}
########### Debugging code ################
static $i = 0;
$i++;
if (is_array($current)) {
// When $i > 319 calling isset causes the process to hang and you have to restart the webserver to get out of it.
$this_fails = isset($current['#override_mode_breadcrumb']);
}
###########################################
// Avoid infinite loops by checking if we've been here before.
// e.g. View > query > view > query ...
if (\is_array($current) && isset($current['#override_mode_breadcrumb'])) {
return FALSE;
}
if (\is_object($current) && isset($current->{'#override_mode_breadcrumb'})) {
return FALSE;
}
return TRUE;
}
}
$classes_removed_variables = unserialize('a:17:{s:7:"element";a:45:{s:5:"#type";s:6:"select";s:8:"#options";a:1:{s:16:"Other workspaces";a:3:{s:36:"eb57d455-4dba-4f29-a356-1ef8d75f976f";s:17:"Foundation Models";s:36:"7d3bd93b-f1c5-439a-a60b-fce9fddcf516";s:9:"John Test";s:5:"stage";s:5:"Stage";}}s:14:"#default_value";s:0:"";s:11:"#attributes";a:5:{s:8:"onchange";s:19:"this.form.submit();";s:20:"data-drupal-selector";s:17:"edit-workspace-id";s:5:"class";a:1:{i:0;s:11:"form-select";}s:2:"id";s:17:"edit-workspace-id";s:4:"name";s:12:"workspace_id";}s:19:"#wrapper_attributes";a:1:{s:5:"class";a:1:{i:0;s:16:"container-inline";}}s:6:"#input";b:1;s:9:"#multiple";b:0;s:13:"#sort_options";b:0;s:11:"#sort_start";i:0;s:8:"#process";a:4:{i:0;a:2:{i:0;s:33:"Drupal\\Core\\Render\\Element\\Select";i:1;s:13:"processSelect";}i:1;a:2:{i:0;s:33:"Drupal\\Core\\Render\\Element\\Select";i:1;s:15:"processAjaxForm";}i:2;a:2:{i:0;s:45:"Drupal\\inline_form_errors\\RenderElementHelper";i:1;s:14:"processElement";}i:3;a:2:{i:0;s:38:"Drupal\\bootstrap\\Plugin\\ProcessManager";i:1;s:7:"process";}}s:11:"#pre_render";a:2:{i:0;a:2:{i:0;s:33:"Drupal\\Core\\Render\\Element\\Select";i:1;s:15:"preRenderSelect";}i:1;a:2:{i:0;s:40:"Drupal\\bootstrap\\Plugin\\PrerenderManager";i:1;s:9:"preRender";}}s:6:"#theme";s:6:"select";s:15:"#theme_wrappers";a:1:{i:0;s:12:"form_element";}s:15:"#value_callback";a:2:{i:0;s:33:"Drupal\\Core\\Render\\Element\\Select";i:1;s:13:"valueCallback";}s:8:"#context";a:0:{}s:5:"#icon";N;s:14:"#icon_position";s:6:"before";s:10:"#icon_only";b:0;s:16:"#defaults_loaded";b:1;s:5:"#tree";b:0;s:8:"#parents";a:1:{i:0;s:12:"workspace_id";}s:14:"#array_parents";a:1:{i:0;s:12:"workspace_id";}s:7:"#weight";i:0;s:10:"#processed";b:1;s:9:"#required";b:0;s:14:"#title_display";s:6:"before";s:20:"#description_display";s:5:"after";s:7:"#errors";N;s:3:"#id";s:17:"edit-workspace-id";s:5:"#name";s:12:"workspace_id";s:6:"#value";s:0:"";s:15:"#ajax_processed";b:0;s:5:"#ajax";N;s:24:"#autocomplete_route_name";N;s:12:"#input_group";N;s:19:"#input_group_button";N;s:7:"#sorted";b:1;s:18:"#smart_description";b:0;s:6:"#cache";a:2:{s:4:"tags";a:0:{}s:7:"max-age";i:-1;}s:9:"#attached";a:0:{}s:9:"#children";s:0:"";s:16:"#render_children";b:1;s:10:"#has_error";b:0;s:13:"#field_prefix";N;s:13:"#field_suffix";N;}s:19:"theme_hook_original";s:6:"select";s:12:"title_prefix";a:0:{}s:12:"title_suffix";a:0:{}s:12:"db_is_active";b:1;s:8:"is_admin";b:1;s:9:"logged_in";b:1;s:9:"directory";s:49:"profiles/tacos/your_sites_profile/themes/my_theme";s:7:"options";a:2:{i:0;a:3:{s:8:"selected";b:1;s:4:"type";s:6:"option";s:5:"value";s:0:"";}i:1;a:3:{s:4:"type";s:8:"optgroup";s:5:"label";s:16:"Other workspaces";s:7:"options";a:3:{i:0;a:4:{s:8:"selected";b:0;s:4:"type";s:6:"option";s:5:"value";s:36:"eb57d455-4dba-4f29-a356-1ef8d75f976f";s:5:"label";s:17:"Foundation Models";}i:1;a:4:{s:8:"selected";b:0;s:4:"type";s:6:"option";s:5:"value";s:36:"7d3bd93b-f1c5-439a-a60b-fce9fddcf516";s:5:"label";s:9:"John Test";}i:2;a:4:{s:8:"selected";b:0;s:4:"type";s:6:"option";s:5:"value";s:5:"stage";s:5:"label";s:5:"Stage";}}}}s:8:"is_front";b:1;s:6:"#cache";a:1:{s:8:"contexts";a:1:{i:0;s:17:"url.path.is_front";}}s:5:"theme";a:30:{s:4:"name";s:8:"my_theme";s:4:"type";s:5:"theme";s:11:"description";s:21:"Sub-theme of houstons";s:7:"package";s:5:"Other";s:24:"core_version_requirement";s:10:"^8.8 || ^9";s:10:"base theme";s:8:"houstons";s:9:"libraries";a:1:{i:0;s:15:"my_theme/global";}s:18:"libraries-override";a:1:{s:14:"houstons/modal";s:14:"my_theme/modal";}s:7:"regions";a:15:{s:3:"top";s:11:"Top of Page";s:10:"navigation";s:10:"Navigation";s:22:"navigation_collapsible";s:24:"Navigation (Collapsible)";s:17:"navigation_search";s:17:"Navigation Search";s:4:"hero";s:11:"Hero Banner";s:6:"header";s:7:"Top Bar";s:11:"highlighted";s:11:"Highlighted";s:4:"help";s:4:"Help";s:7:"content";s:7:"Content";s:13:"sidebar_first";s:7:"Primary";s:14:"sidebar_second";s:9:"Secondary";s:10:"pre_footer";s:18:"Pre Footer Content";s:6:"footer";s:6:"Footer";s:8:"page_top";s:8:"Page top";s:11:"page_bottom";s:11:"Page bottom";}s:16:"libraries-extend";a:1:{s:29:"core/drupal.dialog.off_canvas";a:1:{i:0;s:19:"my_theme/off-canvas";}}s:20:"ckeditor_stylesheets";a:2:{i:0;s:43:"css/libraries/ckeditor/ckeditor-backend.css";i:1;s:35:"css/libraries/ckeditor/ckeditor.css";}s:17:"core_incompatible";b:0;s:9:"lifecycle";s:6:"stable";s:5:"mtime";i:1690914479;s:6:"engine";s:24:"component_library_engine";s:8:"features";a:5:{i:0;s:7:"favicon";i:1;s:4:"logo";i:2;s:17:"node_user_picture";i:3;s:20:"comment_user_picture";i:4;s:25:"comment_user_verification";}s:10:"screenshot";s:64:"profiles/tacos/your_sites_profile/themes/my_theme/screenshot.png";s:7:"version";N;s:3:"php";s:5:"7.3.0";s:16:"libraries_extend";a:0:{}s:18:"libraries_override";a:0:{}s:12:"dependencies";a:1:{i:0;s:8:"houstons";}s:14:"regions_hidden";a:2:{i:0;s:8:"page_top";i:1;s:11:"page_bottom";}s:3:"dev";b:0;s:10:"livereload";s:0:"";s:4:"path";s:49:"profiles/tacos/your_sites_profile/themes/my_theme";s:5:"title";s:23:"Your Sites Custom Theme";s:8:"settings";a:86:{s:5:"_core";a:1:{s:19:"default_config_hash";s:43:"EBskbP-6knEscPxbKQU9fI6FcAYffuwyrdEPRHD8LT4";}s:7:"favicon";a:4:{s:8:"mimetype";s:24:"image/vnd.microsoft.icon";s:4:"path";s:0:"";s:3:"url";s:62:"/profiles/tacos/your_sites_profile/themes/my_theme/favicon.ico";s:11:"use_default";i:1;}s:8:"features";a:4:{s:20:"comment_user_picture";b:1;s:25:"comment_user_verification";b:1;s:7:"favicon";i:1;s:17:"node_user_picture";b:0;}s:4:"logo";a:3:{s:4:"path";s:0:"";s:3:"url";s:0:"";s:11:"use_default";i:1;}s:7:"schemas";a:3:{s:9:"bootstrap";i:8000;s:8:"houstons";i:8000;s:8:"my_theme";i:8000;}s:15:"button_colorize";i:1;s:14:"button_iconize";i:1;s:11:"button_size";s:0:"";s:15:"fluid_container";i:0;s:28:"forms_has_error_value_toggle";i:1;s:24:"forms_required_has_error";i:0;s:24:"forms_smart_descriptions";i:1;s:37:"forms_smart_descriptions_allowed_tags";s:33:"b, code, em, i, kbd, span, strong";s:30:"forms_smart_descriptions_limit";s:3:"250";s:18:"image_lazy_loading";i:0;s:16:"image_responsive";i:1;s:11:"image_shape";s:0:"";s:14:"table_bordered";i:0;s:15:"table_condensed";i:0;s:11:"table_hover";i:1;s:13:"table_striped";i:1;s:16:"table_responsive";s:2:"-1";s:10:"breadcrumb";s:1:"1";s:15:"breadcrumb_home";i:0;s:16:"breadcrumb_title";i:0;s:14:"navbar_inverse";i:0;s:15:"navbar_position";s:10:"static-top";s:12:"region_wells";a:13:{s:10:"navigation";s:0:"";s:22:"navigation_collapsible";s:0:"";s:6:"header";s:0:"";s:11:"highlighted";s:0:"";s:4:"help";s:0:"";s:7:"content";s:0:"";s:13:"sidebar_first";s:0:"";s:14:"sidebar_second";s:0:"";s:6:"footer";s:0:"";s:3:"top";s:0:"";s:17:"navigation_search";s:0:"";s:4:"hero";s:0:"";s:10:"pre_footer";s:0:"";}s:13:"modal_enabled";i:1;s:22:"modal_jquery_ui_bridge";i:1;s:15:"modal_animation";i:1;s:14:"modal_backdrop";s:4:"true";s:17:"modal_focus_input";i:1;s:14:"modal_keyboard";i:1;s:17:"modal_select_text";i:1;s:10:"modal_show";i:1;s:10:"modal_size";s:0:"";s:15:"popover_enabled";i:1;s:17:"popover_animation";i:1;s:18:"popover_auto_close";i:1;s:17:"popover_container";s:4:"body";s:15:"popover_content";s:0:"";s:13:"popover_delay";s:1:"0";s:12:"popover_html";i:0;s:17:"popover_placement";s:5:"right";s:16:"popover_selector";s:0:"";s:13:"popover_title";s:0:"";s:15:"popover_trigger";s:5:"click";s:15:"tooltip_enabled";i:1;s:17:"tooltip_animation";i:1;s:17:"tooltip_container";s:4:"body";s:13:"tooltip_delay";s:1:"0";s:12:"tooltip_html";i:0;s:17:"tooltip_placement";s:9:"auto left";s:16:"tooltip_selector";s:0:"";s:15:"tooltip_trigger";s:5:"hover";s:12:"cdn_provider";s:0:"";s:11:"cdn_version";s:5:"3.4.1";s:9:"cdn_theme";s:0:"";s:22:"cdn_cache_ttl_versions";i:0;s:20:"cdn_cache_ttl_themes";i:0;s:20:"cdn_cache_ttl_assets";i:0;s:21:"cdn_cache_ttl_library";i:0;s:10:"cdn_custom";s:275:"https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.css https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.js https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js";s:18:"include_deprecated";i:0;s:28:"suppress_deprecated_warnings";i:0;s:5:"table";s:0:"";s:16:"use_classic_logo";i:0;s:19:"use_classic_favicon";i:0;s:24:"reset_http_request_cache";s:0:"";s:11:"navbar_dark";i:1;s:11:"font_weight";s:5:"heavy";s:19:"container_max_width";s:0:"";s:20:"navbar_space_between";i:1;s:18:"use_compact_search";i:0;s:17:"navbar_background";i:0;s:27:"navbar_background_screen_xs";s:0:"";s:27:"navbar_background_screen_sm";s:0:"";s:27:"navbar_background_screen_md";s:0:"";s:27:"navbar_background_screen_lg";s:0:"";s:27:"navbar_background_screen_xl";s:0:"";s:17:"navbar_full_width";i:0;s:20:"autocomplete_enhance";i:0;s:12:"navbar_color";s:4:"dark";s:19:"local_task_position";s:0:"";s:13:"navbar_sticky";N;}s:14:"has_glyphicons";b:1;s:12:"query_string";s:6:"ryrmpu";}s:11:"input_group";b:0;s:6:"prefix";N;s:6:"suffix";N;s:10:"is_multple";b:0;s:22:"theme_hook_suggestions";a:0:{}}');
$test_class = new RecursiveFilterTest();
$test_class->traverse($classes_removed_variables);
echo "Completed.\n";
Resulted in:
The system hangs silently and you have to restart the process to get it going again.
But I expected this output instead:
Completed.
The reason we think it's a PHP bug is because it seems to hang on isset($current['#override_mode_breadcrumb'])
. Similar things like empty cause it to hang too.
PHP Version
8.1.18
Operating System
No response