Skip to content

Commit d3a6054

Browse files
dryabovnikic
authored andcommitted
Fix/improve handling of escaping in ini parser
Quoting from UPGRADING: - A leading dollar in a quoted string can now be escaped: "\${" will now be interpreted as a string with contents `${`. - Backslashes in double quoted strings are now more consistently treated as escape characters. Previously, "foo\\" followed by something other than a newline was not considered as a teminated string. It is now interpreted as a string with contents `foo\`. However, as an exception, the string "foo\" followed by a newline will continue to be treated as a valid string with contents `foo\` rather than an unterminated string. This exception exists to support naive uses of Windows file pahts as "C:\foo\". Closes GH-7420.
1 parent 15ba73c commit d3a6054

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

Zend/zend_ini_scanner.l

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -591,31 +591,35 @@ end_raw_value_chars:
591591
return 0;
592592
}
593593

594-
while (YYCURSOR < YYLIMIT) {
595-
switch (*YYCURSOR++) {
594+
unsigned char *s = SCNG(yy_text);
595+
596+
while (s < YYLIMIT) {
597+
switch (*s++) {
596598
case '"':
597-
if (YYCURSOR < YYLIMIT && YYCURSOR[-2] == '\\' && *YYCURSOR != '\r' && *YYCURSOR != '\n') {
598-
continue;
599-
}
600599
break;
601600
case '$':
602-
if (*YYCURSOR == '{') {
601+
if (s < YYLIMIT && *s == '{') {
603602
break;
604603
}
605604
continue;
606605
case '\\':
607-
if (YYCURSOR < YYLIMIT && *YYCURSOR != '"') {
608-
YYCURSOR++;
606+
if (s < YYLIMIT) {
607+
unsigned char escaped = *s++;
608+
/* A special case for Windows paths, e.g. key="C:\path\" */
609+
if (escaped == '"' && (s >= YYLIMIT || *s == '\n' || *s == '\r')) {
610+
break;
611+
}
609612
}
610613
ZEND_FALLTHROUGH;
611614
default:
612615
continue;
613616
}
614617

615-
YYCURSOR--;
618+
s--;
616619
break;
617620
}
618621

622+
YYCURSOR = s;
619623
yyleng = YYCURSOR - SCNG(yy_text);
620624

621625
zend_ini_escape_string(ini_lval, yytext, yyleng, '"');

ext/standard/tests/general_functions/parse_ini_basic.data

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,14 @@ ini-with.hyphen = hyphen and dot
130130
[windows paths]
131131
winpath1="c:\some windows\path\test\new\r\quote \" here\single ' quote\some more"
132132
winpath2="special case\"
133+
134+
[characters escaping]
135+
; Note: single-quoted strings don't support characters escaping, and the line below
136+
; is single-quoted string, followed by unquoted text, followed by single-quoted '.'
137+
single_quoted = 'She said \'Exactly my point\'.'
138+
double_quoted = "She said \"Exactly my point\"."
139+
double_quoted_2 = "Use \\\" to escape double quote"
140+
double_quoted_multiline = "Lorem \"ipsum\"""
141+
dolor"
142+
dollar_test = "\${test}"
143+
unescaped ="\n\r\t"

ext/standard/tests/general_functions/parse_ini_basic.phpt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var_dump(parse_ini_file($ini_file, 1));
1515
echo "Done.\n";
1616
?>
1717
--EXPECT--
18-
array(26) {
18+
array(27) {
1919
["basic"]=>
2020
array(15) {
2121
["basicval"]=>
@@ -279,5 +279,21 @@ array(26) {
279279
["winpath2"]=>
280280
string(13) "special case\"
281281
}
282+
["characters escaping"]=>
283+
array(6) {
284+
["single_quoted"]=>
285+
string(28) "She said \Exactly my point\."
286+
["double_quoted"]=>
287+
string(28) "She said "Exactly my point"."
288+
["double_quoted_2"]=>
289+
string(29) "Use \" to escape double quote"
290+
["double_quoted_multiline"]=>
291+
string(20) "Lorem "ipsum"
292+
dolor"
293+
["dollar_test"]=>
294+
string(7) "${test}"
295+
["unescaped"]=>
296+
string(6) "\n\r\t"
297+
}
282298
}
283299
Done.

0 commit comments

Comments
 (0)