|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2007-11-09 14:59 UTC] ed at bronto dot com
Description:
------------
Using fputcsv to output a cell that ends with a \ followed by double quotes (") causes it to not use any escape sequence. Oddly, fgetscsv is able to parse it correctly. Unlike fgetscsv, I assume fputcsv follows RFC 4180 and uses " as the escape character.
Reproduce code:
---------------
$row = array();
$row[] = 'a\\"';
$row[] = 'bbb';
$fp = fopen('test.csv', 'w+');
fputcsv($fp, $row);
fclose($fp);
Expected result:
----------------
expected output: "a\""",bbb
Actual result:
--------------
actual output: "a\"",bbb
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 23:00:01 2025 UTC |
Same problem on windows XP PHP version 5.2.5 on cells that contain a \ followed by double quotes (")I've found the cause of this while writing tests for PR 197. php_fputcsv(), while iterating over the fields to be output, has this fairly odd "escaped" concept — once escape_char (which is hardcoded \ at present) is seen, escaping stops until the next enclosure (" by default) is seen. It doesn't matter whether it's the following character or not. After that, escape_char is then ignored anyway, and the enclosure is used as the "escape" character. This came in via https://github.com/php/php-src/commit/af0adbed3963cdee1bfaf5e3a74b029d2b92c8b7 seven years ago to make the use of enclosures optional — the feature in general is good, but this is definitely an issue in the implementation.To summarize the related bugs: fputcsv() seems to be using inconsistent and broken escaping of the enclosing char (`"`) : - `"` followed by `\` are not escaped - `"` not followed by `\` are escaped by doubling them (e.g. `"` becomes `""`); leading to inconsistent escaping method - `\` themselves are not escaped, leading to generation of invalid CSV if a field is terminated by `\`: `"foo bar\",baz` - With the input `\\"`, the `"` is still considered to be escaped Due to this combinaison of bugs, it is impossible to parse the CSV generated by the following call: fputcsv(STDOUT, ['foo\"bar', 'foo""bar', 'foo bar\\']); Output is: "foo\"bar","foo""""bar","foo bar\" Trying to parse this with a parser using the doubled-char escaping method will break on the first field. Trying to parse this with a parser using the backslash escaping method will break on the 2nd and 3rd fields. Trying to parse this with a parser allowing both methods will break on the 3rd field. Without the 3rd field, parsing this CSV document would result in loss of information (some `\` or `"` from the original input would be lost).The issues with PHP’s CSV functions also seem to be exploitable. <?php $handle = fopen('php://memory', 'w+b'); fputcsv($handle, [ 'foo bar\\', # 1 'baz quz', # 2 'x', # 3 'y', # 4 'z', # 5 'foo\\\\",bar' # 6 ]); rewind($handle); var_dump(fgetcsv($handle)); // array(6) { // [0]=> string(18) "foo bar\",baz quz"" # 1 // [1]=> string(1) "x" # 2 (was # 3) // [2]=> string(1) "y" # 3 (was # 4) // [3]=> string(1) "z" # 4 (was # 5) // [4]=> string(5) "foo\\" # 5 // [5]=> string(4) "bar"" # 6 // } 3v4l.org: http://3v4l.org/LTnC1