Skip to content
/ form Public

Commit b32f51f

Browse files
hlecorchenicolas-grekas
authored andcommitted
[Form] Don't submit absent forms even when they have false_values children
In 8.1, #45081 made the request handlers call MissingDataHandler before checking whether the form was actually present in the request. For compound forms with false_values-aware children (expanded multiple ChoiceType, CheckboxType, ...), the handler synthesises values for the missing children, masking the "form absent" condition and causing the form to be submitted on any unrelated POST to the same endpoint. Move the early-return guard before MissingDataHandler::handle() so an absent form is never processed. Fixes #64315.
1 parent 2465bc6 commit b32f51f

3 files changed

Lines changed: 43 additions & 21 deletions

File tree

Extension/HttpFoundation/HttpFoundationRequestHandler.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ public function handleRequest(FormInterface $form, mixed $request = null): void
6161
} else {
6262
$queryData = $request->query->all()[$name] ?? $missingData;
6363

64-
$data = $this->missingDataHandler->handle($form, $queryData);
65-
66-
if ($missingData === $data) {
64+
if ($missingData === $queryData) {
6765
// Don't submit GET requests if the form's name does not exist
6866
// in the request
6967
return;
7068
}
69+
70+
$data = $this->missingDataHandler->handle($form, $queryData);
7171
}
7272
} else {
7373
// Mark the form with an error if the uploaded size was too large
@@ -98,15 +98,15 @@ public function handleRequest(FormInterface $form, mixed $request = null): void
9898
$files = null;
9999
}
100100

101-
if ('PATCH' !== $method) {
102-
$params = $this->missingDataHandler->handle($form, $params);
103-
}
104-
105101
if ($missingData === $params) {
106102
// Don't submit the form if it is not present in the request
107103
return;
108104
}
109105

106+
if ('PATCH' !== $method) {
107+
$params = $this->missingDataHandler->handle($form, $params);
108+
}
109+
110110
if (\is_array($params) && \is_array($files)) {
111111
$data = FormUtil::mergeParamsAndFiles($params, $files);
112112
} else {

NativeRequestHandler.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,14 @@ public function handleRequest(FormInterface $form, mixed $request = null): void
6767
$data = $_GET;
6868
} else {
6969
$queryData = $_GET[$name] ?? $missingData;
70-
$data = $this->missingDataHandler->handle($form, $queryData);
7170

72-
if ($missingData === $data) {
71+
if ($missingData === $queryData) {
7372
// Don't submit GET requests if the form's name does not exist
7473
// in the request
7574
return;
7675
}
76+
77+
$data = $this->missingDataHandler->handle($form, $queryData);
7778
}
7879
} else {
7980
// Mark the form with an error if the uploaded size was too large
@@ -109,15 +110,15 @@ public function handleRequest(FormInterface $form, mixed $request = null): void
109110
$files = null;
110111
}
111112

112-
if ('PATCH' !== $method) {
113-
$params = $this->missingDataHandler->handle($form, $params);
114-
}
115-
116113
if ($missingData === $params) {
117114
// Don't submit the form if it is not present in the request
118115
return;
119116
}
120117

118+
if ('PATCH' !== $method) {
119+
$params = $this->missingDataHandler->handle($form, $params);
120+
}
121+
121122
if (\is_array($params) && \is_array($files)) {
122123
$data = FormUtil::mergeParamsAndFiles($params, $files);
123124
} else {

Tests/AbstractRequestHandlerTestCase.php

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function testSubmitCheckboxInCollectionFormWithEmptyData($method)
7171
'method' => $method,
7272
]);
7373

74-
$this->setRequestData($method, []);
74+
$this->setRequestData($method, ['collection' => []]);
7575

7676
$this->requestHandler->handleRequest($form, $this->request);
7777

@@ -110,7 +110,7 @@ public function testSubmitCheckboxFormWithEmptyData($method)
110110
$form->get('subform')
111111
->add('checkbox', CheckboxType::class);
112112

113-
$this->setRequestData($method, []);
113+
$this->setRequestData($method, ['form' => []]);
114114

115115
$this->requestHandler->handleRequest($form, $this->request);
116116

@@ -156,18 +156,39 @@ public function testSubmitExpandedMultipleChoiceWithPartialDataDoesNotEmitArrayF
156156
$this->assertSame(['ROLE_USER'], $form->getData());
157157
}
158158

159+
#[DataProvider('methodProvider')]
160+
public function testDoNotSubmitAbsentNamedFormWithCheckboxesWhenRequestBodyContainsOtherData($method)
161+
{
162+
$form = $this->factory->createNamed('form', FormType::class, null, ['method' => $method])
163+
->add('displayedColumns', ChoiceType::class, [
164+
'choices' => ['foo' => 'foo', 'bar' => 'bar'],
165+
'expanded' => true,
166+
'multiple' => true,
167+
]);
168+
169+
$this->setRequestData($method, ['other_field' => 'value']);
170+
171+
$this->requestHandler->handleRequest($form, $this->request);
172+
173+
$this->assertFalse($form->isSubmitted());
174+
}
175+
159176
#[DataProvider('methodExceptPatchProvider')]
160-
public function testSubmitSimpleCheckboxFormWithEmptyData($method)
177+
public function testSubmitNamedFormWithMissingCheckboxesWhenFormKeyIsPresentInRequest($method)
161178
{
162-
$form = $this->factory->createNamed('checkbox', CheckboxType::class, true, [
163-
'method' => $method,
164-
]);
179+
$form = $this->factory->createNamed('form', FormType::class, null, ['method' => $method])
180+
->add('displayedColumns', ChoiceType::class, [
181+
'choices' => ['foo' => 'foo', 'bar' => 'bar'],
182+
'expanded' => true,
183+
'multiple' => true,
184+
]);
165185

166-
$this->setRequestData($method, []);
186+
$this->setRequestData($method, ['form' => []]);
167187

168188
$this->requestHandler->handleRequest($form, $this->request);
169189

170-
$this->assertFalse($form->getData());
190+
$this->assertTrue($form->isSubmitted());
191+
$this->assertSame([], $form->get('displayedColumns')->getData());
171192
}
172193

173194
public static function methodExceptPatchProvider(): array

0 commit comments

Comments
 (0)