diff options
Diffstat (limited to 'Zend/zend_language_scanner.l')
-rw-r--r-- | Zend/zend_language_scanner.l | 171 |
1 files changed, 111 insertions, 60 deletions
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 7e60f5cf05..4fb4202264 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -297,30 +297,25 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state) RESET_DOC_COMMENT(); } -ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle) +ZEND_API zend_result zend_lex_tstring(zval *zv, unsigned char *ident) { - zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles); - /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */ - file_handle->opened_path = NULL; - if (file_handle->free_filename) { - file_handle->filename = NULL; + unsigned char *end = ident; + while ((*end >= 'a' && *end <= 'z') || (*end >= 'A' && *end <= 'Z') || *end == '_') { + end++; } -} -ZEND_API zend_result zend_lex_tstring(zval *zv, zend_lexer_ident_ref ident_ref) -{ - char *ident = (char *) SCNG(yy_start) + ident_ref.offset; - size_t length = ident_ref.len; - if (length == sizeof("<?=")-1 && memcmp(ident, "<?=", sizeof("<?=")-1) == 0) { + size_t length = end - ident; + if (length == 0) { + ZEND_ASSERT(ident[0] == '<' && ident[1] == '?' && ident[2] == '='); zend_throw_exception(zend_ce_parse_error, "Cannot use \"<?=\" as an identifier", 0); return FAILURE; } if (SCNG(on_event)) { - SCNG(on_event)(ON_FEEDBACK, T_STRING, 0, ident, length, SCNG(on_event_context)); + SCNG(on_event)(ON_FEEDBACK, T_STRING, 0, (char *) ident, length, SCNG(on_event_context)); } - ZVAL_STRINGL(zv, ident, length); + ZVAL_STRINGL(zv, (char *) ident, length); return SUCCESS; } @@ -537,17 +532,13 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle) if (zend_stream_fixup(file_handle, &buf, &size) == FAILURE) { /* Still add it to open_files to make destroy_file_handle work */ zend_llist_add_element(&CG(open_files), file_handle); + file_handle->in_list = 1; return FAILURE; } ZEND_ASSERT(!EG(exception) && "stream_fixup() should have failed"); zend_llist_add_element(&CG(open_files), file_handle); - if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) { - zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files)); - size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle; - fh->handle.stream.handle = (void*)(((char*)fh) + diff); - file_handle->handle.stream.handle = fh->handle.stream.handle; - } + file_handle->in_list = 1; /* Reset the scanner for scanning the new file */ SCNG(yy_in) = file_handle; @@ -585,7 +576,7 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle) if (file_handle->opened_path) { compiled_filename = zend_string_copy(file_handle->opened_path); } else { - compiled_filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0); + compiled_filename = zend_string_copy(file_handle->filename); } zend_set_compiled_filename(compiled_filename); @@ -601,7 +592,7 @@ END_EXTERN_C() static zend_op_array *zend_compile(int type) { zend_op_array *op_array = NULL; - zend_bool original_in_compilation = CG(in_compilation); + bool original_in_compilation = CG(in_compilation); CG(in_compilation) = 1; CG(ast) = NULL; @@ -631,6 +622,7 @@ static zend_op_array *zend_compile(int type) zend_emit_final_return(type == ZEND_USER_FUNCTION); op_array->line_start = 1; op_array->line_end = last_lineno; + zend_init_static_variables_map_ptr(op_array); pass_two(op_array); zend_oparray_context_end(&original_oparray_context); zend_file_context_end(&original_file_context); @@ -655,9 +647,9 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type) if (open_file_for_scanning(file_handle)==FAILURE) { if (!EG(exception)) { if (type==ZEND_REQUIRE) { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename)); } else { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename); + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename)); } } } else { @@ -669,9 +661,9 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type) } ZEND_API zend_ast *zend_compile_string_to_ast( - zend_string *code, zend_arena **ast_arena, const char *filename) { + zend_string *code, zend_arena **ast_arena, zend_string *filename) { zval code_zv; - zend_bool original_in_compilation; + bool original_in_compilation; zend_lex_state original_lex_state; zend_ast *ast; @@ -715,7 +707,7 @@ zend_op_array *compile_filename(int type, zval *filename) ZVAL_STR(&tmp, zval_get_string(filename)); filename = &tmp; } - zend_stream_init_filename(&file_handle, Z_STRVAL_P(filename)); + zend_stream_init_filename_ex(&file_handle, Z_STR_P(filename)); retval = zend_compile_file(&file_handle, type); if (retval && file_handle.handle.stream.handle) { @@ -737,11 +729,10 @@ zend_op_array *compile_filename(int type, zval *filename) return retval; } -ZEND_API void zend_prepare_string_for_scanning(zval *str, const char *filename) +ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename) { char *buf; size_t size, old_len; - zend_string *new_compiled_filename; /* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */ old_len = Z_STRLEN_P(str); @@ -773,10 +764,7 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, const char *filename) } yy_scan_buffer(buf, size); - - new_compiled_filename = zend_string_init(filename, strlen(filename), 0); - zend_set_compiled_filename(new_compiled_filename); - zend_string_release_ex(new_compiled_filename, 0); + zend_set_compiled_filename(filename); CG(zend_lineno) = 1; CG(increment_lineno) = 0; RESET_DOC_COMMENT(); @@ -809,6 +797,7 @@ zend_op_array *compile_string(zend_string *source_string, const char *filename) zend_lex_state original_lex_state; zend_op_array *op_array = NULL; zval tmp; + zend_string *filename_str; if (ZSTR_LEN(source_string) == 0) { return NULL; @@ -817,7 +806,9 @@ zend_op_array *compile_string(zend_string *source_string, const char *filename) ZVAL_STR_COPY(&tmp, source_string); zend_save_lexical_state(&original_lex_state); - zend_prepare_string_for_scanning(&tmp, filename); + filename_str = zend_string_init(filename, strlen(filename), 0); + zend_prepare_string_for_scanning(&tmp, filename_str); + zend_string_release(filename_str); BEGIN(ST_IN_SCRIPTING); op_array = zend_compile(ZEND_EVAL_CODE); @@ -838,6 +829,7 @@ zend_result highlight_file(const char *filename, zend_syntax_highlighter_ini *sy zend_save_lexical_state(&original_lex_state); if (open_file_for_scanning(&file_handle)==FAILURE) { zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename); + zend_destroy_file_handle(&file_handle); zend_restore_lexical_state(&original_lex_state); return FAILURE; } @@ -851,17 +843,15 @@ zend_result highlight_file(const char *filename, zend_syntax_highlighter_ini *sy return SUCCESS; } -void highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *str_name) +void highlight_string(zend_string *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *filename) { zend_lex_state original_lex_state; - zval tmp; - - if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) { - ZVAL_STR(&tmp, zval_get_string_func(str)); - str = &tmp; - } + zval str_zv; + zend_string *filename_str = zend_string_init(filename, strlen(filename), 0); + ZVAL_STR_COPY(&str_zv, str); zend_save_lexical_state(&original_lex_state); - zend_prepare_string_for_scanning(str, str_name); + zend_prepare_string_for_scanning(&str_zv, filename_str); + zend_string_release(filename_str); BEGIN(INITIAL); zend_highlight(syntax_highlighter_ini); if (SCNG(script_filtered)) { @@ -869,9 +859,7 @@ void highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter SCNG(script_filtered) = NULL; } zend_restore_lexical_state(&original_lex_state); - if (UNEXPECTED(str == &tmp)) { - zval_ptr_dtor(&tmp); - } + zval_ptr_dtor(&str_zv); } ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding) @@ -1023,7 +1011,7 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c /* cache where we started so we can parse after validating */ char *start = s + 1; size_t len = 0; - zend_bool valid = 1; + bool valid = 1; unsigned long codepoint; if (*start != '{') { @@ -1163,9 +1151,9 @@ static const char *next_newline(const char *str, const char *end, size_t *newlin return NULL; } -static zend_bool strip_multiline_string_indentation( - zval *zendlval, int indentation, zend_bool using_spaces, - zend_bool newline_at_start, zend_bool newline_at_end) +static bool strip_multiline_string_indentation( + zval *zendlval, int indentation, bool using_spaces, + bool newline_at_start, bool newline_at_end) { const char *str = Z_STRVAL_P(zendlval), *end = str + Z_STRLEN_P(zendlval); char *copy = Z_STRVAL_P(zendlval); @@ -1372,6 +1360,7 @@ DNUM ({LNUM}?"."{LNUM})|({LNUM}"."{LNUM}?) EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM}) HNUM "0x"[0-9a-fA-F]+(_[0-9a-fA-F]+)* BNUM "0b"[01]+(_[01]+)* +ONUM "0o"[0-7]+(_[0-7]+)* LABEL [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* WHITESPACE [ \n\r\t]+ TABS_AND_SPACES [ \t]* @@ -1549,6 +1538,19 @@ NEWLINE ("\r"|"\n"|"\r\n") RETURN_TOKEN_WITH_IDENT(T_TRAIT); } +/* + * The enum keyword must be followed by whitespace and another identifier. + * This avoids the BC break of using enum in classes, namespaces, functions and constants. + */ +<ST_IN_SCRIPTING>"enum"{WHITESPACE}("extends"|"implements") { + yyless(4); + RETURN_TOKEN_WITH_STR(T_STRING, 0); +} +<ST_IN_SCRIPTING>"enum"{WHITESPACE}[a-zA-Z_\x80-\xff] { + yyless(4); + RETURN_TOKEN_WITH_IDENT(T_ENUM); +} + <ST_IN_SCRIPTING>"extends" { RETURN_TOKEN_WITH_IDENT(T_EXTENDS); } @@ -1918,7 +1920,7 @@ NEWLINE ("\r"|"\n"|"\r\n") /* The +/- 2 skips "0b" */ size_t len = yyleng - 2; char *end, *bin = yytext + 2; - zend_bool contains_underscores; + bool contains_underscores; /* Skip any leading 0s */ while (len > 0 && (*bin == '0' || *bin == '_')) { @@ -1956,11 +1958,61 @@ NEWLINE ("\r"|"\n"|"\r\n") } } +<ST_IN_SCRIPTING>{ONUM} { + /* The +/- 2 skips "0o" */ + size_t len = yyleng - 2; + char *end, *octal = yytext + 2; + bool contains_underscores = (memchr(octal, '_', len) != NULL); + + /* Skip any leading 0s */ + while (len > 0 && (*octal == '0' || *octal == '_')) { + ++octal; + --len; + } + + if (len == 0) { + ZVAL_LONG(zendlval, 0); + RETURN_TOKEN_WITH_VAL(T_LNUMBER); + } + + if (contains_underscores) { + octal = estrndup(octal, len); + strip_underscores(octal, &len); + } + + errno = 0; + + ZVAL_LONG(zendlval, ZEND_STRTOL(octal, &end, 8)); + + ZEND_ASSERT(end == octal + len); + + if (!errno) { + if (contains_underscores) { + efree(octal); + } + RETURN_TOKEN_WITH_VAL(T_LNUMBER); + } + + /* Overflow */ + ZEND_ASSERT(errno == ERANGE); + /* Reset errno */ + errno = 0; + + /* zend_oct_strtod skips leading '0' */ + ZVAL_DOUBLE(zendlval, zend_oct_strtod(octal, (const char **)&end)); + ZEND_ASSERT(!errno); + ZEND_ASSERT(end == octal + len); + if (contains_underscores) { + efree(octal); + } + RETURN_TOKEN_WITH_VAL(T_DNUMBER); +} + <ST_IN_SCRIPTING>{LNUM} { size_t len = yyleng; char *end, *lnum = yytext; - zend_bool is_octal = lnum[0] == '0'; - zend_bool contains_underscores = (memchr(lnum, '_', len) != NULL); + bool is_octal = lnum[0] == '0'; + bool contains_underscores = (memchr(lnum, '_', len) != NULL); if (contains_underscores) { lnum = estrndup(lnum, len); @@ -2023,7 +2075,7 @@ NEWLINE ("\r"|"\n"|"\r\n") /* The +/- 2 skips "0x" */ size_t len = yyleng - 2; char *end, *hex = yytext + 2; - zend_bool contains_underscores; + bool contains_underscores; /* Skip any leading 0s */ while (len > 0 && (*hex == '0' || *hex == '_')) { @@ -2077,7 +2129,7 @@ string: RETURN_TOKEN_WITH_VAL(T_NUM_STRING); } -<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */ +<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM}|{ONUM} { /* Offset must be treated as a string */ if (yyleng == 1) { ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext))); } else { @@ -2090,7 +2142,7 @@ string: const char *end; size_t len = yyleng; char *dnum = yytext; - zend_bool contains_underscores = (memchr(dnum, '_', len) != NULL); + bool contains_underscores = (memchr(dnum, '_', len) != NULL); if (contains_underscores) { dnum = estrndup(dnum, len); @@ -2528,7 +2580,7 @@ skip_escape_conversion: unsigned char *saved_cursor; int bprefix = (yytext[0] != '<') ? 1 : 0, spacing = 0, indentation = 0; zend_heredoc_label *heredoc_label = emalloc(sizeof(zend_heredoc_label)); - zend_bool is_heredoc = 1; + bool is_heredoc = 1; CG(zend_lineno)++; heredoc_label->length = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); @@ -2909,7 +2961,7 @@ heredoc_scan_done: ZVAL_STRINGL(zendlval, yytext, yyleng - newline); if (!SCNG(heredoc_scan_ahead) && !EG(exception) && PARSER_MODE()) { - zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r'; + bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r'; zend_string *copy = Z_STR_P(zendlval); if (!strip_multiline_string_indentation( @@ -3010,7 +3062,7 @@ nowdoc_scan_done: ZVAL_STRINGL(zendlval, yytext, yyleng - newline); if (!EG(exception) && spacing != -1 && PARSER_MODE()) { - zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r'; + bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r'; if (!strip_multiline_string_indentation( zendlval, indentation, spacing == HEREDOC_USING_SPACES, newline_at_start, newline != 0)) { @@ -3050,8 +3102,7 @@ emit_token: emit_token_with_ident: if (PARSER_MODE()) { - elem->ident.offset = SCNG(yy_text) - SCNG(yy_start); - elem->ident.len = SCNG(yy_leng); + elem->ident = SCNG(yy_text); } if (SCNG(on_event)) { SCNG(on_event)(ON_TOKEN, token, start_line, yytext, yyleng, SCNG(on_event_context)); |