From e62c0b5a2d9633e1c229bfec23beaf3a87a6e425 Mon Sep 17 00:00:00 2001 From: Chekote Date: Mon, 10 Feb 2014 15:46:13 -0600 Subject: [PATCH] Fix "Array was modified outside object" in ResizeFormListener. The onSubmit() method of the ResizeFormListener class is assuming the data is an array, and calling unset directly inside a foreach. This works fine in most scenarios, but if data is an instance of IteratorAggregate, it breaks with the following error: Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener::onSubmit(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in ./vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php line 142 This is because the foreach loop is using an Iterator in the background, but the ResizeFormListener has unset the underlying data directly, causing the Iterator and data to be out of sync. When the data is an instance of IteratorAggregate, the loop should use the iterator directly and not rely on foreach. The onSubmit method has been updated accordingly. --- .../Core/EventListener/ResizeFormListener.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index f1c39db245..d2b13e4a96 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -139,9 +139,21 @@ class ResizeFormListener implements EventSubscriberInterface // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { - foreach ($data as $name => $child) { - if (!$form->has($name)) { - unset($data[$name]); + if ($data instanceof \IteratorAggregate) { + $iter = $data->getIterator(); + while ($iter->valid()) { + $name = $iter->key(); + if ($form->has($name)) { + $iter->next(); + } else { + $iter->offsetUnset($name); + } + } + } else { + foreach ($data as $name => $child) { + if (!$form->has($name)) { + unset($data[$name]); + } } } }