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

Created on 20 July 2023, 11 months ago
Updated 21 July 2023, 11 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 field_collection.entity.inc

if (($entity = $this->hostEntity()) && isset($entity->{$this->field_name})) {
      foreach ($entity->{$this->field_name} as $langcode => &$data) {
        if (!empty($data)) {
          foreach ($data as $delta => $item) {
            if (isset($item['value']) && $item['value'] == $this->item_id) {
              $this->langcode = $langcode;
              return $delta;
            }

            if (isset($item['entity']) && $item['entity'] === $this) {
              $this->langcode = $langcode;
              return $delta;
            }
          }
        }
      }
      // If we don't find the delta in the current values (cause the item
      // is being deleted, for example), we search the delta in the originalcontent.
      if (!empty($entity->original)) {
        foreach ($entity->original->{$this->field_name} as $langcode => &$data) {
          if (!empty($data)) {
            foreach ($data as $delta => $item) {
              if (isset($item['value']) && $item['value'] == $this->item_id) {
                $this->langcode = $langcode;
                return $delta;
              }

              if (isset($item['entity']) && $item['entity'] === $this) {
                $this->langcode = $langcode;
                return $delta;
              }
            }
          }
        }
      }

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

Needs review

Version

1.2

Component

Code

Created by

πŸ‡ͺπŸ‡ΈSpain Carlitus

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

Comments & Activities

Production build 0.69.0 2024