diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 692f91e95c..83fe717f0d 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -166,7 +166,7 @@ class ChoiceType extends AbstractType $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance - $hash = md5(json_encode(array($choices, $options['preferred_choices']))); + $hash = hash('sha256', serialize(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 3da49dfa6a..2e99c2c774 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1216,6 +1216,47 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase )); } + // https://github.com/symfony/symfony/issues/10409 + public function testReuseNonUtf8ChoiceLists() + { + $form1 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => chr(181).'meter', + ), + )); + + $form2 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => chr(181).'meter', + ), + )); + + $form3 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => null, + ), + )); + + // $form1 and $form2 use the same ChoiceList + $this->assertSame( + $form1->getConfig()->getOption('choice_list'), + $form2->getConfig()->getOption('choice_list') + ); + + // $form3 doesn't, but used to use the same when using json_encode() + // instead of serialize for the hashing algorithm + $this->assertNotSame( + $form1->getConfig()->getOption('choice_list'), + $form3->getConfig()->getOption('choice_list') + ); + } + public function testInitializeWithDefaultObjectChoice() { $obj1 = (object) array('value' => 'a', 'label' => 'A');