]> granicus.if.org Git - php/commitdiff
Forbid double use() and use() of param
authorNikita Popov <nikic@php.net>
Tue, 12 Jan 2016 14:18:10 +0000 (15:18 +0100)
committerNikita Popov <nikic@php.net>
Tue, 12 Jan 2016 14:37:39 +0000 (15:37 +0100)
Also commit a test I forgot to add for forbidden use() of
auto-globals.

Zend/tests/closure_use_auto_global.phpt [new file with mode: 0644]
Zend/tests/closure_use_parameter_name.phpt [new file with mode: 0644]
Zend/tests/closure_use_variable_twice.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/Zend/tests/closure_use_auto_global.phpt b/Zend/tests/closure_use_auto_global.phpt
new file mode 100644 (file)
index 0000000..9ab0897
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Cannot use() auto-global
+--FILE--
+<?php
+
+function test() {
+    $fn = function() use($GLOBALS) {
+        var_dump($GLOBALS);
+    };
+    $fn();
+}
+test();
+
+?>
+--EXPECTF--
+Fatal error: Cannot use auto-global as lexical variable in %s on line %d
diff --git a/Zend/tests/closure_use_parameter_name.phpt b/Zend/tests/closure_use_parameter_name.phpt
new file mode 100644 (file)
index 0000000..7ecc6d8
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Can't use name of lexical variable for parameter
+--FILE--
+<?php
+
+$a = 1;
+$fn = function ($a) use ($a) {
+    var_dump($a);
+};
+$fn(2);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use lexical variable $a as a parameter name in %s on line %d
diff --git a/Zend/tests/closure_use_variable_twice.phpt b/Zend/tests/closure_use_variable_twice.phpt
new file mode 100644 (file)
index 0000000..06c2645
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Closure cannot use one variable twice
+--FILE--
+<?php
+
+$a = 1;
+$fn = function() use ($a, &$a) {
+    $a = 2;
+};
+$fn();
+var_dump($a);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use variable $a twice in %s on line %d
index 2cc1a640aaba26569c226e963e86f89056f03076..8ac98191354812a5e321376bc8360bd14dcd946e 100644 (file)
@@ -3725,7 +3725,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
 
 static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */
 {
-       znode var_node, result;
+       znode var_node;
        zend_op *opline;
 
        zend_compile_expr(&var_node, var_ast);
@@ -4923,15 +4923,33 @@ static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /*
 
 void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
 {
+       zend_op_array *op_array = CG(active_op_array);
        zend_ast_list *list = zend_ast_get_list(ast);
        uint32_t i;
 
        for (i = 0; i < list->children; ++i) {
                zend_ast *var_ast = list->child[i];
+               zend_string *var_name = zend_ast_get_str(var_ast);
                zend_bool by_ref = var_ast->attr;
-
                zval zv;
                ZVAL_NULL(&zv);
+
+               if (op_array->static_variables
+                               && zend_hash_exists(op_array->static_variables, var_name)) {
+                       zend_error_noreturn(E_COMPILE_ERROR,
+                               "Cannot use variable $%s twice", ZSTR_VAL(var_name));
+               }
+
+               {
+                       int i;
+                       for (i = 0; i < op_array->last_var; i++) {
+                               if (zend_string_equals(op_array->vars[i], var_name)) {
+                                       zend_error_noreturn(E_COMPILE_ERROR,
+                                               "Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name));
+                               }
+                       }
+               }
+
                zend_compile_static_var_common(var_ast, &zv, by_ref);
        }
 }