8000 bug #24460 [Form] fix parsing invalid floating point numbers (xabbuh) · pierredup/symfony@aaa5999 · GitHub
[go: up one dir, main page]

Skip to content

Commit aaa5999

Browse files
committed
bug symfony#24460 [Form] fix parsing invalid floating point numbers (xabbuh)
This PR was merged into the 2.7 branch. Discussion ---------- [Form] fix parsing invalid floating point numbers | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#19854, symfony#22586 | License | MIT | Doc PR | Should make AppVeyor builds pass again. Code borrowed from `NumberToLocalizedStringTransformer`. Commits ------- 042eac4 [Form] fix parsing invalid floating point numbers
2 parents 2392798 + 042eac4 commit aaa5999

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ public function reverseTransform($value)
116116
return;
117117
}
118118

119+
$position = 0;
119120
$formatter = $this->getNumberFormatter();
120121
$groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
121122
$decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
@@ -129,18 +130,44 @@ public function reverseTransform($value)
129130
$value = str_replace(',', $decSep, $value);
130131
}
131132

133+
if (false !== strpos($value, $decSep)) {
134+
$type = \NumberFormatter::TYPE_DOUBLE;
135+
} else {
136+
$type = \PHP_INT_SIZE === 8 ? \NumberFormatter::TYPE_INT64 : \NumberFormatter::TYPE_INT32;
137+
}
138+
132139
// replace normal spaces so that the formatter can read them
133-
$value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value));
140+
$result = $formatter->parse(str_replace(' ', "\xc2\xa0", $value), $type, $position);
134141

135142
if (intl_is_failure($formatter->getErrorCode())) {
136143
throw new TransformationFailedException($formatter->getErrorMessage());
137144
}
138145

139146
if (self::FRACTIONAL == $this->type) {
140-
$value /= 100;
147+
$result /= 100;
141148
}
142149

143-
return $value;
150+
if (\function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value, null, true)) {
151+
$length = mb_strlen($value, $encoding);
152+
$remainder = mb_substr($value, $position, $length, $encoding);
153+
} else {
154+
$length = \strlen($value);
155+
$remainder = substr($value, $position, $length);
156+
}
157+
158+
// After parsing, position holds the index of the character where the
159+
// parsing stopped
160+
if ($position < $length) {
161+
// Check if there are unrecognized characters at the end of the
162+
// number (excluding whitespace characters)
163+
$remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0");
164+
165+
if ('' !== $remainder) {
166+
throw new TransformationFailedException(sprintf('The number contains unrecognized characters: "%s"', $remainder));
167+
}
168+
}
169+
170+
return $result;
144171
}
145172

146173
/**

src/Symfony/Component/Form/Tests/Extension/Core/DataTransfor 8000 mer/PercentToLocalizedStringTransformerTest.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot()
141141
*/
142142
public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot()
143143
{
144-
// Since we test against "de_AT", we need the full implementation
144+
// Since we test against "de_DE", we need the full implementation
145145
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
146146

147-
\Locale::setDefault('de_AT');
147+
\Locale::setDefault('de_DE');
148148

149149
$transformer = new PercentToLocalizedStringTransformer(1, 'integer');
150150

@@ -236,4 +236,70 @@ public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGro
236236
$this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
237237
$this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
238238
}
239+
240+
/**
241+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
242+
*/
243+
public function testReverseTransformDisallowsLeadingExtraCharacters()
244+
{
245+
$transformer = new PercentToLocalizedStringTransformer();
246+
247+
$transformer->reverseTransform('foo123');
248+
}
249+
250+
/**
251+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
252+
* @expectedExceptionMessage The number contains unrecognized characters: "foo3"
253+
*/
254+
public function testReverseTransformDisallowsCenteredExtraCharacters()
255+
{
256+
$transformer = new PercentToLocalizedStringTransformer();
257+
258+
$transformer->reverseTransform('12foo3');
259+
}
260+
261+
/**
262+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
263+
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
264+
* @requires extension mbstring
265+
*/
266+
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
267+
{
268+
// Since we test against other locales, we need the full implementation
269+
IntlTestHelper::requireFullIntl($this, false);
270+
271+
\Locale::setDefault('ru');
272+
273+
$transformer = new PercentToLocalizedStringTransformer();
274+
275+
$transformer->reverseTransform("12\xc2\xa0345,67foo8");
276+
}
277+
278+
/**
279+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
280+
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
281+
*/
282+
public function testReverseTransformDisallowsTrailingExtraCharacters()
283+
{
284+
$transformer = new PercentToLocalizedStringTransformer();
285+
286+
$transformer->reverseTransform('123foo');
287+
}
288+
289+
/**
290+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
291+
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
292+
* @requires extension mbstring
293+
*/
294+
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
295+
{
296+
// Since we test against other locales, we need the full implementation
297+
IntlTestHelper::requireFullIntl($this, false);
298+
299+
\Locale::setDefault('ru');
300+
301+
$transformer = new PercentToLocalizedStringTransformer();
302+
303+
$transformer->reverseTransform("12\xc2\xa0345,678foo");
304+
}
239305
}

0 commit comments

Comments
 (0)
0