Skip to content

Commit c818d94

Browse files
authored
ext/(standard|spl): Deprecate passing a non-empty string as the $enclosure parameter (#15362)
1 parent 37c22c4 commit c818d94

15 files changed

+184
-45
lines changed

NEWS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,20 @@ PHP NEWS
7777
. The SplFixedArray::__wakeup() method has been deprecated as it implements
7878
__serialize() and __unserialize() which need to be overwritten instead.
7979
(TysonAndre)
80+
. Passing a non-empty string for the $enclosure parameter of:
81+
- SplFileObject::setCsvControl()
82+
- SplFileObject::fputcsv()
83+
- SplFileObject::fgetcsv()
84+
is now deprecated. (Girgias)
8085

8186
- Standard:
8287
. Unserializing the uppercase 'S' tag is now deprecated. (timwolla)
8388
. Enables crc32 auxiliary detection on OpenBSD. (David Carlier)
89+
. Passing a non-empty string for the $enclosure parameter of:
90+
- fputcsv()
91+
- fgetcsv()
92+
- str_getcsv()
93+
is now deprecated. (Girgias)
8494

8595
- Streams:
8696
. Implemented GH-15155 (Stream context is lost when custom stream wrapper is

UPGRADING

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,12 @@ PHP 8.4 UPGRADE NOTES
506506
- SPL:
507507
. The SplFixedArray::__wakeup() method has been deprecated as it implements
508508
__serialize() and __unserialize() which need to be overwritten instead.
509+
. Passing a non-empty string for the $enclosure parameter of:
510+
- SplFileObject::setCsvControl()
511+
- SplFileObject::fputcsv()
512+
- SplFileObject::fgetcsv()
513+
is now deprecated.
514+
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism
509515

510516
- Standard:
511517
. Calling stream_context_set_option() with 2 arguments is deprecated.
@@ -514,6 +520,12 @@ PHP 8.4 UPGRADE NOTES
514520
RFC: https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number
515521
. Unserializing strings using the uppercase 'S' tag is deprecated.
516522
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
523+
. Passing a non-empty string for the $enclosure parameter of:
524+
- fputcsv()
525+
- fgetcsv()
526+
- str_getcsv()
527+
is now deprecated.
528+
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism
517529

518530
- XML:
519531
. The xml_set_object() function has been deprecated.

ext/spl/spl_directory.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,6 +2310,10 @@ PHP_METHOD(SplFileObject, fgetcsv)
23102310
if (esc_len == 0) {
23112311
escape = PHP_CSV_NO_ESCAPE;
23122312
} else {
2313+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
2314+
if (UNEXPECTED(EG(exception))) {
2315+
RETURN_THROWS();
2316+
}
23132317
escape = (unsigned char) esc[0];
23142318
}
23152319
}
@@ -2358,6 +2362,10 @@ PHP_METHOD(SplFileObject, fputcsv)
23582362
if (esc_len == 0) {
23592363
escape = PHP_CSV_NO_ESCAPE;
23602364
} else {
2365+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
2366+
if (UNEXPECTED(EG(exception))) {
2367+
RETURN_THROWS();
2368+
}
23612369
escape = (unsigned char) esc[0];
23622370
}
23632371
}
@@ -2405,6 +2413,10 @@ PHP_METHOD(SplFileObject, setCsvControl)
24052413
if (esc_len == 0) {
24062414
escape = PHP_CSV_NO_ESCAPE;
24072415
} else {
2416+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
2417+
if (UNEXPECTED(EG(exception))) {
2418+
RETURN_THROWS();
2419+
}
24082420
escape = (unsigned char) esc[0];
24092421
}
24102422
}

ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_escape_basic.phpt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ var_dump($fo->fgetcsv(',', '"', '"'));
1313
<?php
1414
unlink('SplFileObject__fgetcsv6.csv');
1515
?>
16-
--EXPECT--
16+
--EXPECTF--
17+
Deprecated: SplFileObject::fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
1718
array(3) {
1819
[0]=>
1920
string(3) "aaa"

ext/spl/tests/SplFileObject/SplFileObject_setCsvControl_basic.phpt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ SPL: SplFileObject::setCsvControl basic
44
Erwin Poeze <erwin.poeze at gmail.com>
55
--FILE--
66
<?php
7-
file_put_contents('csv_control_data_basic.csv',
8-
<<<CDATA
9-
'groene appelen'|10
10-
'gele bananen'|20
11-
'rode kersen'|30
12-
CDATA
7+
file_put_contents(
8+
'csv_control_data_basic.csv',
9+
<<<CDATA
10+
'groene appelen'|10
11+
'gele bananen'|20
12+
'rode kersen'|30
13+
CDATA
1314
);
1415
$s = new SplFileObject('csv_control_data_basic.csv');
1516
$s->setFlags(SplFileObject::READ_CSV);
16-
$s->setCsvControl('|', '\'', '/');
17+
$s->setCsvControl('|', '\'', '');
1718
foreach ($s as $row) {
1819
list($fruit, $quantity) = $row;
1920
echo "$fruit : $quantity\n";

ext/standard/file.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,6 +1734,10 @@ PHP_FUNCTION(fputcsv)
17341734
if (escape_str_len < 1) {
17351735
escape_char = PHP_CSV_NO_ESCAPE;
17361736
} else {
1737+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
1738+
if (UNEXPECTED(EG(exception))) {
1739+
RETURN_THROWS();
1740+
}
17371741
/* use first character from string */
17381742
escape_char = (unsigned char) *escape_str;
17391743
}
@@ -1875,6 +1879,10 @@ PHP_FUNCTION(fgetcsv)
18751879
if (escape_str_len < 1) {
18761880
escape = PHP_CSV_NO_ESCAPE;
18771881
} else {
1882+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
1883+
if (UNEXPECTED(EG(exception))) {
1884+
RETURN_THROWS();
1885+
}
18781886
escape = (unsigned char) escape_str[0];
18791887
}
18801888
}

ext/standard/string.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5447,25 +5447,40 @@ PHP_FUNCTION(str_getcsv)
54475447
{
54485448
zend_string *str;
54495449
char delim = ',', enc = '"';
5450-
int esc = (unsigned char) '\\';
5451-
char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
5452-
size_t delim_len = 0, enc_len = 0, esc_len = 0;
5450+
int escape = (unsigned char) '\\';
5451+
char *delim_str = NULL, *enc_str = NULL, *escape_str = NULL;
5452+
size_t delim_len = 0, enc_len = 0, escape_str_len = 0;
54535453

54545454
ZEND_PARSE_PARAMETERS_START(1, 4)
54555455
Z_PARAM_STR(str)
54565456
Z_PARAM_OPTIONAL
54575457
Z_PARAM_STRING(delim_str, delim_len)
54585458
Z_PARAM_STRING(enc_str, enc_len)
5459-
Z_PARAM_STRING(esc_str, esc_len)
5459+
Z_PARAM_STRING(escape_str, escape_str_len)
54605460
ZEND_PARSE_PARAMETERS_END();
54615461

54625462
delim = delim_len ? delim_str[0] : delim;
54635463
enc = enc_len ? enc_str[0] : enc;
5464-
if (esc_str != NULL) {
5465-
esc = esc_len ? (unsigned char) esc_str[0] : PHP_CSV_NO_ESCAPE;
5464+
5465+
// TODO ValueError for delimiter and enclosure string being longer than 1 byte
5466+
if (escape_str != NULL) {
5467+
if (escape_str_len > 1) {
5468+
zend_argument_value_error(4, "must be empty or a single character");
5469+
RETURN_THROWS();
5470+
}
5471+
5472+
if (escape_str_len < 1) {
5473+
escape = PHP_CSV_NO_ESCAPE;
5474+
} else {
5475+
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
5476+
if (UNEXPECTED(EG(exception))) {
5477+
RETURN_THROWS();
5478+
}
5479+
escape = (unsigned char) escape_str[0];
5480+
}
54665481
}
54675482

5468-
HashTable *values = php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str));
5483+
HashTable *values = php_fgetcsv(NULL, delim, enc, escape, ZSTR_LEN(str), ZSTR_VAL(str));
54695484
if (values == NULL) {
54705485
values = php_bc_fgetcsv_empty_line();
54715486
}

ext/standard/tests/file/bug40501.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fclose($h);
1111
var_dump($data);
1212
?>
1313
--EXPECTF--
14+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
1415
array(2) {
1516
[0]=>
1617
string(%d) "this element contains the delimiter, and ends with an odd number of

ext/standard/tests/file/bug72330.phpt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ $string = '"first #' . $utf_1 . $utf_2 . '";"second"';
1717
$fields = str_getcsv($string, ';', '"', "#");
1818
var_dump($fields);
1919
?>
20-
--EXPECT--
20+
--EXPECTF--
21+
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
2122
array(2) {
2223
[0]=>
2324
string(11) "first #с؀"

ext/standard/tests/file/fputcsv_variation15.phpt

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,13 @@ $list = array (
2222
13 => 'aaa,"bbb "',
2323
14 => 'aaa"aaa","bbb"bbb',
2424
15 => 'aaa"aaa""",bbb',
25-
16 => 'aaa,"/"bbb,ccc',
26-
17 => 'aaa"/"a","bbb"',
27-
18 => '"/"","aaa"',
28-
19 => '"/""",aaa',
2925
);
3026

3127
$file = __DIR__ . '/fputcsv_variation15.csv';
32-
@unlink($file);
3328

3429
$fp = fopen($file, "w");
3530
foreach ($list as $v) {
36-
fputcsv($fp, explode(',', $v), ',', '"', '/');
31+
fputcsv($fp, explode(',', $v), ',', '"', '');
3732
}
3833
fclose($fp);
3934

@@ -46,16 +41,19 @@ echo '$list = ';var_export($res);echo ";\n";
4641

4742
$fp = fopen($file, "r");
4843
$res = array();
49-
while($l=fgetcsv($fp, 0, ',', '"', '/'))
44+
while($l=fgetcsv($fp, 0, ',', '"', ''))
5045
{
5146
$res[] = join(',',$l);
5247
}
5348
fclose($fp);
5449

5550
echo '$list = ';var_export($res);echo ";\n";
5651

52+
?>
53+
--CLEAN--
54+
<?php
55+
$file = __DIR__ . '/fputcsv_variation15.csv';
5756
@unlink($file);
58-
5957
?>
6058
--EXPECT--
6159
$list = array (
@@ -75,10 +73,6 @@ $list = array (
7573
13 => 'aaa,"""bbb """',
7674
14 => '"aaa""aaa""","""bbb""bbb"',
7775
15 => '"aaa""aaa""""""",bbb',
78-
16 => 'aaa,"""/"bbb",ccc',
79-
17 => '"aaa""/"a""","""bbb"""',
80-
18 => '"""/"""","""aaa"""',
81-
19 => '"""/"""""",aaa',
8276
);
8377
$list = array (
8478
0 => 'aaa,bbb',
@@ -97,8 +91,4 @@ $list = array (
9791
13 => 'aaa,"bbb "',
9892
14 => 'aaa"aaa","bbb"bbb',
9993
15 => 'aaa"aaa""",bbb',
100-
16 => 'aaa,"/"bbb,ccc',
101-
17 => 'aaa"/"a","bbb"',
102-
18 => '"/"","aaa"',
103-
19 => '"/""",aaa',
10494
);

ext/standard/tests/file/fputcsv_variation17.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ $eol_chars = ['||', '|', '\n', "\n", "\0"];
1212
foreach ($eol_chars as $eol_char) {
1313
$stream = fopen('php://memory', 'w+');
1414
foreach ($data as $record) {
15-
fputcsv($stream, $record, ',', '"', '\\', $eol_char);
15+
fputcsv($stream, $record, ',', '"', '', $eol_char);
1616
}
1717
rewind($stream);
1818
echo stream_get_contents($stream), "\n";
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
fputcsv() variant where escape parameter matters
3+
--FILE--
4+
<?php
5+
6+
$list = [
7+
1 => 'aaa,"/"bbb,ccc',
8+
2 => 'aaa"/"a","bbb"',
9+
3 => '"/"","aaa"',
10+
4 => '"/""",aaa',
11+
];
12+
13+
$file = __DIR__ . '/fputcsv_variation18.csv';
14+
15+
$fp = fopen($file, "w");
16+
foreach ($list as $v) {
17+
fputcsv($fp, explode(',', $v), ',', '"', '/');
18+
}
19+
fclose($fp);
20+
21+
$res = file($file);
22+
foreach($res as &$val)
23+
{
24+
$val = substr($val, 0, -1);
25+
}
26+
echo '$list = ';var_export($res);echo ";\n";
27+
28+
$fp = fopen($file, "r");
29+
$res = array();
30+
while($l=fgetcsv($fp, 0, ',', '"', '/'))
31+
{
32+
$res[] = join(',',$l);
33+
}
34+
fclose($fp);
35+
36+
echo '$list = ';var_export($res);echo ";\n";
37+
38+
?>
39+
--CLEAN--
40+
<?php
41+
$file = __DIR__ . '/fputcsv_variation18.csv';
42+
@unlink($file);
43+
?>
44+
--EXPECTF--
45+
Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
46+
47+
Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
48+
49+
Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
50+
51+
Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
52+
$list = array (
53+
0 => 'aaa,"""/"bbb",ccc',
54+
1 => '"aaa""/"a""","""bbb"""',
55+
2 => '"""/"""","""aaa"""',
56+
3 => '"""/"""""",aaa',
57+
);
58+
59+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
60+
61+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
62+
63+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
64+
65+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
66+
67+
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
68+
$list = array (
69+
0 => 'aaa,"/"bbb,ccc',
70+
1 => 'aaa"/"a","bbb"',
71+
2 => '"/"","aaa"',
72+
3 => '"/""",aaa',
73+
);

ext/standard/tests/strings/gh12151.phpt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ GH-12151 (str_getcsv ending with escape zero segfualt)
55
var_export(str_getcsv("y","","y","\000"));
66
var_export(str_getcsv("\0yy","y","y","\0"));
77
?>
8-
--EXPECT--
8+
--EXPECTF--
9+
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
910
array (
1011
0 => '' . "\0" . '',
11-
)array (
12+
)
13+
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
14+
array (
1215
0 => '' . "\0" . '',
1316
1 => '' . "\0" . '',
1417
)

0 commit comments

Comments
 (0)