mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fix encoding declaration handling
As the encoding declaration influences lexing it needs to be immidiately handled in the parser.
This commit is contained in:
parent
2a26cbb70e
commit
458f67cd21
5 changed files with 69 additions and 66 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5113,6 +5113,52 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) {
|
|||
efree(jmp_opnums);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
|
||||
new_encoding = zend_multibyte_fetch_encoding(encoding_name->val TSRMLS_CC);
|
||||
if (!new_encoding) {
|
||||
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);
|
||||
zend_multibyte_set_filter(new_encoding TSRMLS_CC);
|
||||
|
||||
/* need to re-scan if input filter changed */
|
||||
if (old_input_filter != LANG_SCNG(input_filter) ||
|
||||
(old_input_filter && new_encoding != old_encoding)) {
|
||||
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];
|
||||
|
@ -5125,68 +5171,28 @@ void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
|
|||
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")) {
|
||||
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);
|
||||
} 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 (CG(multibyte)) {
|
||||
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);
|
||||
if (!new_encoding) {
|
||||
zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(value_zv));
|
||||
} else {
|
||||
old_input_filter = LANG_SCNG(input_filter);
|
||||
old_encoding = LANG_SCNG(script_encoding);
|
||||
zend_multibyte_set_filter(new_encoding TSRMLS_CC);
|
||||
|
||||
/* need to re-scan if input filter changed */
|
||||
if (old_input_filter != LANG_SCNG(input_filter) ||
|
||||
(old_input_filter && new_encoding != old_encoding)) {
|
||||
zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
|
||||
"Zend multibyte feature is turned off by settings");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue