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:
codinghuang 2021-09-05 00:53:51 +08:00 committed by Nikita Popov
parent ca07cf3079
commit 5bda4cd25a
14 changed files with 137 additions and 17 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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)
{

View file

@ -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 {}

View file

@ -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)

View 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

View file

@ -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);

View file

@ -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 */

View file

@ -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) {

View file

@ -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);

View file

@ -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)) {