8000 Form rendering throws notice if the form is submitted with array instead of string · Issue #23995 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Form rendering throws notice if the form is submitted with array instead of string #23995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mhujer opened this issue Aug 26, 2017 · 11 comments
Closed
Labels

Comments

@mhujer
Copy link
Contributor
mhujer commented Aug 26, 2017
Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.3.6

When the user uses Chrome Inspect feature and changes the <input type="text" name to include an extra array (e.g. from article_form[title] to article_form[title][foobar], the form fails to render. The reason is that the template is trying to render the "invalid" array as an <input> value.

Twig_Error_Runtime:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion").

  at vendor\symfony\symfony\src\Symfony\Bridge\Twig\Resources\views\Form\form_div_layout.html.twig:13
  at Twig_Template->displayBlock('form_widget_simple', array('value' => array('foo' => 'aa'), 'attr' => array(), 'form' => object(FormView), 'id' => 'article_form_title', 'name' => 'title', 'full_name' => 'article_form[title]', 'disabled' => false, 'label' => 'Article title', 'label_format' => null, 'multipart' => false, 'block_prefixes' => array('form', 'text', '_article_form_title'), 'unique_block_prefix' => '_article_form_title', 'translation_domain' => null, 'cache_key' => '_article_form_title_text', 'errors' => object(FormErrorIterator), 'valid' => false, 'data' => array('foo' => 'aa'), 'required' => true, 'size' => null, 'label_attr' => array(), 'compound' => false, 'method' => 'POST', 'action' => '', 'submitted' => true, 'app' => object(AppVariable)), array('form_widget' => array(object(__TwigTemplate_74fc98e978cb4218b308d1fa4d08196af014f2b1069a5f65da3ed6ecc38bdf83), 'block_form_widget'),
...

The problematic line in the template is this:

<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>

The simplest repro-case I managed to create is this one:

    public function createAction()
    {

        $form = $this->createFormBuilder(
            [
                'title' => [
                    'foo' => 'bar',
                ],
            ])
            ->add('title', TextType::class)
            ->getForm();

        return $this->render('article/add-article.html.twig', [
            'form' => $form->createView(),
        ]);
    }
# article/add-article.html.twig
{% block body %}
	{{ form(form) }}
{% endblock %}
@linaori
Copy link
Contributor
linaori commented Aug 26, 2017

So that means the page would result in a 500 error because the user is messing with the HTML?

8000
@mhujer mhujer changed the title Form rendering fails if the form is submitted with array instead of string Form rendering throws notice if the form is submitted with array instead of string Aug 26, 2017
@mhujer
Copy link
Contributor Author
mhujer commented Aug 26, 2017

No, I jumped to conclusion too fast. It only reports a notice. Which is converted to exception in dev mode.

In prod mode it converts the data to string Array:
image

It happens also on the Symfony.com: http://symfony.com/search?q[foo]=form.

But if the developer forgets to add @Assert\Type(type="string"), the form may validate just fine and pass the array further in the app. Which may actually be happening - the Symfony web searches for term Array.

(I checked several webapps and most of them are prone to this issue)

@ogizanagi ogizanagi added the Form label Aug 26, 2017
@sstok
Copy link
Contributor
sstok commented Aug 26, 2017

I'm not entirely sure how we can fix this this properly, we could add a safe guard in the themes (which will not fix this issue for custom themes).

Or we can add a transformer to ensure if a none scalar value is provided it's transformed to an empty string. But this could be considered a BC break as some may have added additional transformer(s) that expect this kind of behavior 🤔

@mhujer
Copy link
Contributor Author
mhujer commented Aug 26, 2017

@iltar I'm afraid I found a case when it fails with 500.

Can someone please check that I haven't overlooked something?

When there is another assert - such as @Assert\Email() or @Assert\Length(min="10", max="100") which expects string-ish value, they do this check:

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

So if the $value is of type array, exception is throw and the error page is rendered.

The Type validator is called (if it is before other validators - such as in the example bellow), but it does not prevent the other validators from being called.

Symfony\Component\Validator\Exception\UnexpectedTypeException:
Expected argument of type "string", "array" given

  at vendor\symfony\symfony\src\Symfony\Component\Validator\Constraints\LengthValidator.php:37
  at Symfony\Component\Validator\Constraints\LengthValidator->validate(array('foo' => 'aaaa'), object(Length))
     (vendor\symfony\symfony\src\Symfony\Component\Validator\Validator\RecursiveContextualValidator.php:850)
  at Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateInGroup(array('foo' => 'aaaa'), null, object(GenericMetadata), 'Default', object(ExecutionContext))
     (vendor\symfony\symfony\src\Symfony\Component\Validator\Validator\RecursiveContextualValidator.php:696)
  at Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateGenericNode(array('foo' => 
...

Case for reproduction (you need to change input name from form[title] to form[title][foo]:

    public function createyAction(Request $request)
    {
        $form = $this->createFormBuilder()
            ->add('title', TextType::class, [
                'constraints' => [
                    new Type('string'),
                    new Length(['min' => 10]),
                ],
            ])
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            //foo
        }

        return $this->render('article/add-article.html.twig', [
            'form' => $form->createView(),
        ]);
    }
# article/add-article.html.twig
{% block body %}
	{{ form(form) }}
{% endblock %}

@mhujer
Copy link
Contributor Author
mhujer commented Aug 26, 2017

Related: #14943 and #20935

@linaori
Copy link
Contributor
linaori commented Aug 26, 2017

Honestly, if a user messes with the input fields, a 500 is justified. Won't have to expect valid responses if you send invalid requests

@mhujer
Copy link
Contributor Author
mhujer commented Aug 27, 2017

For me it seems unexpected from the DX point-of-view: If the proper @Assert\Type() annotations are added, it should work like any other validation.

And I think it may be possible to flood the server logs with this error.

@techi602
Copy link

@iltar you can not justify error 500 for unhandled user input validation (error 400 bad request would be more suitable in this case - yet still embarrassing for simple form validation)
Imagine hackbots which will spam your application error logs with random input field names.

@ianmclaughlin
Copy link

HTTP 400 (Bad Request) is for client errors, so it's inappropriate to return 500

Our logs are being filled with exceptions which don't need to be thrown

@Tobion
Copy link
Contributor
Tobion commented Oct 11, 2017

Related #4102

@xabbuh
Copy link
Member
xabbuh commented Sep 23, 2018

closing in favour of #4102

@xabbuh xabbuh closed this as completed Sep 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants
0