Skip to content

Commit 1b2ae02

Browse files
security #cve-2021-41270 [Serializer] Use single quote to escape formulas (jderusse)
This PR was merged into the 4.4 branch.
2 parents b5704a9 + d834b28 commit 1b2ae02

File tree

2 files changed

+81
-11
lines changed

2 files changed

+81
-11
lines changed

Encoder/CsvEncoder.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
3535

3636
private const UTF8_BOM = "\xEF\xBB\xBF";
3737

38-
private $formulasStartCharacters = ['=', '-', '+', '@'];
38+
private const FORMULAS_START_CHARACTERS = ['=', '-', '+', '@', "\t", "\r"];
39+
3940
private $defaultContext = [
4041
self::DELIMITER_KEY => ',',
4142
self::ENCLOSURE_KEY => '"',
@@ -238,8 +239,8 @@ private function flatten(iterable $array, array &$result, string $keySeparator,
238239
if (is_iterable($value)) {
239240
$this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator, $escapeFormulas);
240241
} else {
241-
if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), $this->formulasStartCharacters, true)) {
242-
$result[$parentKey.$key] = "\t".$value;
242+
if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), self::FORMULAS_START_CHARACTERS, true)) {
243+
$result[$parentKey.$key] = "'".$value;
243244
} else {
244245
// Ensures an actual value is used when dealing with true and false
245246
$result[$parentKey.$key] = false === $value ? 0 : (true === $value ? 1 : $value);

Tests/Encoder/CsvEncoderTest.php

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -285,31 +285,52 @@ private function doTestEncodeFormulas(bool $legacy = false)
285285

286286
$this->assertSame(<<<'CSV'
287287
0
288-
" =2+3"
288+
'=2+3
289289

290290
CSV
291291
, $this->encoder->encode(['=2+3'], 'csv'));
292292

293293
$this->assertSame(<<<'CSV'
294294
0
295-
" -2+3"
295+
'-2+3
296296

297297
CSV
298298
, $this->encoder->encode(['-2+3'], 'csv'));
299299

300300
$this->assertSame(<<<'CSV'
301301
0
302-
" +2+3"
302+
'+2+3
303303

304304
CSV
305305
, $this->encoder->encode(['+2+3'], 'csv'));
306306

307307
$this->assertSame(<<<'CSV'
308308
0
309-
" @MyDataColumn"
309+
'@MyDataColumn
310310

311311
CSV
312312
, $this->encoder->encode(['@MyDataColumn'], 'csv'));
313+
314+
$this->assertSame(<<<'CSV'
315+
0
316+
"' tab"
317+
318+
CSV
319+
, $this->encoder->encode(["\ttab"], 'csv'));
320+
321+
$this->assertSame(<<<'CSV'
322+
0
323+
"'=1+2"";=1+2"
324+
325+
CSV
326+
, $this->encoder->encode(['=1+2";=1+2'], 'csv'));
327+
328+
$this->assertSame(<<<'CSV'
329+
0
330+
"'=1+2'"" ;,=1+2"
331+
332+
CSV
333+
, $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv'));
313334
}
314335

315336
public function testDoNotEncodeFormulas()
@@ -341,13 +362,34 @@ public function testDoNotEncodeFormulas()
341362

342363
CSV
343364
, $this->encoder->encode(['@MyDataColumn'], 'csv'));
365+
366+
$this->assertSame(<<<'CSV'
367+
0
368+
" tab"
369+
370+
CSV
371+
, $this->encoder->encode(["\ttab"], 'csv'));
372+
373+
$this->assertSame(<<<'CSV'
374+
0
375+
"=1+2"";=1+2"
376+
377+
CSV
378+
, $this->encoder->encode(['=1+2";=1+2'], 'csv'));
379+
380+
$this->assertSame(<<<'CSV'
381+
0
382+
"=1+2'"" ;,=1+2"
383+
384+
CSV
385+
, $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv'));
344386
}
345387

346388
public function testEncodeFormulasWithSettingsPassedInContext()
347389
{
348390
$this->assertSame(<<<'CSV'
349391
0
350-
" =2+3"
392+
'=2+3
351393

352394
CSV
353395
, $this->encoder->encode(['=2+3'], 'csv', [
@@ -356,7 +398,7 @@ public function testEncodeFormulasWithSettingsPassedInContext()
356398

357399
$this->assertSame(<<<'CSV'
358400
0
359-
" -2+3"
401+
'-2+3
360402

361403
CSV
362404
, $this->encoder->encode(['-2+3'], 'csv', [
@@ -365,7 +407,7 @@ public function testEncodeFormulasWithSettingsPassedInContext()
365407

366408
$this->assertSame(<<<'CSV'
367409
0
368-
" +2+3"
410+
'+2+3
369411

370412
CSV
371413
, $this->encoder->encode(['+2+3'], 'csv', [
@@ -374,12 +416,39 @@ public function testEncodeFormulasWithSettingsPassedInContext()
374416

375417
$this->assertSame(<<<'CSV'
376418
0
377-
" @MyDataColumn"
419+
'@MyDataColumn
378420

379421
CSV
380422
, $this->encoder->encode(['@MyDataColumn'], 'csv', [
381423
CsvEncoder::ESCAPE_FORMULAS_KEY => true,
382424
]));
425+
426+
$this->assertSame(<<<'CSV'
427+
0
428+
"' tab"
429+
430+
CSV
431+
, $this->encoder->encode(["\ttab"], 'csv', [
432+
CsvEncoder::ESCAPE_FORMULAS_KEY => true,
433+
]));
434+
435+
$this->assertSame(<<<'CSV'
436+
0
437+
"'=1+2"";=1+2"
438+
439+
CSV
440+
, $this->encoder->encode(['=1+2";=1+2'], 'csv', [
441+
CsvEncoder::ESCAPE_FORMULAS_KEY => true,
442+
]));
443+
444+
$this->assertSame(<<<'CSV'
445+
0
446+
"'=1+2'"" ;,=1+2"
447+
448+
CSV
449+
, $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv', [
450+
CsvEncoder::ESCAPE_FORMULAS_KEY => true,
451+
]));
383452
}
384453

385454
public function testEncodeWithoutHeader()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy