From dbace93c1dcbb1619e12e51c973c58fa7b016847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 14 Nov 2024 17:30:18 +0100 Subject: [PATCH 1/5] Dummy --- Zend/zend_compile.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8e4221673c4cf..b7e2aa351ad6d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4954,6 +4954,79 @@ static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args) return SUCCESS; } +static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel); + +static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *args) /* {{{ */ +{ + /* Bail out if we do not have exactly two parameters. */ + if (args->children != 2) { + return FAILURE; + } + + zend_eval_const_expr(&args->child[0]); + /* Bail out if the first parameter is not a Closure. */ + if (args->child[0]->kind != ZEND_AST_CLOSURE) { + printf("!closure\n"); + return FAILURE; + } + zend_ast_decl *closure_ast = (zend_ast_decl *) args->child[0]; + zend_ast *uses_ast = closure_ast->child[1]; + /* Bail out if the Closure is not static. */ + if (!(closure_ast->flags & ZEND_ACC_STATIC)) { + printf("!static\n"); + return FAILURE; + } + /* Bail out if the Closure imports stuff from the outer scope. */ + if (uses_ast) { + printf("uses\n"); + return FAILURE; + } + + znode closure; + zend_compile_func_decl(&closure, args->child[0], 0); + + znode expr_node, reset_node, value_node, key_node; + zend_op *opline; + uint32_t opnum_reset, opnum_fetch; + zend_compile_expr(&expr_node, args->child[1]); + + opnum_reset = get_next_op_number(); + opline = zend_emit_op(&reset_node, ZEND_FE_RESET_R, &expr_node, NULL); + + zend_begin_loop(ZEND_FE_FREE, &reset_node, 0); + + opnum_fetch = get_next_op_number(); + opline = zend_emit_op(NULL, ZEND_FE_FETCH_R, &reset_node, NULL); + + opline->op2_type = IS_VAR; + opline->op2.var = get_temporary_variable(); + GET_NODE(&value_node, opline->op2); + zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, &closure); + uint32_t opnum_init = get_next_op_number() - 1; + opline = &CG(active_op_array)->opcodes[opnum_init]; + opline->extended_value = 1; + opline = zend_emit_op(NULL, ZEND_SEND_VAR, &value_node, NULL); + opline->op2.opline_num = 1; + zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL); + + zend_emit_jump(opnum_fetch); + + opline = &CG(active_op_array)->opcodes[opnum_reset]; + opline->op2.opline_num = get_next_op_number(); + + opline = &CG(active_op_array)->opcodes[opnum_fetch]; + opline->extended_value = get_next_op_number(); + + zend_end_loop(opnum_fetch, &reset_node); + + opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL); + + result->op_type = IS_CONST; + ZVAL_LONG(&result->u.constant, 1); + + return SUCCESS; +} + static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ { if (zend_string_equals_literal(lcname, "strlen")) { @@ -5022,6 +5095,8 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string * return zend_compile_func_array_key_exists(result, args); } else if (zend_string_equals_literal(lcname, "sprintf")) { return zend_compile_func_sprintf(result, args); + } else if (zend_string_equals_literal(lcname, "array_map")) { + return zend_compile_func_array_map(result, args); } else { return FAILURE; } From 872ff405b3376b0a123b19047c03a44e6cd71139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 14 Nov 2024 17:38:57 +0100 Subject: [PATCH 2/5] Dummy --- Zend/zend_compile.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b7e2aa351ad6d..1de0cd6ca9d65 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5001,13 +5001,11 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opline->op2_type = IS_VAR; opline->op2.var = get_temporary_variable(); GET_NODE(&value_node, opline->op2); - zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, &closure); - uint32_t opnum_init = get_next_op_number() - 1; - opline = &CG(active_op_array)->opcodes[opnum_init]; + opline = zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, &closure); opline->extended_value = 1; - opline = zend_emit_op(NULL, ZEND_SEND_VAR, &value_node, NULL); + opline = zend_emit_op(NULL, ZEND_SEND_VAR_EX, &value_node, NULL); opline->op2.opline_num = 1; - zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL); + zend_emit_op(NULL, ZEND_DO_FCALL, NULL, NULL); zend_emit_jump(opnum_fetch); From 365ee7c8ebd336d8daa98a140c5ef1a1c9ff99d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 15 Nov 2024 11:41:10 +0100 Subject: [PATCH 3/5] Dummy --- Zend/zend_compile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 1de0cd6ca9d65..562f1668351ba 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4982,9 +4982,6 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg return FAILURE; } - znode closure; - zend_compile_func_decl(&closure, args->child[0], 0); - znode expr_node, reset_node, value_node, key_node; zend_op *opline; uint32_t opnum_reset, opnum_fetch; @@ -4997,6 +4994,8 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opnum_fetch = get_next_op_number(); opline = zend_emit_op(NULL, ZEND_FE_FETCH_R, &reset_node, NULL); + znode closure; + zend_compile_func_decl(&closure, args->child[0], 0); opline->op2_type = IS_VAR; opline->op2.var = get_temporary_variable(); From e33b266e0aa3e470e901c633bd92272ca6ba7814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 15 Nov 2024 13:09:08 +0100 Subject: [PATCH 4/5] Fix --- Zend/zend_compile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 562f1668351ba..0a1e149708792 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4982,7 +4982,7 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg return FAILURE; } - znode expr_node, reset_node, value_node, key_node; + znode expr_node, reset_node, value_node/*, key_node*/; zend_op *opline; uint32_t opnum_reset, opnum_fetch; zend_compile_expr(&expr_node, args->child[1]); @@ -5004,6 +5004,7 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opline->extended_value = 1; opline = zend_emit_op(NULL, ZEND_SEND_VAR_EX, &value_node, NULL); opline->op2.opline_num = 1; + opline->result.var = EX_NUM_TO_VAR(1 - 1); zend_emit_op(NULL, ZEND_DO_FCALL, NULL, NULL); zend_emit_jump(opnum_fetch); From d7158764114b3f6f673a00d8c7ef48f3532cfe7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 15 Nov 2024 13:24:58 +0100 Subject: [PATCH 5/5] Dummy --- Zend/zend_compile.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0a1e149708792..46c2af37f10c1 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4982,6 +4982,9 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg return FAILURE; } + znode closure; + zend_compile_func_decl(&closure, args->child[0], 0); + znode expr_node, reset_node, value_node/*, key_node*/; zend_op *opline; uint32_t opnum_reset, opnum_fetch; @@ -4994,8 +4997,6 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opnum_fetch = get_next_op_number(); opline = zend_emit_op(NULL, ZEND_FE_FETCH_R, &reset_node, NULL); - znode closure; - zend_compile_func_decl(&closure, args->child[0], 0); opline->op2_type = IS_VAR; opline->op2.var = get_temporary_variable(); @@ -5005,7 +5006,10 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opline = zend_emit_op(NULL, ZEND_SEND_VAR_EX, &value_node, NULL); opline->op2.opline_num = 1; opline->result.var = EX_NUM_TO_VAR(1 - 1); - zend_emit_op(NULL, ZEND_DO_FCALL, NULL, NULL); + znode return_value; + zend_emit_op(&return_value, ZEND_DO_FCALL, NULL, NULL); +/* opline = zend_emit_op(NULL, ZEND_ASSIGN_DIM, result, NULL); + zend_emit_op_data(&return_value);*/ zend_emit_jump(opnum_fetch);