com php-src: Fix encoding declaration handling: Zend/tests/decl are_001.phpt Zend/tests/declare_003.phpt Zend/zend_compile.c Zend/zend_compile.h
Zend/zen d_language_parser.y
| From: | Nikita Popov | Date: | Mon, 18 Aug 2014 14:27:53 +0000 |
| Subject: | com php-src: Fix encoding declaration handling: Zend/tests/decl are_001.phpt Zend/tests/declare_003.phpt Zend/zend_compile.c Zend/zend_compile.h Zend/zen d_language_parser.y |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-80857@lists.php.net to get a copy of this message | ||
Commit: 458f67cd2109620c5f59305a56c64f07c886720d
Author: Nikita Popov <nikic@php.net> Mon, 18 Aug 2014 16:07:18 +0200
Parents: 2a26cbb70e11c045cbb21966c1053e41b805d18f
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=458f67cd2109620c5f59305a56c64f07c886720d
Log:
Fix encoding declaration handling
As the encoding declaration influences lexing it needs to be
immidiately handled in the parser.
Changed paths:
M Zend/tests/declare_001.phpt
M Zend/tests/declare_003.phpt
M Zend/zend_compile.c
M Zend/zend_compile.h
M Zend/zend_language_parser.y
Diff:
diff --git a/Zend/tests/declare_001.phpt b/Zend/tests/declare_001.phpt
index 21d7978..4eff180 100644
--- a/Zend/tests/declare_001.phpt
+++ b/Zend/tests/declare_001.phpt
@@ -13,7 +13,6 @@ zend.multibyte=1
declare(encoding = 1);
declare(encoding = 112313123213131232100);
-declare(encoding = NULL);
declare(encoding = 'utf-8');
declare(encoding = M_PI);
@@ -25,6 +24,4 @@ Warning: Unsupported encoding [1] in %sdeclare_001.php on line %d
Warning: Unsupported encoding [1.1231312321313E+20] in %sdeclare_001.php on line %d
-Warning: Unsupported encoding [] in %sdeclare_001.php on line %d
-
-Fatal error: Cannot use constants as encoding in %sdeclare_001.php on line %d
+Fatal error: Encoding must be a literal in %s on line %d
diff --git a/Zend/tests/declare_003.phpt b/Zend/tests/declare_003.phpt
index 2980f75..2f3e887 100644
--- a/Zend/tests/declare_003.phpt
+++ b/Zend/tests/declare_003.phpt
@@ -8,7 +8,6 @@ zend.multibyte=1
declare(encoding = 1);
declare(encoding = 11111111111111);
-declare(encoding = NULL);
declare(encoding = M_PI);
print 'DONE';
@@ -19,6 +18,4 @@ Warning: Unsupported encoding [1] in %sdeclare_003.php on line %d
Warning: Unsupported encoding [11111111111111] in %sdeclare_003.php on line %d
-Warning: Unsupported encoding [] in %sdeclare_003.php on line %d
-
-Fatal error: Cannot use constants as encoding in %sdeclare_003.php on line %d
+Fatal error: Encoding must be a literal in %s on line %d
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 4a04862..5b35233 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5113,61 +5113,31 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) {
efree(jmp_opnums);
}
-void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
- zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
- zend_ast *stmt_ast = ast->child[1];
- zend_declarables orig_declarables = CG(declarables);
+/* Encoding declarations must already be handled during parsing */
+void zend_handle_encoding_declaration(zend_ast_list *declares TSRMLS_DC) {
zend_uint i;
-
for (i = 0; i < declares->children; ++i) {
zend_ast *declare_ast = declares->child[i];
zend_ast *name_ast = declare_ast->child[0];
zend_ast *value_ast = declare_ast->child[1];
-
zend_string *name = zend_ast_get_str(name_ast);
- zval value_zv;
-
- zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
-
- if (zend_str_equals_literal_ci(name, "ticks")) {
- convert_to_long(&value_zv);
- ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
- } else if (zend_str_equals_literal_ci(name, "encoding")) {
- if (Z_TYPE(value_zv) == IS_CONSTANT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use constants as encoding");
- }
-
- /*
- * Check that the pragma comes before any opcodes. If the compilation
- * got as far as this, the previous portion of the script must have been
- * parseable according to the .ini script_encoding setting. We still
- * want to tell them to put declare() at the top.
- */
- {
- zend_uint num = CG(active_op_array)->last;
- /* ignore ZEND_EXT_STMT and ZEND_TICKS */
- while (num > 0 &&
- (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
- CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
- --num;
- }
- if (num > 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
- "the very first statement in the script");
- }
+ if (zend_str_equals_literal_ci(name, "encoding")) {
+ if (value_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Encoding must be a literal");
}
if (CG(multibyte)) {
+ zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
+
const zend_encoding *new_encoding, *old_encoding;
zend_encoding_filter old_input_filter;
CG(encoding_declared) = 1;
- convert_to_string(&value_zv);
- new_encoding = zend_multibyte_fetch_encoding(Z_STRVAL(value_zv) TSRMLS_CC);
+ new_encoding = zend_multibyte_fetch_encoding(encoding_name->val TSRMLS_CC);
if (!new_encoding) {
- zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(value_zv));
+ zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", encoding_name->val);
} else {
old_input_filter = LANG_SCNG(input_filter);
old_encoding = LANG_SCNG(script_encoding);
@@ -5179,14 +5149,50 @@ void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
}
}
+
+ STR_RELEASE(encoding_name);
} else {
zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
"Zend multibyte feature is turned off by settings");
}
+ }
+ }
+}
+
+void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
+ zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
+ zend_ast *stmt_ast = ast->child[1];
+ zend_declarables orig_declarables = CG(declarables);
+ zend_uint i;
+
+ for (i = 0; i < declares->children; ++i) {
+ zend_ast *declare_ast = declares->child[i];
+ zend_ast *name_ast = declare_ast->child[0];
+ zend_ast *value_ast = declare_ast->child[1];
+
+ zend_string *name = zend_ast_get_str(name_ast);
+ if (zend_str_equals_literal_ci(name, "ticks")) {
+ zval value_zv;
+ zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
+ convert_to_long(&value_zv);
+ ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
zval_dtor(&value_zv);
+ } else if (zend_str_equals_literal_ci(name, "encoding")) {
+ /* Encoding declaration was already handled during parsing. Here we
+ * only check that it is the first statement in the file. */
+ zend_uint num = CG(active_op_array)->last;
+ while (num > 0 &&
+ (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
+ CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
+ --num;
+ }
+
+ if (num > 0) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
+ "the very first statement in the script");
+ }
} else {
zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", name->val);
- zval_dtor(&value_zv);
}
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 41761ab..cecba02 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -453,6 +453,7 @@ void zend_emit_final_return(zval *zv TSRMLS_DC);
zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
zend_uint zend_add_member_modifier(zend_uint flags, zend_uint new_flag);
zend_ast_list *zend_ast_append_doc_comment(zend_ast_list *list TSRMLS_DC);
+void zend_handle_encoding_declaration(zend_ast_list *declares TSRMLS_DC);
/* parser-driven code generators */
void zend_do_free(znode *op1 TSRMLS_DC);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index a7e75fb..340371a 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -349,8 +349,10 @@ unticked_statement:
foreach_statement
{ $$.ast = zend_ast_create(ZEND_AST_FOREACH,
$3.ast, $7.ast, $5.ast, $9.ast); }
- | T_DECLARE '(' const_list ')' declare_statement
- { $$.ast = zend_ast_create(ZEND_AST_DECLARE, $3.ast, $5.ast); }
+ | T_DECLARE '(' const_list ')'
+ { zend_handle_encoding_declaration($3.list TSRMLS_CC); }
+ declare_statement
+ { $$.ast = zend_ast_create(ZEND_AST_DECLARE, $3.ast, $6.ast); }
| ';' /* empty statement */ { $$.ast = NULL; }
| T_TRY '{' inner_statement_list '}' catch_list finally_statement
{ $$.ast = zend_ast_create(ZEND_AST_TRY, $3.ast, $5.ast, $6.ast); }