Skip to content

Commit 8a70a55

Browse files
author
Jani Taskinen
committed
MFH: - Fixed bugs #43915, #43923 and #44019, a tiny performance issue fixed too
1 parent dc8bfca commit 8a70a55

File tree

6 files changed

+110
-54
lines changed

6 files changed

+110
-54
lines changed

Zend/zend_ini_parser.y

+16-22
Original file line numberDiff line numberDiff line change
@@ -246,21 +246,24 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
246246

247247
%}
248248

249-
%expect 1
249+
%expect 0
250250
%pure_parser
251251

252252
%token TC_SECTION
253253
%token TC_RAW
254+
%token TC_CONSTANT
254255
%token TC_NUMBER
255256
%token TC_STRING
257+
%token TC_WHITESPACE
258+
%token TC_LABEL
256259
%token TC_OFFSET
257260
%token TC_DOLLAR_CURLY
258261
%token TC_VARNAME
259262
%token TC_QUOTED_STRING
260263
%token BOOL_TRUE
261264
%token BOOL_FALSE
262265
%token END_OF_LINE
263-
%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@'
266+
%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
264267
%left '|' '&'
265268
%right '~' '!'
266269
@@ -279,7 +282,7 @@ statement:
279282
ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
280283
free(Z_STRVAL($2));
281284
}
282-
| TC_STRING '=' string_or_value {
285+
| TC_LABEL '=' string_or_value {
283286
#if DEBUG_CFG_PARSER
284287
printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
285288
#endif
@@ -296,32 +299,24 @@ statement:
296299
free(Z_STRVAL($2));
297300
free(Z_STRVAL($5));
298301
}
299-
| TC_STRING { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
302+
| TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
300303
| END_OF_LINE
301304
;
302305
303306
section_string_or_value:
304-
TC_RAW { $$ = $1; }
305-
| section_var_list { $$ = $1; }
306-
| '"' encapsed_list '"' { $$ = $2; }
307+
var_string_list { $$ = $1; }
307308
| /* empty */ { zend_ini_init_string(&$$); }
308309
;
309310
310311
string_or_value:
311312
expr { $$ = $1; }
312-
| TC_RAW { $$ = $1; }
313-
| TC_NUMBER { $$ = $1; }
314313
| BOOL_TRUE { $$ = $1; }
315314
| BOOL_FALSE { $$ = $1; }
316-
| '"' encapsed_list '"' { $$ = $2; }
317315
| END_OF_LINE { zend_ini_init_string(&$$); }
318316
;
319317
320318
option_offset:
321-
TC_NUMBER { $$ = $1; }
322-
| TC_RAW { $$ = $1; }
323-
| var_string_list { $$ = $1; }
324-
| '"' encapsed_list '"' { $$ = $2; }
319+
var_string_list { $$ = $1; }
325320
| /* empty */ { zend_ini_init_string(&$$); }
326321
;
327322
@@ -331,18 +326,13 @@ encapsed_list:
331326
| /* empty */ { zend_ini_init_string(&$$); }
332327
;
333328
334-
section_var_list:
335-
cfg_var_ref { $$ = $1; }
336-
| TC_STRING { $$ = $1; }
337-
| section_var_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
338-
| section_var_list TC_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
339-
;
340-
341329
var_string_list:
342330
cfg_var_ref { $$ = $1; }
343331
| constant_string { $$ = $1; }
332+
| '"' encapsed_list '"' { $$ = $2; }
344333
| var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
345334
| var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
335+
| var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
346336
;
347337
348338
expr:
@@ -359,7 +349,11 @@ cfg_var_ref:
359349
;
360350
361351
constant_string:
362-
TC_STRING { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
352+
TC_CONSTANT { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
353+
| TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
354+
| TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
355+
| TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
356+
| TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
363357
;
364358
365359
/*

Zend/zend_ini_scanner.l

+29-27
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ static void zend_ini_escape_string(zval *lval, char *str, int len, char quote_ty
258258
} else {
259259
*t++ = *s;
260260
}
261-
262261
if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
263262
SCNG(lineno)++;
264263
}
@@ -272,25 +271,26 @@ static void zend_ini_escape_string(zval *lval, char *str, int len, char quote_ty
272271

273272
LNUM [0-9]+
274273
DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*)
275-
NUMBER {LNUM}|{DNUM}
276-
ANY_CHAR (.|[\n])
274+
NUMBER [-]?{LNUM}|{DNUM}
275+
ANY_CHAR (.|[\n\t])
277276
NEWLINE ("\r"|"\n"|"\r\n")
278277
TABS_AND_SPACES [ \t]
278+
WHITESPACE [ \t]+
279279
CONSTANT [a-zA-Z][a-zA-Z0-9_]*
280-
LABEL [a-zA-Z0-9][a-zA-Z0-9._]*
281-
TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@]
280+
LABEL [a-zA-Z0-9][a-zA-Z0-9._-]*
281+
TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@{}]
282282
OPERATORS [&|~()!]
283+
DOLLAR_CURLY "${"
283284
284-
LITERAL_DOLLAR ("$"+([^a-zA-Z0-9$"'\\{]|("\\"{ANY_CHAR})))
285-
VALUE_CHARS ("{"*([^=\n\r;&|~()!$"'\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
286-
RAW_VALUE_CHARS [^=\n\r;]
287-
SINGLE_QUOTED_CHARS [^']
288-
289-
SECTION_VALUE_CHARS ("{"*([^\n\r;$"'\\{\]]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
290285
SECTION_RAW_CHARS [^\]\n\r]
286+
SINGLE_QUOTED_CHARS [^']
287+
RAW_VALUE_CHARS [^=\n\r;]
291288
292-
/* Allow using ${foobar} inside quoted strings */
293-
DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
289+
/* Allow using ${foobar} in sections, quoted strings and values */
290+
LITERAL_DOLLAR ("$"([^a-zA-Z0-9{]|("\\"{ANY_CHAR})))
291+
VALUE_CHARS ([^$= \t\n\r;&|~()!"']|{LITERAL_DOLLAR})
292+
SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
293+
DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
294294
295295
/* " */
296296
@@ -343,7 +343,7 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
343343
return ']';
344344
}
345345

346-
<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>"${" { /* Variable start */
346+
<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{DOLLAR_CURLY} { /* Variable start */
347347
yy_push_state(ST_VARNAME TSRMLS_CC);
348348
return TC_DOLLAR_CURLY;
349349
}
@@ -365,8 +365,8 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
365365
RETURN_TOKEN(BOOL_FALSE, "", 0);
366366
}
367367

368-
<INITIAL,ST_OFFSET>{LABEL} { /* Get option name or option offset value */
369-
RETURN_TOKEN(TC_STRING, yytext, yyleng);
368+
<INITIAL>{LABEL} { /* Get option name */
369+
RETURN_TOKEN(TC_LABEL, yytext, yyleng);
370370
}
371371

372372
<INITIAL>{TABS_AND_SPACES}*[=]{TABS_AND_SPACES}* { /* Start option value */
@@ -392,17 +392,17 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
392392
RETURN_TOKEN(TC_RAW, yytext, yyleng);
393393
}
394394

395-
<ST_VALUE,ST_RAW>{NEWLINE} { /* End of option value */
395+
<ST_VALUE,ST_RAW>{TABS_AND_SPACES}*{NEWLINE} { /* End of option value */
396396
BEGIN(INITIAL);
397397
SCNG(lineno)++;
398398
return END_OF_LINE;
399399
}
400400

401-
<ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
402-
RETURN_TOKEN(TC_STRING, yytext, yyleng);
401+
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
402+
RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
403403
}
404404

405-
<ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
405+
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
406406
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
407407
}
408408

@@ -421,16 +421,14 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
421421
}
422422

423423
<ST_VALUE>{VALUE_CHARS}+ { /* Get everything else as option/offset value */
424-
/* Eat trailing tabs and spaces */
425-
EAT_TRAILING_WHITESPACE();
426424
RETURN_TOKEN(TC_STRING, yytext, yyleng);
427425
}
428426

429427
<ST_SECTION_VALUE,ST_OFFSET>{SECTION_VALUE_CHARS}+ { /* Get rest as section/offset value */
430428
RETURN_TOKEN(TC_STRING, yytext, yyleng);
431429
}
432430

433-
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>["] { /* Double quoted '"' string start */
431+
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{TABS_AND_SPACES}*["] { /* Double quoted '"' string start */
434432
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
435433
return '"';
436434
}
@@ -440,21 +438,25 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
440438
return TC_QUOTED_STRING;
441439
}
442440
443-
<ST_DOUBLE_QUOTES>["] { /* Double quoted '"' string ends */
441+
<ST_DOUBLE_QUOTES>["]{TABS_AND_SPACES}* { /* Double quoted '"' string ends */
444442
yy_pop_state(TSRMLS_C);
445443
return '"';
446444
}
447445
448-
<INITIAL,ST_VALUE,ST_RAW,ST_OFFSET>{TABS_AND_SPACES} {
446+
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{WHITESPACE} {
447+
RETURN_TOKEN(TC_WHITESPACE, yytext, yyleng);
448+
}
449+
450+
<INITIAL,ST_RAW>{TABS_AND_SPACES}+ {
449451
/* eat whitespace */
450452
}
451453
452-
<INITIAL>{NEWLINE} {
454+
<INITIAL>{TABS_AND_SPACES}*{NEWLINE} {
453455
SCNG(lineno)++;
454456
return END_OF_LINE;
455457
}
456458
457-
<INITIAL,ST_VALUE,ST_RAW>[;][^\r\n]*{NEWLINE} { /* Comment */
459+
<INITIAL,ST_VALUE,ST_RAW>{TABS_AND_SPACES}*[;][^\r\n]*{NEWLINE} { /* Comment */
458460
BEGIN(INITIAL);
459461
SCNG(lineno)++;
460462
return END_OF_LINE;

ext/standard/tests/general_functions/parse_ini_basic.data

+24-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ string = asdadfsdjkslkj ¡@£$$ { }[ ]/%#¤
1313
sqstring = 'adsasdadasdasd'
1414
dqstring = "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
1515
php_constant = E_ALL
16+
user_constant = TEST_CONSTANT
1617

1718
[basic with whitespace]
1819
basicval = bar
@@ -89,7 +90,7 @@ novalue_option4[]=
8990
;[PATH="${basicval}/path/quoted"]
9091
["PATH=${basicval}/all/quoted"]
9192

92-
; The rest is from bug #29306
93+
; This is test for bug #29306
9394
[01]
9495
e=e
9596
f=f
@@ -104,3 +105,25 @@ c=c
104105
d=d
105106
[0815]
106107
bla=bla
108+
109+
;Test for bug #43923
110+
[bug #43923]
111+
curly1 = {
112+
curly2 = "{"
113+
curly3 = '{'
114+
115+
;Test for bug #44019
116+
[bug #44019]
117+
concatenation_before = TEST_CONSTANT "+some_text_after"
118+
concatenation_middle = "some_text_before+" TEST_CONSTANT "+some_text_after"
119+
concatenation_after = "some_text_before+" TEST_CONSTANT
120+
concatenation_nows_before = TEST_CONSTANT"+some_text_after"
121+
concatenation_nows_middle = "some_text_before+"TEST_CONSTANT"+some_text_after"
122+
concatenation_nows_after = "some_text_before+"TEST_CONSTANT
123+
124+
;Test for bug #43915
125+
[bug #43915]
126+
ini_with-hyphen = with hyphen and underscore
127+
ini.with-hyphen = dot and hyphen
128+
ini-with.hyphen = hyphen and dot
129+

ext/standard/tests/general_functions/parse_ini_basic.phpt

+39-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ basicqval=FUBAR_QUOTES_VARIABLE
88

99
$ini_file = dirname(__FILE__)."/parse_ini_basic.data";
1010

11+
define('TEST_CONSTANT', 'this_is_test_constant');
12+
1113
var_dump(parse_ini_file($ini_file, 1));
1214

1315
echo "Done.\n";
1416
?>
1517
--EXPECTF--
16-
array(22) {
18+
array(25) {
1719
["basic"]=>
18-
array(14) {
20+
array(15) {
1921
["basicval"]=>
2022
string(3) "bar"
2123
["longval"]=>
@@ -44,6 +46,8 @@ array(22) {
4446
string(51) "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
4547
["php_constant"]=>
4648
string(4) "6143"
49+
["user_constant"]=>
50+
string(21) "this_is_test_constant"
4751
}
4852
["basic with whitespace"]=>
4953
array(13) {
@@ -235,5 +239,38 @@ array(22) {
235239
["bla"]=>
236240
string(3) "bla"
237241
}
242+
["bug #43923"]=>
243+
array(3) {
244+
["curly1"]=>
245+
string(1) "{"
246+
["curly2"]=>
247+
string(1) "{"
248+
["curly3"]=>
249+
string(1) "{"
250+
}
251+
["bug #44019"]=>
252+
array(6) {
253+
["concatenation_before"]=>
254+
string(37) "this_is_test_constant+some_text_after"
255+
["concatenation_middle"]=>
256+
string(54) "some_text_before+this_is_test_constant+some_text_after"
257+
["concatenation_after"]=>
258+
string(38) "some_text_before+this_is_test_constant"
259+
["concatenation_nows_before"]=>
260+
string(37) "this_is_test_constant+some_text_after"
261+
["concatenation_nows_middle"]=>
262+
string(54) "some_text_before+this_is_test_constant+some_text_after"
263+
["concatenation_nows_after"]=>
264+
string(38) "some_text_before+this_is_test_constant"
265+
}
266+
["bug #43915"]=>
267+
array(3) {
268+
["ini_with-hyphen"]=>
269+
string(26) "with hyphen and underscore"
270+
["ini.with-hyphen"]=>
271+
string(14) "dot and hyphen"
272+
["ini-with.hyphen"]=>
273+
string(14) "hyphen and dot"
274+
}
238275
}
239276
Done.

ext/standard/tests/general_functions/parse_ini_booleans.data

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ error_reporting2 = E_ALL&~E_NOTICE
66
error_reporting3 = E_ALL & ~E_NOTICE
77
error_reporting4 = E_ALL & ~E_NOTICE | E_STRICT
88

9-
[true or false]
9+
['true or false']
1010
bool_true = true
1111
bool_yes = yes
1212
bool_on = on

ext/standard/tests/general_functions/parse_ini_booleans.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ array(3) {
1515
["error_reporting values"]=>
1616
array(6) {
1717
["foo"]=>
18-
string(14) "E_ALL E_NOTICE"
18+
string(6) "6143 8"
1919
["error_reporting"]=>
2020
string(4) "6143"
2121
["error_reporting1"]=>

0 commit comments

Comments
 (0)