Przeglądaj źródła

detect recursive implicit casts (fixed issue #1572)

Simon Krajewski 12 lat temu
rodzic
commit
9cd06b6135
1 zmienionych plików z 26 dodań i 4 usunięć
  1. 26 4
      codegen.ml

+ 26 - 4
codegen.ml

@@ -1309,6 +1309,8 @@ module Abstract = struct
 	let find_to ab pl b = List.find (Type.unify_to_field ab pl b) ab.a_to
 	let find_from ab pl a b = List.find (Type.unify_from_field ab pl a b) ab.a_from
 
+	let cast_stack = ref []
+
 	let get_underlying_type a pl =
 		try
 			if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
@@ -1351,6 +1353,13 @@ module Abstract = struct
 		let tright = follow eright.etype in
 		let tleft = follow tleft in
 		if tleft == tright then eright else
+		let recurse cf f =
+			if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
+			cast_stack := cf :: !cast_stack;
+			let r = f() in
+			cast_stack := List.tl !cast_stack;
+			r
+		in
 		try (match tright,tleft with
 			| (TAbstract({a_impl = Some c1} as a1,pl1) as t1),(TAbstract({a_impl = Some c2} as a2,pl2) as t2) ->
 				if a1 == a2 then
@@ -1363,14 +1372,25 @@ module Abstract = struct
 						if Meta.has Meta.MultiType a2.a_meta then raise Not_found;
 						c2,snd (find_from a2 pl2 t1 t2),a2,pl2
 					in
-					match cfo with None -> eright | Some cf -> make_static_call ctx c cf a pl [eright] tleft p
+					match cfo with
+					| None -> eright
+					| Some cf ->
+						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
 				end
 			| TDynamic _,_ | _,TDynamic _ ->
 				eright
 			| TAbstract({a_impl = Some c} as a,pl),t2 when not (Meta.has Meta.MultiType a.a_meta) ->
-				begin match snd (find_to a pl t2) with None -> eright | Some cf -> make_static_call ctx c cf a pl [eright] tleft p end
+				begin match snd (find_to a pl t2) with
+					| None -> eright
+					| Some cf ->
+						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
+				end
 			| t1,(TAbstract({a_impl = Some c} as a,pl) as t2) when not (Meta.has Meta.MultiType a.a_meta) ->
-				begin match snd (find_from a pl t1 t2) with None -> eright | Some cf -> make_static_call ctx c cf a pl [eright] tleft p end
+				begin match snd (find_from a pl t1 t2) with
+					| None -> eright
+					| Some cf ->
+						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
+				end
 			| _ ->
 				eright)
 		with Not_found ->
@@ -1527,7 +1547,9 @@ let post_process filters t =
 			match f.cf_expr with
 			| None -> ()
 			| Some e ->
-				f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters)
+				Abstract.cast_stack := f :: !Abstract.cast_stack;
+				f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters);
+				Abstract.cast_stack := List.tl !Abstract.cast_stack;
 		in
 		List.iter process_field c.cl_ordered_fields;
 		List.iter process_field c.cl_ordered_statics;