Unset referenced variables after foreach loops

Created on 21 July 2023, 11 months ago
Updated 12 September 2023, 10 months ago

Using sonarqube to review out code we have this "crital" warning:

"Make sure that the referenced value variable is unset after the loop"

in views/plugins/views_wizard/views_ui_base_views_wizard.class.php

            foreach ($path_fields as &$field) {
              $field['id'] = view::generate_item_id($field['id'], $display_options['default']['fields']);
              $display_options['default']['fields'][$field['id']] = $field;
            }

When a reference is used in a foreach loop instead of using a simple variable, the reference remains assigned and keeps its "value" which is a reference, even after the foreach execution. Most of the time, this is not what the developer is expecting and the reference may be used wrongly in the rest of the code. For this reason, it is recommended to always unset a reference that is used in a foreach to avoid any unexpected side effects.

Noncompliant Code Example

$arr = array(1, 2, 3);
foreach ($arr as &$value) { // Noncompliant; $value is still alive after the loop and references the last item of the array: $arr[2]
    $value = $value * 2;
}
$value = 'x';
Compliant Solution
$arr = array(1, 2, 3);
foreach ($arr as &$value) { // Compliant; there is no risk to use by mistake the content of $value pointing to $arr[2]
    $value = $value * 2;
}
unset($value);
$value = 'x';
🐛 Bug report
Status

Fixed

Version

3.0

Component

Code

Created by

🇪🇸Spain Carlitus

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Carlitus
  • Open in Jenkins → Open on Drupal.org →
    Core: 7.x + Environment: PHP 8.0 & MySQL 5.7
    last update 11 months ago
    run-tests.sh exception
  • @carlitus opened merge request.
  • Status changed to Needs review 11 months ago
  • Status changed to Needs work 11 months ago
  • 🇺🇸United States DamienMcKenna NH, USA

    That looks like a useful tiny improvement, thank you for putting it together.

    There's a tiny issue with the change - the indenting is incorrect, please re-save the change using two spaces for each indent so that it lines up correctly? Thank you.

  • Open in Jenkins → Open on Drupal.org →
    Core: 7.x + Environment: PHP 8.0 & MySQL 5.7
    last update 11 months ago
    run-tests.sh exception
  • Open in Jenkins → Open on Drupal.org →
    Core: 7.x + Environment: PHP 8.0 & MySQL 5.7
    last update 11 months ago
    run-tests.sh exception
  • 🇪🇸Spain Carlitus

    Sorry for the wrong indenting, i think was a nano thing. Now i've made it with phpstorm and it seems right.

  • Status changed to Needs review 11 months ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 7.x + Environment: PHP 8.0 & MySQL 5.7
    last update 11 months ago
    234 pass
  • 🇺🇸United States DamienMcKenna NH, USA

    Let's extend this to fix similar issues in other parts of the codebase:

    grep -r foreach|grep \&
    ./views_ui.module:  foreach ($plugins['display'] as &$display) {
    ./plugins/views_wizard/views_ui_base_views_wizard.class.php:            foreach ($path_fields as &$field) {
    ./plugins/views_wizard/views_ui_base_views_wizard.class.php:    foreach ($display_options as &$options) {
    ./plugins/views_wizard/views_ui_base_views_wizard.class.php:        foreach ($display_options['default']['fields'] as &$field) {
    ./plugins/views_plugin_style.inc:      foreach ($classes as &$class) {
    ./plugins/views_plugin_display.inc:      foreach ($filters as &$filter) {
    ./includes/admin.inc:    foreach ($new_fields as &$new_field) {
    ./includes/admin.inc:  foreach ($rows as &$row) {
    ./views.api.php:    foreach ($query->where as &$condition_group) {
    ./views.api.php:      foreach ($condition_group['conditions'] as &$condition) {
    ./views.api.php:  foreach ($commands as &$command) {
    ./theme/theme.inc:        foreach ($vars['rows'] as $num => &$column_items) {
    ./modules/comment/views_plugin_row_comment_rss.inc:    foreach ($this->comments as &$comment) {
    ./modules/field/views_handler_field_field.inc:      foreach ($values as $row_id => &$value) {
    ./modules/search/views_handler_filter_search.inc:        foreach ($condition_conditions as $key => &$condition) {
    ./modules/search/views_handler_filter_search.inc:      foreach ($conditions as $key => &$subcondition) {
    ./modules/search/views_handler_argument_search.inc:        foreach ($condition_conditions as $key => &$condition) {
    ./modules/system/views_handler_argument_file_fid.inc:    foreach ($titles as &$title) {
    ./modules/comment.views.inc:    foreach ($build as $cid => &$comment_build) {
    ./handlers/views_handler_field.inc:    foreach ($classes as &$class) {
    ./handlers/views_handler_field.inc:    foreach ($classes as &$class) {
    ./handlers/views_handler_field.inc:    foreach ($classes as &$class) {
    ./handlers/views_handler_filter_entity_bundle.inc:      foreach ($this->value as &$value) {
    ./handlers/views_handler_relationship_groupwise_max.inc:    foreach ($conditions as $condition_id => &$condition) {
    ./help/api-forms.html:    foreach ($this->view->result as $row_id => $row) {
    ./views.module:  foreach ($conditions as $condition_id => &$condition) {
    
  • 🇺🇸United States DamienMcKenna NH, USA

    @Carlitus: can you please review the new patch and let me know what you think? Thank you.

  • 🇪🇸Spain Carlitus

    Hi,

    I have checked it and I see everything is fine

    The only thing is that I have seen some unused instances in the foreach keys, but maybe this is another minor issue.

    comment.views.inc

    line 708

        foreach ($build as $cid => &$comment_build) {
          if (isset($comment_build['links'])) {
            unset($comment_build['links']);
          }
        }
        unset($comment_build);
    

    theme.inc

            foreach ($vars['rows'] as $num => &$column_items) {
              unset($column_items[$column]);
              unset($vars['header'][$column]);
            }
            unset($column_items);
    
  • Status changed to RTBC 10 months ago
  • 🇺🇸United States DamienMcKenna NH, USA

    I think it'd be better to do that cleanup separately.

  • Status changed to Fixed 10 months ago
  • 🇺🇸United States DamienMcKenna NH, USA

    Committed.

  • 🇺🇸United States DamienMcKenna NH, USA
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.69.0 2024