mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Support specifying start position in compile_string
Add additional zend_compile_position argument, which can be either AT_SHEBANG, AT_OPEN_TAG or AFTER_OPEN_TAG. The previous behavior corresponds to AFTER_OPEN_TAG. Closes GH-7462.
This commit is contained in:
parent
ca07cf3079
commit
5bda4cd25a
14 changed files with 137 additions and 17 deletions
|
@ -80,7 +80,7 @@ static inline uint32_t zend_alloc_cache_slot(void) {
|
|||
}
|
||||
|
||||
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
|
||||
ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename);
|
||||
ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position);
|
||||
|
||||
#ifndef ZTS
|
||||
ZEND_API zend_compiler_globals compiler_globals;
|
||||
|
|
|
@ -740,6 +740,12 @@ struct _zend_execute_data {
|
|||
|
||||
#include "zend_globals.h"
|
||||
|
||||
typedef enum _zend_compile_position {
|
||||
ZEND_COMPILE_POSITION_AT_SHEBANG = 0,
|
||||
ZEND_COMPILE_POSITION_AT_OPEN_TAG,
|
||||
ZEND_COMPILE_POSITION_AFTER_OPEN_TAG
|
||||
} zend_compile_position;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
void init_compiler(void);
|
||||
|
@ -752,7 +758,7 @@ void zend_file_context_begin(zend_file_context *prev_context);
|
|||
void zend_file_context_end(zend_file_context *prev_context);
|
||||
|
||||
extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
|
||||
extern ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename);
|
||||
extern ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position);
|
||||
|
||||
ZEND_API int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem);
|
||||
void startup_scanner(void);
|
||||
|
@ -805,7 +811,7 @@ zend_string *zval_make_interned_string(zval *zv);
|
|||
struct _zend_arena;
|
||||
|
||||
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type);
|
||||
ZEND_API zend_op_array *compile_string(zend_string *source_string, const char *filename);
|
||||
ZEND_API zend_op_array *compile_string(zend_string *source_string, const char *filename, zend_compile_position position);
|
||||
ZEND_API zend_op_array *compile_filename(int type, zend_string *filename);
|
||||
ZEND_API zend_ast *zend_compile_string_to_ast(
|
||||
zend_string *code, struct _zend_arena **ast_arena, zend_string *filename);
|
||||
|
|
|
@ -4394,7 +4394,7 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval
|
|||
break;
|
||||
case ZEND_EVAL: {
|
||||
char *eval_desc = zend_make_compiled_string_description("eval()'d code");
|
||||
new_op_array = zend_compile_string(inc_filename, eval_desc);
|
||||
new_op_array = zend_compile_string(inc_filename, eval_desc, ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
efree(eval_desc);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1223,7 +1223,7 @@ ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *re
|
|||
|
||||
original_compiler_options = CG(compiler_options);
|
||||
CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
|
||||
new_op_array = zend_compile_string(code_str, string_name);
|
||||
new_op_array = zend_compile_string(code_str, string_name, ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
CG(compiler_options) = original_compiler_options;
|
||||
|
||||
if (new_op_array) {
|
||||
|
|
|
@ -782,7 +782,7 @@ ZEND_API size_t zend_get_scanned_file_offset(void)
|
|||
return offset;
|
||||
}
|
||||
|
||||
zend_op_array *compile_string(zend_string *source_string, const char *filename)
|
||||
zend_op_array *compile_string(zend_string *source_string, const char *filename, zend_compile_position position)
|
||||
{
|
||||
zend_lex_state original_lex_state;
|
||||
zend_op_array *op_array = NULL;
|
||||
|
@ -799,7 +799,19 @@ zend_op_array *compile_string(zend_string *source_string, const char *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);
|
||||
|
||||
switch (position) {
|
||||
case ZEND_COMPILE_POSITION_AT_SHEBANG:
|
||||
BEGIN(SHEBANG);
|
||||
break;
|
||||
case ZEND_COMPILE_POSITION_AT_OPEN_TAG:
|
||||
BEGIN(INITIAL);
|
||||
break;
|
||||
case ZEND_COMPILE_POSITION_AFTER_OPEN_TAG:
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
break;
|
||||
}
|
||||
|
||||
op_array = zend_compile(ZEND_EVAL_CODE);
|
||||
|
||||
zend_restore_lexical_state(&original_lex_state);
|
||||
|
|
|
@ -199,6 +199,41 @@ static ZEND_FUNCTION(zend_string_or_stdclass)
|
|||
}
|
||||
}
|
||||
|
||||
static ZEND_FUNCTION(zend_test_compile_string)
|
||||
{
|
||||
zend_string *source_string = NULL;
|
||||
zend_string *filename = NULL;
|
||||
zend_long position = ZEND_COMPILE_POSITION_AT_OPEN_TAG;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 3)
|
||||
Z_PARAM_STR(source_string)
|
||||
Z_PARAM_STR(filename)
|
||||
Z_PARAM_LONG(position)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
zend_op_array *op_array = NULL;
|
||||
|
||||
op_array = compile_string(source_string, ZSTR_VAL(filename), position);
|
||||
|
||||
if (op_array) {
|
||||
zval retval;
|
||||
|
||||
zend_try {
|
||||
ZVAL_UNDEF(&retval);
|
||||
zend_execute(op_array, &retval);
|
||||
} zend_catch {
|
||||
destroy_op_array(op_array);
|
||||
efree_size(op_array, sizeof(zend_op_array));
|
||||
zend_bailout();
|
||||
} zend_end_try();
|
||||
|
||||
destroy_op_array(op_array);
|
||||
efree_size(op_array, sizeof(zend_op_array));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
|
||||
static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
|
||||
{
|
||||
|
|
|
@ -62,6 +62,8 @@ namespace {
|
|||
|
||||
function zend_test_void_return(): void {}
|
||||
|
||||
function zend_test_compile_string(string $source_string, string $filename, int $position): void {}
|
||||
|
||||
/** @deprecated */
|
||||
function zend_test_deprecated(mixed $arg = null): void {}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 53832c784e59195e8ef41710c1e4e778f396c99b */
|
||||
* Stub hash: 91ffc3205c6ac7b07953c9446e9cb9988d893dd4 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -10,6 +10,12 @@ ZEND_END_ARG_INFO()
|
|||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_void_return, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_compile_string, 0, 3, IS_VOID, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, source_string, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, position, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_deprecated, 0, 0, IS_VOID, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg, IS_MIXED, 0, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -84,6 +90,7 @@ ZEND_END_ARG_INFO()
|
|||
static ZEND_FUNCTION(zend_test_array_return);
|
||||
static ZEND_FUNCTION(zend_test_nullable_array_return);
|
||||
static ZEND_FUNCTION(zend_test_void_return);
|
||||
static ZEND_FUNCTION(zend_test_compile_string);
|
||||
static ZEND_FUNCTION(zend_test_deprecated);
|
||||
static ZEND_FUNCTION(zend_create_unterminated_string);
|
||||
static ZEND_FUNCTION(zend_terminate_string);
|
||||
|
@ -111,6 +118,7 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(zend_test_array_return, arginfo_zend_test_array_return)
|
||||
ZEND_FE(zend_test_nullable_array_return, arginfo_zend_test_nullable_array_return)
|
||||
ZEND_FE(zend_test_void_return, arginfo_zend_test_void_return)
|
||||
ZEND_FE(zend_test_compile_string, arginfo_zend_test_compile_string)
|
||||
ZEND_DEP_FE(zend_test_deprecated, arginfo_zend_test_deprecated)
|
||||
ZEND_FE(zend_create_unterminated_string, arginfo_zend_create_unterminated_string)
|
||||
ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string)
|
||||
|
|
55
ext/zend_test/tests/zend_test_compile_string.phpt
Normal file
55
ext/zend_test/tests/zend_test_compile_string.phpt
Normal file
|
@ -0,0 +1,55 @@
|
|||
--TEST--
|
||||
Zend: Test compile string
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
define('ZEND_COMPILE_POSITION_AT_SHEBANG', 0);
|
||||
define('ZEND_COMPILE_POSITION_AT_OPEN_TAG', 1);
|
||||
define('ZEND_COMPILE_POSITION_AFTER_OPEN_TAG', 2);
|
||||
|
||||
$source_string = <<<EOF
|
||||
#!/path/to/php
|
||||
<?php
|
||||
var_dump('php');
|
||||
EOF;
|
||||
|
||||
zend_test_compile_string($source_string, 'Source string', ZEND_COMPILE_POSITION_AT_SHEBANG);
|
||||
|
||||
$source_string = <<<EOF
|
||||
#!/path/to/php
|
||||
<?php
|
||||
var_dump('php');
|
||||
EOF;
|
||||
|
||||
zend_test_compile_string($source_string, 'Source string', ZEND_COMPILE_POSITION_AT_OPEN_TAG);
|
||||
|
||||
$source_string = <<<EOF
|
||||
<?php
|
||||
var_dump('php');
|
||||
EOF;
|
||||
|
||||
zend_test_compile_string($source_string, 'Source string', ZEND_COMPILE_POSITION_AT_OPEN_TAG);
|
||||
|
||||
$source_string = <<<EOF
|
||||
var_dump('php');
|
||||
EOF;
|
||||
|
||||
zend_test_compile_string($source_string, 'Source string', ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
|
||||
$source_string = <<<EOF
|
||||
<?php
|
||||
var_dump('php');
|
||||
EOF;
|
||||
|
||||
zend_test_compile_string($source_string, 'Source string', ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "php"
|
||||
#!/path/to/php
|
||||
string(3) "php"
|
||||
string(3) "php"
|
||||
string(3) "php"
|
||||
|
||||
Parse error: syntax error, unexpected token "<", expecting end of file in Source string on line 1
|
|
@ -60,15 +60,17 @@ static void fuzzer_execute_ex(zend_execute_data *execute_data) {
|
|||
}
|
||||
}
|
||||
|
||||
static zend_op_array *(*orig_compile_string)(zend_string *source_string, const char *filename);
|
||||
static zend_op_array *(*orig_compile_string)(
|
||||
zend_string *source_string, const char *filename, zend_compile_position position);
|
||||
|
||||
static zend_op_array *fuzzer_compile_string(zend_string *str, const char *filename) {
|
||||
static zend_op_array *fuzzer_compile_string(
|
||||
zend_string *str, const char *filename, zend_compile_position position) {
|
||||
if (ZSTR_LEN(str) > MAX_SIZE) {
|
||||
/* Avoid compiling huge inputs via eval(). */
|
||||
fuzzer_bailout();
|
||||
}
|
||||
|
||||
return orig_compile_string(str, filename);
|
||||
return orig_compile_string(str, filename, position);
|
||||
}
|
||||
|
||||
static void (*orig_execute_internal)(zend_execute_data *execute_data, zval *return_value);
|
||||
|
|
|
@ -270,7 +270,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
|
|||
|
||||
zend_op_array *(*compile_file)(zend_file_handle *file_handle, int type);
|
||||
zend_op_array *(*init_compile_file)(zend_file_handle *file_handle, int type);
|
||||
zend_op_array *(*compile_string)(zend_string *source_string, const char *filename);
|
||||
zend_op_array *(*compile_string)(zend_string *source_string, const char *filename, zend_compile_position position);
|
||||
HashTable file_sources;
|
||||
|
||||
zend_arena *oplog_arena; /* arena for storing oplog */
|
||||
|
|
|
@ -878,7 +878,7 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co
|
|||
|
||||
bp_code = zend_string_concat3(
|
||||
"return ", sizeof("return ")-1, expr, expr_len, ";", sizeof(";")-1);
|
||||
new_break.ops = zend_compile_string(bp_code, "Conditional Breakpoint Code");
|
||||
new_break.ops = zend_compile_string(bp_code, "Conditional Breakpoint Code", ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
zend_string_release(bp_code);
|
||||
|
||||
if (new_break.ops) {
|
||||
|
|
|
@ -309,7 +309,7 @@ zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) {
|
|||
return op_array;
|
||||
}
|
||||
|
||||
zend_op_array *phpdbg_compile_string(zend_string *source_string, const char *filename) {
|
||||
zend_op_array *phpdbg_compile_string(zend_string *source_string, const char *filename, zend_compile_position position) {
|
||||
zend_string *fake_name;
|
||||
zend_op_array *op_array;
|
||||
phpdbg_file_source *dataptr;
|
||||
|
@ -317,7 +317,7 @@ zend_op_array *phpdbg_compile_string(zend_string *source_string, const char *fil
|
|||
char *bufptr, *endptr;
|
||||
|
||||
if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) {
|
||||
return PHPDBG_G(compile_string)(source_string, filename);
|
||||
return PHPDBG_G(compile_string)(source_string, filename, position);
|
||||
}
|
||||
|
||||
dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint32_t) * ZSTR_LEN(source_string));
|
||||
|
@ -332,7 +332,7 @@ zend_op_array *phpdbg_compile_string(zend_string *source_string, const char *fil
|
|||
dataptr->lines = ++line;
|
||||
dataptr->line[line] = endptr - dataptr->buf;
|
||||
|
||||
op_array = PHPDBG_G(compile_string)(source_string, filename);
|
||||
op_array = PHPDBG_G(compile_string)(source_string, filename, position);
|
||||
|
||||
if (op_array == NULL) {
|
||||
efree(dataptr->buf);
|
||||
|
|
|
@ -514,7 +514,7 @@ exec_code:
|
|||
} /* }}} */
|
||||
|
||||
int phpdbg_compile_stdin(zend_string *code) {
|
||||
PHPDBG_G(ops) = zend_compile_string(code, "Standard input code");
|
||||
PHPDBG_G(ops) = zend_compile_string(code, "Standard input code", ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
|
||||
zend_string_release(code);
|
||||
|
||||
if (EG(exception)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue