Skip to content

ext/(standard|spl): Deprecate passing a non-empty string as the $escape parameter #15362

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

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,20 @@ PHP NEWS
. The SplFixedArray::__wakeup() method has been deprecated as it implements
__serialize() and __unserialize() which need to be overwritten instead.
(TysonAndre)
. Passing a non-empty string for the $enclosure parameter of:
- SplFileObject::setCsvControl()
- SplFileObject::fputcsv()
- SplFileObject::fgetcsv()
is now deprecated. (Girgias)

- Standard:
. Unserializing the uppercase 'S' tag is now deprecated. (timwolla)
. Enables crc32 auxiliary detection on OpenBSD. (David Carlier)
. Passing a non-empty string for the $enclosure parameter of:
- fputcsv()
- fgetcsv()
- str_getcsv()
is now deprecated. (Girgias)

- Streams:
. Implemented GH-15155 (Stream context is lost when custom stream wrapper is
Expand Down
12 changes: 12 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,12 @@ PHP 8.4 UPGRADE NOTES
- SPL:
. The SplFixedArray::__wakeup() method has been deprecated as it implements
__serialize() and __unserialize() which need to be overwritten instead.
. Passing a non-empty string for the $enclosure parameter of:
- SplFileObject::setCsvControl()
- SplFileObject::fputcsv()
- SplFileObject::fgetcsv()
is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism

- Standard:
. Calling stream_context_set_option() with 2 arguments is deprecated.
Expand All @@ -512,6 +518,12 @@ PHP 8.4 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number
. Unserializing strings using the uppercase 'S' tag is deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
. Passing a non-empty string for the $enclosure parameter of:
- fputcsv()
- fgetcsv()
- str_getcsv()
is now deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_proprietary_csv_escaping_mechanism

- XML:
. The xml_set_object() function has been deprecated.
Expand Down
12 changes: 12 additions & 0 deletions ext/spl/spl_directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2310,6 +2310,10 @@ PHP_METHOD(SplFileObject, fgetcsv)
if (esc_len == 0) {
escape = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
escape = (unsigned char) esc[0];
}
}
Expand Down Expand Up @@ -2358,6 +2362,10 @@ PHP_METHOD(SplFileObject, fputcsv)
if (esc_len == 0) {
escape = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
escape = (unsigned char) esc[0];
}
}
Expand Down Expand Up @@ -2405,6 +2413,10 @@ PHP_METHOD(SplFileObject, setCsvControl)
if (esc_len == 0) {
escape = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
escape = (unsigned char) esc[0];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ var_dump($fo->fgetcsv(',', '"', '"'));
<?php
unlink('SplFileObject__fgetcsv6.csv');
?>
--EXPECT--
--EXPECTF--
Deprecated: SplFileObject::fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
array(3) {
[0]=>
string(3) "aaa"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ SPL: SplFileObject::setCsvControl basic
Erwin Poeze <erwin.poeze at gmail.com>
--FILE--
<?php
file_put_contents('csv_control_data_basic.csv',
<<<CDATA
'groene appelen'|10
'gele bananen'|20
'rode kersen'|30
CDATA
file_put_contents(
'csv_control_data_basic.csv',
<<<CDATA
'groene appelen'|10
'gele bananen'|20
'rode kersen'|30
CDATA
);
$s = new SplFileObject('csv_control_data_basic.csv');
$s->setFlags(SplFileObject::READ_CSV);
$s->setCsvControl('|', '\'', '/');
$s->setCsvControl('|', '\'', '');
foreach ($s as $row) {
list($fruit, $quantity) = $row;
echo "$fruit : $quantity\n";
Expand Down
8 changes: 8 additions & 0 deletions ext/standard/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,10 @@ PHP_FUNCTION(fputcsv)
if (escape_str_len < 1) {
escape_char = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
/* use first character from string */
escape_char = (unsigned char) *escape_str;
}
Expand Down Expand Up @@ -1875,6 +1879,10 @@ PHP_FUNCTION(fgetcsv)
if (escape_str_len < 1) {
escape = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
escape = (unsigned char) escape_str[0];
}
}
Expand Down
29 changes: 22 additions & 7 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -5447,25 +5447,40 @@ PHP_FUNCTION(str_getcsv)
{
zend_string *str;
char delim = ',', enc = '"';
int esc = (unsigned char) '\\';
char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
size_t delim_len = 0, enc_len = 0, esc_len = 0;
int escape = (unsigned char) '\\';
char *delim_str = NULL, *enc_str = NULL, *escape_str = NULL;
size_t delim_len = 0, enc_len = 0, escape_str_len = 0;

ZEND_PARSE_PARAMETERS_START(1, 4)
Z_PARAM_STR(str)
Z_PARAM_OPTIONAL
Z_PARAM_STRING(delim_str, delim_len)
Z_PARAM_STRING(enc_str, enc_len)
Z_PARAM_STRING(esc_str, esc_len)
Z_PARAM_STRING(escape_str, escape_str_len)
ZEND_PARSE_PARAMETERS_END();

delim = delim_len ? delim_str[0] : delim;
enc = enc_len ? enc_str[0] : enc;
if (esc_str != NULL) {
esc = esc_len ? (unsigned char) esc_str[0] : PHP_CSV_NO_ESCAPE;

// TODO ValueError for delimiter and enclosure string being longer than 1 byte
if (escape_str != NULL) {
if (escape_str_len > 1) {
zend_argument_value_error(4, "must be empty or a single character");
RETURN_THROWS();
}

if (escape_str_len < 1) {
escape = PHP_CSV_NO_ESCAPE;
} else {
php_error_docref(NULL, E_DEPRECATED, "Passing a non-empty string to the $escape parameter is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
escape = (unsigned char) escape_str[0];
}
}

HashTable *values = php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str));
HashTable *values = php_fgetcsv(NULL, delim, enc, escape, ZSTR_LEN(str), ZSTR_VAL(str));
if (values == NULL) {
values = php_bc_fgetcsv_empty_line();
}
Expand Down
1 change: 1 addition & 0 deletions ext/standard/tests/file/bug40501.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fclose($h);
var_dump($data);
?>
--EXPECTF--
Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
array(2) {
[0]=>
string(%d) "this element contains the delimiter, and ends with an odd number of
Expand Down
3 changes: 2 additions & 1 deletion ext/standard/tests/file/bug72330.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ $string = '"first #' . $utf_1 . $utf_2 . '";"second"';
$fields = str_getcsv($string, ';', '"', "#");
var_dump($fields);
?>
--EXPECT--
--EXPECTF--
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
array(2) {
[0]=>
string(11) "first #с؀"
Expand Down
22 changes: 6 additions & 16 deletions ext/standard/tests/file/fputcsv_variation15.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,13 @@ $list = array (
13 => 'aaa,"bbb "',
14 => 'aaa"aaa","bbb"bbb',
15 => 'aaa"aaa""",bbb',
16 => 'aaa,"/"bbb,ccc',
17 => 'aaa"/"a","bbb"',
18 => '"/"","aaa"',
19 => '"/""",aaa',
);

$file = __DIR__ . '/fputcsv_variation15.csv';
@unlink($file);

$fp = fopen($file, "w");
foreach ($list as $v) {
fputcsv($fp, explode(',', $v), ',', '"', '/');
fputcsv($fp, explode(',', $v), ',', '"', '');
}
fclose($fp);

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

$fp = fopen($file, "r");
$res = array();
while($l=fgetcsv($fp, 0, ',', '"', '/'))
while($l=fgetcsv($fp, 0, ',', '"', ''))
{
$res[] = join(',',$l);
}
fclose($fp);

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

?>
--CLEAN--
<?php
$file = __DIR__ . '/fputcsv_variation15.csv';
@unlink($file);

?>
--EXPECT--
$list = array (
Expand All @@ -75,10 +73,6 @@ $list = array (
13 => 'aaa,"""bbb """',
14 => '"aaa""aaa""","""bbb""bbb"',
15 => '"aaa""aaa""""""",bbb',
16 => 'aaa,"""/"bbb",ccc',
17 => '"aaa""/"a""","""bbb"""',
18 => '"""/"""","""aaa"""',
19 => '"""/"""""",aaa',
);
$list = array (
0 => 'aaa,bbb',
Expand All @@ -97,8 +91,4 @@ $list = array (
13 => 'aaa,"bbb "',
14 => 'aaa"aaa","bbb"bbb',
15 => 'aaa"aaa""",bbb',
16 => 'aaa,"/"bbb,ccc',
17 => 'aaa"/"a","bbb"',
18 => '"/"","aaa"',
19 => '"/""",aaa',
);
2 changes: 1 addition & 1 deletion ext/standard/tests/file/fputcsv_variation17.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $eol_chars = ['||', '|', '\n', "\n", "\0"];
foreach ($eol_chars as $eol_char) {
$stream = fopen('php://memory', 'w+');
foreach ($data as $record) {
fputcsv($stream, $record, ',', '"', '\\', $eol_char);
fputcsv($stream, $record, ',', '"', '', $eol_char);
}
rewind($stream);
echo stream_get_contents($stream), "\n";
Expand Down
73 changes: 73 additions & 0 deletions ext/standard/tests/file/fputcsv_variation18.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
--TEST--
fputcsv() variant where escape parameter matters
--FILE--
<?php

$list = [
1 => 'aaa,"/"bbb,ccc',
2 => 'aaa"/"a","bbb"',
3 => '"/"","aaa"',
4 => '"/""",aaa',
];

$file = __DIR__ . '/fputcsv_variation18.csv';

$fp = fopen($file, "w");
foreach ($list as $v) {
fputcsv($fp, explode(',', $v), ',', '"', '/');
}
fclose($fp);

$res = file($file);
foreach($res as &$val)
{
$val = substr($val, 0, -1);
}
echo '$list = ';var_export($res);echo ";\n";

$fp = fopen($file, "r");
$res = array();
while($l=fgetcsv($fp, 0, ',', '"', '/'))
{
$res[] = join(',',$l);
}
fclose($fp);

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

?>
--CLEAN--
<?php
$file = __DIR__ . '/fputcsv_variation18.csv';
@unlink($file);
?>
--EXPECTF--
Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fputcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
$list = array (
0 => 'aaa,"""/"bbb",ccc',
1 => '"aaa""/"a""","""bbb"""',
2 => '"""/"""","""aaa"""',
3 => '"""/"""""",aaa',
);

Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d

Deprecated: fgetcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
$list = array (
0 => 'aaa,"/"bbb,ccc',
1 => 'aaa"/"a","bbb"',
2 => '"/"","aaa"',
3 => '"/""",aaa',
);
7 changes: 5 additions & 2 deletions ext/standard/tests/strings/gh12151.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ GH-12151 (str_getcsv ending with escape zero segfualt)
var_export(str_getcsv("y","","y","\000"));
var_export(str_getcsv("\0yy","y","y","\0"));
?>
--EXPECT--
--EXPECTF--
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
array (
0 => '' . "\0" . '',
)array (
)
Deprecated: str_getcsv(): Passing a non-empty string to the $escape parameter is deprecated since 8.4 in %s on line %d
array (
0 => '' . "\0" . '',
1 => '' . "\0" . '',
)
Loading
Loading