Forráskód Böngészése

[php] rename local vars with the same names as super global vars (fixes #9924)

Aleksandr Kuzmenko 4 éve
szülő
commit
8c0b13c395
3 módosított fájl, 44 hozzáadás és 9 törlés
  1. 1 0
      extra/CHANGES.txt
  2. 18 9
      src/generators/genphp7.ml
  3. 25 0
      tests/unit/src/unit/TestPhp.hx

+ 1 - 0
extra/CHANGES.txt

@@ -4,6 +4,7 @@
 
 	jvm : fixed equality checks for `Null<Float>` and `Null<Int>` (#9897)
 	hl : fixed crash if a thread finishes without invoking `sendMessage`/`readMessage` (#9920)
+	php : fixed local vars with certain names (_SERVER, _GET etc) overriding super global values (#9924)
 
 2020-09-11 4.1.4:
 

+ 18 - 9
src/generators/genphp7.ml

@@ -181,6 +181,15 @@ let is_native_array_type t = match follow t with TAbstract ({ a_path = tp }, _)
 *)
 let get_real_name name = if is_keyword name then name ^ "_hx" else name
 
+(**
+	Returns local variable name free of risk to collide with superglobals like $_SERVER or $_GET
+*)
+let vname name =
+	match name with
+	| "GLOBALS" | "_SERVER" | "_GET" | "_POST" | "_FILES" | "_COOKIE"
+	| "_SESSION" | "_REQUEST" | "_ENV" -> name ^ "_hx_"
+	| _ -> name
+
 (**
 	If `path` contains some reserved in PHP words, they will be replaced with allowed words.
 *)
@@ -1546,8 +1555,8 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 			(match expr.eexpr with
 				| TConst const -> self#write_expr_const const
 				| TLocal var ->
-					vars#used var.v_name;
-					self#write ("$" ^ var.v_name)
+					vars#used (vname var.v_name);
+					self#write ("$" ^ (vname var.v_name))
 				| TArray (target, index) -> self#write_expr_array_access target index
 				| TBinop (OpAssign, { eexpr = TArray (target, index) }, value) when is_array_type target.etype ->
 					self#write_expr_set_array_item target index value
@@ -1700,8 +1709,8 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 			Writes TVar to output buffer
 		*)
 		method write_expr_var var expr =
-			vars#declared var.v_name;
-			self#write ("$" ^ var.v_name ^ " = ");
+			vars#declared (vname var.v_name);
+			self#write ("$" ^ (vname var.v_name) ^ " = ");
 			match expr with
 				| None -> self#write "null"
 				| Some expr -> self#write_expr expr
@@ -1884,8 +1893,8 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 			let rec traverse = function
 				| [] -> ()
 				| (v,body) :: rest ->
-					self#write (" catch(" ^ (self#use_t v.v_type) ^ " $" ^ v.v_name ^ ") ");
-					vars#declared v.v_name;
+					self#write (" catch(" ^ (self#use_t v.v_type) ^ " $" ^ (vname v.v_name) ^ ") ");
+					vars#declared (vname v.v_name);
 					self#write_as_block body;
 					traverse rest
 			in
@@ -2525,7 +2534,7 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 					if add_parentheses then self#write "(";
 					self#write_expr collection;
 					if add_parentheses then self#write ")";
-					self#write (" as $" ^ key.v_name ^ " => $" ^ value.v_name ^ ") ");
+					self#write (" as $" ^ (vname key.v_name) ^ " => $" ^ (vname value.v_name) ^ ") ");
 					self#write_as_block ~unset_locals:true { body with eexpr = TBlock body_exprs };
 				| _ ->
 					fail self#pos __LOC__
@@ -2767,9 +2776,9 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 		method write_function_arg arg =
 			match arg with
 				| ({ v_name = arg_name; v_type = arg_type }, default_value) ->
-					vars#declared arg_name;
+					vars#declared (vname arg_name);
 					if is_ref arg_type then self#write "&";
-					self#write ("$" ^ arg_name);
+					self#write ("$" ^ (vname arg_name));
 					match default_value with
 						| None -> ()
 						| Some expr ->

+ 25 - 0
tests/unit/src/unit/TestPhp.hx

@@ -85,6 +85,31 @@ class TestPhp extends Test
 		});
 	}
 
+	@:analyzer(ignore)
+	function testIssue9924() {
+		var v = Std.random(10);
+
+		var GLOBALS = v;
+		var _SERVER = v;
+		var _GET = v;
+		var _POST = v;
+		var _FILES = v;
+		var _COOKIE = v;
+		var _REQUEST = v;
+		var _ENV = v;
+		// var _SESSION = v; //not defined in CLI
+
+		utest.Assert.notEquals(GLOBALS, SuperGlobal.GLOBALS);
+		utest.Assert.notEquals(_SERVER, SuperGlobal._SERVER);
+		utest.Assert.notEquals(_GET, SuperGlobal._GET);
+		utest.Assert.notEquals(_POST, SuperGlobal._POST);
+		utest.Assert.notEquals(_FILES, SuperGlobal._FILES);
+		utest.Assert.notEquals(_COOKIE, SuperGlobal._COOKIE);
+		utest.Assert.notEquals(_REQUEST, SuperGlobal._REQUEST);
+		utest.Assert.notEquals(_ENV, SuperGlobal._ENV);
+		// utest.Assert.notEquals(_SESSION, SuperGlobal._SESSION);
+	}
+
 	inline static function make():FunctionCallerWrapper {
 		return new FunctionCaller(function(f) f());
 	}