diff --git a/src/plugins/alias/.gitattributes b/src/plugins/alias/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..71a6c8afbd063a189a98779343b9c0195dadbbd7 --- /dev/null +++ b/src/plugins/alias/.gitattributes @@ -0,0 +1,76 @@ +################ +# MERGE: union # +################ + +Changelog merge=union + +################################################## +# BINARY/CHECK-SYNTAX/INDENT/EOL-EOF: set/-unset # +################################################## + +# note: "binary" is a built-in macro that also +# unsets the "text" and "diff" attributes + +# note: set "check-eoleof" and "check-utf8" by default to all files +* check-eoleof check-utf8 + +# note: unset "-check-eoleof" and "-check-utf8" for "binary" +*.jpg binary -check-eoleof -check-utf8 +*.pdf binary -check-eoleof -check-utf8 + +########################################### +# CHECK-SYNTAX/INDENT/EOL-EOF: set/-unset # +########################################### + +*.ml check-syntax check-indent -check-eoleof +*.mli check-syntax check-indent -check-eoleof + +################################ +# HEADER_SPEC: LICENSE.Alias # +################################ + +dune-project header_spec=LICENSE.Alias +dune header_spec=LICENSE.Alias +dune-workspace header_spec=LICENSE.Alias + +Make* header_spec=LICENSE.Alias + +*.ml header_spec=LICENSE.Alias +*.mli header_spec=LICENSE.Alias + +######################## +# HEADER_SPEC: .ignore # +######################## + +# CI + +/.gitlab-ci.yml header_spec=.ignore +/nix/ci.sh header_spec=.ignore +/nix/*.nix header_spec=.ignore + +# Doc + +/Changelog header_spec=.ignore +README* header_spec=.ignore + +# Git + +.gitattributes header_spec=.ignore +.gitignore header_spec=.ignore +.gitkeep header_spec=.ignore +.git-blame-ignore-revs header_spec=.ignore + +# Headers + +/LICENSE.Alias header_spec=.ignore +/headers/open-source/* header_spec=.ignore +/headers/close-source/* header_spec=.ignore + +# OCaml + +/*.opam* header_spec=.ignore +/.ocp-indent header_spec=.ignore + +#Tests + +/tests/**/* header_spec=.ignore diff --git a/src/plugins/alias/.gitignore b/src/plugins/alias/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..bf8b4fea7803f726f79270ec0f26987cc09914f7 --- /dev/null +++ b/src/plugins/alias/.gitignore @@ -0,0 +1,3 @@ +/_build +tests/**/result +tests/*/oracle/dune diff --git a/src/plugins/alias/.gitlab-ci.yml b/src/plugins/alias/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..d4c9ff04cbd35981d073e8a999033b0bb70289c7 --- /dev/null +++ b/src/plugins/alias/.gitlab-ci.yml @@ -0,0 +1,40 @@ +################################################################################ +### STAGES + +stages: + - tests + +################################################################################ +### DEFAULT JOB PARAMETERS + +default: + tags: [nix-v2] + +################################################################################ +### VARIABLES + +variables: + DEFAULT: "master" + OCAML: "4.11" + +################################################################################ +### TESTS + +build-and-test: + stage: tests + script: + - ./nix/ci.sh + +check-headers: + stage: tests + variables: + CI_MODE: "check-headers" + script: + - ./nix/ci.sh + +lint: + stage: tests + variables: + CI_MODE: "lint" + script: + - ./nix/ci.sh diff --git a/src/plugins/alias/.ocp-indent b/src/plugins/alias/.ocp-indent new file mode 100644 index 0000000000000000000000000000000000000000..31dcc35bf57a9873077570a3776515be93e129d9 --- /dev/null +++ b/src/plugins/alias/.ocp-indent @@ -0,0 +1 @@ +normal diff --git a/src/plugins/alias/API.ml b/src/plugins/alias/API.ml new file mode 100644 index 0000000000000000000000000000000000000000..2b77720334f40c9d71c2a9bb80d2ea4437f51698 --- /dev/null +++ b/src/plugins/alias/API.ml @@ -0,0 +1,126 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Cil_types + +open Simplified + +(** Points-to graphs datastructure. *) +module G = Abstract_state.G + +module LSet = Simplified_lset + +module Abstract_state = Abstract_state + +let check_computed () = + if not (Analysis.is_computed ()) + then + Options.abort "Static analysis must be called before any function of the API can be called" + + +let fold_aliases_stmt (f_fold : 'a -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let set_aliases = Abstract_state.find_all_aliases lv state in + LSet.fold_lval (fun e a -> f_fold a e) set_aliases acc + +let fold_new_aliases_stmt (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (s:stmt) (lv:lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let new_state = Analysis.do_stmt state s in + let set_aliases = Abstract_state.find_all_aliases lv new_state in + LSet.fold_lval (fun e a -> f_fold a e) set_aliases acc + +let fold_aliases_kf (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a = + check_computed (); + if Kernel_function.has_definition kf + then + let s = Kernel_function.find_return kf in + fold_new_aliases_stmt f_fold acc kf s lv + else + Options.abort "fold_aliases_kf: function %a has no definition" Kernel_function.pretty kf + +let fold_fundec_stmts (f_fold: 'a -> stmt -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a = + check_computed (); + if Kernel_function.has_definition kf + then + let f_dec = Kernel_function.get_definition kf in + let list_stmt = f_dec.sallstmts in + List.fold_left + (fun acc s -> + fold_new_aliases_stmt + (fun a lv -> f_fold a s lv) + acc + kf + s + lv + ) + acc + list_stmt + else + Options.abort "fold_fundec_stmts: function %a has no definition" Kernel_function.pretty kf + +let are_aliased (kf: kernel_function) (s:stmt) (lv1: lval) (lv2:lval) : bool = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> false + | Some state -> + let setv1 = Abstract_state.find_all_aliases lv1 state in + LSet.mem (BLval lv2) setv1 + +let fold_vertex (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let v : G.V.t = Abstract_state.find_vertex lv state in + let set_aliases = Abstract_state.find_aliases lv state in + LSet.fold_lval (fun lv a-> f_fold a v lv) set_aliases acc + +let fold_vertex_closure (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let list_closure : (G.V.t * LSet.t) list = Abstract_state.find_transitive_closure lv state in + List.fold_left + (fun acc (i,s) -> LSet.fold_lval (fun lv a -> f_fold a i lv) s acc) + acc + list_closure + +let get_state_before_stmt = + Analysis.get_state_before_stmt + +let call_function a f res args = + match Analysis.get_summary f with + None -> None + | Some su -> Some(Abstract_state.call a res args su) + + +let simplify_lval (lv:lval) : lval = + match Simplified.Simplified_lval.from_lval lv with + BLval lv -> lv + | _ -> Options.fatal "This should not happen" diff --git a/src/plugins/alias/API.mli b/src/plugins/alias/API.mli new file mode 100644 index 0000000000000000000000000000000000000000..ca429be02ec70ee7ff6836ea9ec6794b867da0f6 --- /dev/null +++ b/src/plugins/alias/API.mli @@ -0,0 +1,93 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +(** External API of the plugin Alias *) + +open Cil_types + +(** Points-to graphs datastructure. *) +module G: Graph.Sig.G + +(** NB : do the analysis BEFORE using any of those functions *) + +(* previously get_class_before_statement *) +(** [fold_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of the + given lval [lv] right before stmt [s] in function [kf]. *) +val fold_aliases_stmt: + ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(* previously get_class_after_statment *) +(** [fold_new_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of + the given lval [lv] created by stmt [s] in function [kf]. *) +val fold_new_aliases_stmt: + ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(* previously get_class_fundec *) +(** [fold_aliases_kf f acc kf lv] folds [f acc] over all the aliases of lval + [lv] at the end of function [kf]. *) +val fold_aliases_kf: + ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a + +(** [fold_fundec_stmts f acc kf v] folds [f acc s e] on the list of + pairs [s, e] where [e] is the set of lval aliased to [v] after statement [s] + in function [kf]. *) +val fold_fundec_stmts: + ('a -> stmt -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a + +(** [are_aliased kf s lv1 lv2] returns true if and only if the two + lvals [lv1] and [lv2] are aliased before stmt [s] in function + [kf]. *) +val are_aliased: kernel_function -> stmt -> lval -> lval -> bool + +(** [fold_vertex f acc kf s v] folds [f acc i lv] to all [lv] in [i], where [i] is + the vertex that represents the equivalence class of [v] before statement [s] in function [kf]. *) +val fold_vertex: + ('a -> G.V.t -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(** [fold_vertex_closure f acc kf s v] is the transitive closure of function + [fold_vertex]. *) +val fold_vertex_closure: + ('a -> G.V.t -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + + +(** direct access to the abstract state. See Abstract_state.mli *) + +module Abstract_state : Abstract_state.S + +(** [get_state_before_stmt f s] gets the abstract state computed after + statement [s] in function [f]. Returns [None] if + the abstract state is bottom or not computed. *) +val get_state_before_stmt : kernel_function -> stmt -> Abstract_state.t option + + +(** [call_function a f Some(res) args] computes the abstract state + after the instruction res=f(args) where res is a lval. [a] is the + abstract state before the call. If function [f] returns no value, + use [call_function a f None args] instead. Returns [None] if + the abstract state [a] is bottom or not computed. *) +val call_function: Abstract_state.t -> kernel_function -> lval option -> exp list -> Abstract_state.t option + + +(** [simplify_lval lv] returns a lval where every index of an array is + replaced by 0, evey pointer arithmetic is simplified to an access + to an array *) +val simplify_lval: lval -> lval diff --git a/src/plugins/alias/Alias.ml b/src/plugins/alias/Alias.ml new file mode 100644 index 0000000000000000000000000000000000000000..0d38459c28ab0731dfc4ba3486309aed13df9030 --- /dev/null +++ b/src/plugins/alias/Alias.ml @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + + +module Analysis = Analysis + +module API = API + +let main () = + if Options.Enabled.get() then + begin + Analysis.compute (); + Options.debug "Analysis complete"; + end + +let () = + Db.Main.extend main diff --git a/src/plugins/alias/Alias.mli b/src/plugins/alias/Alias.mli new file mode 100644 index 0000000000000000000000000000000000000000..96a5e0094acff8b7eca10c4ad525dc3b15fa98b8 --- /dev/null +++ b/src/plugins/alias/Alias.mli @@ -0,0 +1,32 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +(** Interface for the Alias plug-in. *) + +module Analysis: sig + (** see file analysis.mli for documentation *) + val compute : unit -> unit + val clear : unit -> unit +end + + +module API = API diff --git a/src/plugins/alias/LICENSE.Alias b/src/plugins/alias/LICENSE.Alias new file mode 100644 index 0000000000000000000000000000000000000000..57a2745d01d2fc7935756153dc194f934af4ebf5 --- /dev/null +++ b/src/plugins/alias/LICENSE.Alias @@ -0,0 +1,19 @@ + +This file is part of the Frama-C plug-in 'Alias' (alias). + +Copyright (C) 2022-2023 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +you can redistribute it and/or modify it under the terms of the GNU +Lesser General Public License as published by the Free Software +Foundation, version 2.1. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +See the GNU Lesser General Public License version 2.1 +for more details (enclosed in the file LICENSE) + diff --git a/src/plugins/alias/Makefile b/src/plugins/alias/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f2765fe084bff0f5fee2ce7f5154e368be87ed9d --- /dev/null +++ b/src/plugins/alias/Makefile @@ -0,0 +1,76 @@ +########################################################################## +# # +# This file is part of the Frama-C plug-in 'Alias' (alias). # +# # +# Copyright (C) 2022-2023 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file LICENSE) # +# # +########################################################################## + +.PHONY: all build-profiling build clean + +FRAMAC_SHARE:=$(shell frama-c -print-share-path) + +sinclude ${FRAMAC_SHARE}/Makefile.common + +########################################################################## +# Build + +all:: build frama-c-alias.opam + +frama-c-alias.opam: frama-c-alias.opam.template dune-project + rm -f $@ + dune build $@ + +build:: + dune build @install + +build-profiling:: + dune build --instrument-with landmarks @install + +clean:: purge-tests + dune clean + rm -rf _build .merlin + +########################################################################## +# Tests + +include ${FRAMAC_SHARE}/Makefile.testing + +########################################################################## +# Install + +include ${FRAMAC_SHARE}/Makefile.installation + +########################################################################## +# Headers + +HDRCK_EXTRA:=-headache-config-file ${FRAMAC_SHARE}/headache_config.txt +include ${FRAMAC_SHARE}/Makefile.headers + +SHORT_NAME:=alias +LONG_NAME:=Alias +PLUGIN_NAME:=Alias +FROM_YEAR:=2022 + +include headers/Makefile.generate-headers + +########################################################################## +# Linting + +include ${FRAMAC_SHARE}/Makefile.linting + +########################################################################## diff --git a/src/plugins/alias/README.md b/src/plugins/alias/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7c9694c4dd98c788a5ad01cf6acd1524a6db0990 --- /dev/null +++ b/src/plugins/alias/README.md @@ -0,0 +1,22 @@ +# MERCE + +GIT project for our collaboration with MERCE + + +## Project Members + +Allan Blanchard +Loïc Correnson +Tristan Le Gall +Jan Rochel +Julien Signoles + +## Building + +This plug-in requires the library 'unionFind' that can be installed as follows: + opam install unionFind + +To build with profiling install the package landmarks-ppx and run: + dune build --instrument-with landmarks + +Using the plugin will then echo profiling information to stderr. diff --git a/src/plugins/alias/abstract_state.ml b/src/plugins/alias/abstract_state.ml new file mode 100644 index 0000000000000000000000000000000000000000..081e221dac1947625cb8195ae4dfe84eb53a214d --- /dev/null +++ b/src/plugins/alias/abstract_state.ml @@ -0,0 +1,1031 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Graph + +open Cil_types + +open Cil_datatype + +open Simplified + +module VSet = Datatype.Int.Set +module VMap = Datatype.Int.Map + +module Lval = Simplified.Simplified_lval +module LSet = Simplified.Simplified_lset +module LMap = Simplified.Simplified_lmap + +module G = Persistent.Digraph.ConcreteBidirectional(Datatype.Int) + +module V = G.V + +(* like LMap, but organized with offset and specialized functions *) +module LLMap = +struct + module OMap = Offset.Map + (* each t is a map (lhost,NoOffset) -> offset -> V.t *) + type t = (V.t OMap.t) LMap.t + + let empty : t = LMap.empty + + let mem (lv:Lval.t) (m:t) = + let lv, off = Lval.removeOffsetLval lv in + try + OMap.mem off (LMap.find lv m) + with + Not_found -> false + + let find (lv:Lval.t) (m:t) : V.t = + let lv, off = Lval.removeOffsetLval lv in + OMap.find off (LMap.find lv m) + + let add (lv:Lval.t) (v:V.t) (m:t) :t = + let lv, off = Lval.removeOffsetLval lv in + let mo = try LMap.find lv m with Not_found -> OMap.empty in + LMap.add lv (OMap.add off v mo) m + + let remove (lv:Lval.t) (m:t) :t = + let lv, off = Lval.removeOffsetLval lv in + let mo = try LMap.find lv m with Not_found -> OMap.empty in + let res = OMap.remove off mo in + if OMap.is_empty res + then + LMap.remove lv m + else + LMap.add lv res m + + let iter (f_iter: Lval.t -> V.t -> unit) (m:t) : unit = + LMap.iter + (fun lv mo -> + OMap.iter + (fun o v -> + let lv = Lval.addOffsetLval o lv in + f_iter lv v + ) + mo + ) + m + + let map (f_map: V.t -> V.t ) (m:t) : 'a = + LMap.map + (fun mo -> + OMap.map + f_map + mo + ) + m + + let pretty fmt (m:t) = + let is_first = ref true in + LMap.iter + (fun lv mo -> + OMap.iter + (fun o v -> let lv = Lval.addOffsetLval o lv in + if !is_first then is_first := false else Format.fprintf fmt "@;<3>"; + Format.fprintf fmt "@ @[%a:%d@]" Lval.pretty lv v) + mo + ) + m + + (* left-biased *) + let union = LMap.union @@ fun _ l r -> Some (OMap.union (fun _ l _r -> Some l) l r) + + let intersect = + let intersect_omap l r = match l, r with + | Some l, Some r -> Some (l,r) + | _ -> None + in + let intersect_lmap l r = match l, r with + | Some l, Some r -> + let omap = OMap.merge (fun _ -> intersect_omap) l r in + if OMap.is_empty omap then None else Some omap + | _ -> None + in + LMap.merge @@ fun _ -> intersect_lmap + + let to_seq m = LMap.fold (fun lv omap s -> OMap.fold (fun o v s -> Seq.cons (lv,o,v) s) omap s) m Seq.empty + + (* specialized functions *) + let rec is_sub_offset o1 o2 = + match (o1,o2) with + NoOffset, _ -> true + | Index (e1,o1), Index (e2,o2) when Cil_datatype.ExpStructEq.equal e1 e2 -> is_sub_offset o1 o2 + | Field (f1,o1), Field (f2,o2) when Fieldinfo.equal f1 f2 -> is_sub_offset o1 o2 + | _ -> false + + (* finds all the lval lv1 apearing in [m] such as there exists an offset o1 and lv1 + o1 = lv *) + let find_upper_offsets (lv:Lval.t) (m:t) : V.t LMap.t = + let lv, off = Lval.removeOffsetLval lv in + let mo = try LMap.find lv m with Not_found -> OMap.empty in + let f_filter o _v = is_sub_offset o off in + let mo = OMap.filter f_filter mo in + OMap.fold + (fun o v acc -> let lv = Lval.addOffsetLval o lv in LMap.add lv v acc) + mo + LMap.empty + +end + +module type S = +sig + + (* see .mli for coments *) + type t + + val get_graph: t -> G.t + + val get_lval_set : G.V.t -> t -> LSet.t + + val pretty : ?debug:bool -> Format.formatter -> t -> unit + + val print_dot : string -> t -> unit + + val find_vertex : lval -> t -> G.V.t + + val find_aliases : lval -> t -> LSet.t + + val find_all_aliases : lval -> t -> LSet.t + + val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list + + val is_included : t -> t -> bool + +end + +type t = { + graph : G.t; + lmap : LLMap.t ; (* lmap(lv) is a table [offset->v] where the vertex v corresponding to lval (lv+offset), in other words (lv+offset) is in label(v) *) + vmap : LSet.t VMap.t ;(* reverse of lmap *) +} + +let node_counter = ref 0 +let fresh_node_id () = + let id = !node_counter in + node_counter := !node_counter + 1; + id + +(* find functions *) +let find_lset (v:V.t) (x:t) : LSet.t = + try VMap.find v x.vmap + with Not_found -> LSet.empty + +let find_aliases (lv:lval) (x:t) = + let lv : Lval.t = Lval.from_lval lv in + try + let v = LLMap.find lv x.lmap in + find_lset v x + with Not_found -> LSet.empty + +let rec get_points_to (v:V.t) (x:t) : LSet.t = + assert (G.mem_vertex x.graph v); + let set_predecessors = + List.fold_left + (fun acc v -> LSet.union acc (get_points_to v x)) + LSet.empty + (G.pred x.graph v) + in + LSet.union + (find_lset v x) + (LSet.map Lval.points_to set_predecessors) + +let aliases_of_vertex (v:V.t) (x:t) : LSet.t = + assert (G.mem_vertex x.graph v); + let list_pred = G.pred x.graph v in + List.fold_left + (fun acc v -> LSet.union acc (get_points_to v x)) + LSet.empty + list_pred + +let find_all_aliases (lv:lval) (x:t) : LSet.t = + let lv : Lval.t = Lval.from_lval lv in + try + begin + let v = LLMap.find lv x.lmap in + match G.succ x.graph v with + [] -> find_lset v x + | [succ_v] -> + aliases_of_vertex succ_v x + | _ -> Options.fatal "invariant violated (more than 1 successor)" + end + with Not_found -> LSet.empty + +let get_graph (x:t) = x.graph + +(* renamed for the interface *) +let get_lval_set = find_lset + + +(* printing functions *) + +let print_debug fmt (x:t) = + Format.fprintf fmt "@[<v>"; + Format.fprintf fmt "@[Edges:"; + G.iter_edges (fun v1 v2 -> Format.fprintf fmt "@;<3 2>@[%d → %d@]" v1 v2) x.graph; + Format.fprintf fmt "@]@;<6>"; + Format.fprintf fmt "@[LMap:@;<3 2>"; + LLMap.pretty fmt x.lmap; + Format.fprintf fmt "@]@;<6>"; + Format.fprintf fmt "@[VMap:@;<2>"; + VMap.iter (fun v ls -> Format.fprintf fmt "@;<2 2>@[%d:%a@]" v LSet.pretty ls) x.vmap; + Format.fprintf fmt "@]"; + Format.fprintf fmt "@]" + +let print_graph fmt (x:t) = + let is_first = ref true in + let print_edge v1 v2 = + if !is_first then is_first := false else Format.fprintf fmt "@;<3>"; + let print_node v fmt lset = Format.fprintf fmt "%d:%a" v LSet.pretty lset in + Format.fprintf fmt "@[%a@] → @[%a@]" + (print_node v1) (VMap.find v1 x.vmap) + (print_node v2) (VMap.find v2 x.vmap) + in + if G.nb_edges x.graph = 0 + then Format.fprintf fmt "<empty>" + else G.iter_edges print_edge x.graph + +let print_aliases fmt (x:t) = + let is_first = ref true in + let print_alias_set _ set_lv = + if !is_first then is_first := false else Format.fprintf fmt "@;<2>"; + LSet.pretty fmt set_lv + in + let alias_set_of_vertex i _ = + let aliases = aliases_of_vertex i x in + if LSet.cardinal aliases >= 2 then Some aliases else None + in + let alias_sets = VMap.filter_map alias_set_of_vertex x.vmap in + if VMap.is_empty alias_sets + then Format.fprintf fmt "<none>" + else VMap.iter print_alias_set alias_sets + +(** invariants of type t must be true before and after each functon call *) +let assert_invariants (x:t) : unit = + (* check that all vertex of the graph have entries in vmap, + and are integer between 0 and node_counter, and have at most 1 successor *) + assert (!node_counter >= 0); + let assert_vertex (v:V.t) = + assert (v >= 0); + assert (v < !node_counter); + assert (VMap.mem v x.vmap); + assert (List.length (G.succ x.graph v) <= 1) + in + G.iter_vertex assert_vertex x.graph; + let assert_edge v1 v2 = + assert (v1 <> v2); + assert (G.mem_vertex x.graph v1); + assert (G.mem_vertex x.graph v2) + in + G.iter_edges assert_edge x.graph; + let assert_lmap (lv:Lval.t) (v:V.t) = + assert (G.mem_vertex x.graph v); + assert (LSet.mem lv (VMap.find v x.vmap)) + in + LLMap.iter assert_lmap x.lmap; + let assert_vmap (v:V.t) (ls:LSet.t) = + assert (G.mem_vertex x.graph v); + (* TODO: we removed the invariant because of OSCS*) + (* if not (LSet.is_empty ls) + * then + * begin + * let lv = LSet.choose ls in + * let is_ptr_lv = Lval.is_pointer lv in + * assert (LSet.for_all (fun x -> Lval.is_pointer x = is_ptr_lv) ls) + * end; *) + assert (LSet.fold (fun lv acc -> acc && V.equal (LLMap.find lv x.lmap) v) ls true) + in + VMap.iter assert_vmap x.vmap + +(* Ensure that assert_invariants is not executed if the -noassert flag is supplied. *) +let assert_invariants x = assert (assert_invariants x; true) + +let pretty ?(debug = false) fmt (x:t) = + if debug then + try + assert_invariants x; + print_graph fmt x + with Assert_failure _ -> print_debug fmt x + else + print_aliases fmt x + +(** .dot printing functions*) +let find_vertex_name_ref = Extlib.mk_fun "find_vertex_name" + +let lset_to_string (s: LSet.t) : string = + let fmt = Format.str_formatter in + Format.fprintf fmt "\"%a\"" LSet.pretty s; + Format.flush_str_formatter () + +module Dot = Graphviz.Dot (struct + include G + let edge_attributes _ = [] + let default_edge_attributes _ = [] + let get_subgraph _ = None + let vertex_attributes _ = [`Shape `Box] + let vertex_name (v:V.t) = + let lset = !find_vertex_name_ref v in + lset_to_string lset + let default_vertex_attributes _ = [] + let graph_attributes _ = [] + end) + +let print_dot filename (a:t) = + let file = open_out filename in + find_vertex_name_ref := + (fun v -> find_lset v a + ); + Dot.output_graph file a.graph; + close_out file + +(* find functions, part 2 *) +let rec closure_find_lset (v:V.t) (x:t) : (V.t * LSet.t) list = + match G.succ x.graph v with + [] -> [v, find_lset v x] + | [v_next] -> (v, find_lset v x)::(closure_find_lset v_next x) + | _ -> Options.fatal ("this shall not happen (invariant broken)") + +let find_transitive_closure (lv:lval) (x:t) : (G.V.t * LSet.t) list = + let lv: Lval.t = Lval.from_lval lv in + assert_invariants x; + try + let v = (LLMap.find lv x.lmap) in + closure_find_lset v x + with + Not_found -> [] +(* TODO : what about offsets ? *) + +(* NOTE on "constant vertex": a constant vertex represents an unamed + scalar value (type bottom in steensgaard's paper), or the address + of a variable. It means that in [vmap], its associated LSet is + empty. By definition, constant vertex cannot be associated to a + lval in [lmap] *) +let create_cst_vertex (x:t) : V.t * t = + let new_v = fresh_node_id () in + let new_g = G.add_vertex x.graph new_v in + let new_lmap = x.lmap in + let new_vmap = VMap.add new_v LSet.empty x.vmap in + new_v , + { + graph = new_g ; + lmap = new_lmap ; + vmap = new_vmap ; + } + +(* find all the aliases of lv1 in x, for create_vertex *) +let find_all_aliases_of_offset (lv1: Lval.t) (x: t) : LSet.t = + + let list_of_lval_to_be_searched : (Lval.t*offset) list = + decompose_lval lv1 + in + (* for each lval, find the set of aliases *) + let f_map (lv,o) = + try (VMap.find (LLMap.find lv x.lmap) x.vmap, o) + with + Not_found -> (LSet.empty,o) + in + Options.debug ~level:9 "decompose_lval %a : [@[<hov 2>" Lval.pretty lv1; + List.iter (fun (x, o) -> Options.debug ~level:9 " (%a,%a) " Lval.pretty x Offset.pretty o) list_of_lval_to_be_searched; + Options.debug ~level:9 "@]]"; + let list_of_aliases : (LSet.t*offset) list = + List.map f_map list_of_lval_to_be_searched + in + (* for each lval of the Lset, add the offset and add it to the resulting set *) + let f_fold_left (acc:LSet.t) (ls,o) = + LSet.fold + (fun lv acc -> let lv = Lval.addOffsetLval o lv in LSet.add lv acc) + ls + acc + in + List.fold_left + f_fold_left + (LSet.singleton lv1) + list_of_aliases + +(* returns the new vertex and the new graph *) +(* only for function find_or_create vertex *) +let create_vertex_simple (lv:Lval.t) (x:t) : V.t * t = + let new_v = fresh_node_id () in + let new_g = G.add_vertex x.graph new_v in + (* find all the alias of lv (because of offset) *) + let set_of_aliases : LSet.t = find_all_aliases_of_offset lv x in + (* add all these aliases *) + Options.debug ~level:9 "all_aliases of %a : %a " Lval.pretty lv LSet.pretty set_of_aliases; + let new_lmap = + LSet.fold + (fun lv acc -> assert (not (LLMap.mem lv x.lmap)); LLMap.add lv new_v acc) + set_of_aliases + x.lmap + in + let new_vmap = VMap.add new_v set_of_aliases x.vmap in + + let new_x = + { + graph = new_g ; + lmap = new_lmap ; + vmap = new_vmap ; + } + in + assert_invariants new_x; + match lv with + | BLval (Var v, NoOffset) -> + begin + match v.vtype with + TPtr _ -> + (* then add a constant vertex *) + let another_v, new_x = create_cst_vertex new_x in + let new_g = G.add_edge new_x.graph new_v another_v in + new_v, {new_x with graph = new_g} + | _ -> new_v ,new_x + end + | _ -> + new_v , new_x + +(* only for function find_or_create_vertex *) +let create_vertex_addr (lv:lval) (v:V.t) (x:t) : V.t *t = + let va, x = create_vertex_simple (BAddrOf lv) x in + let new_g = G.add_edge x.graph va v in + va, { x with graph = new_g} + +let diff_offset (lv1:Lval.t) (lv2:Lval.t) = + let rec f_diff_offset o1 o2 = + match o1, o2 with + NoOffset, _ -> o2 + | Field (_,o1), Field (_,o2) -> f_diff_offset o1 o2 + | Index (_,o1), Index (_,o2) -> f_diff_offset o1 o2 + | _ -> Options.fatal "%s: unexpected case" __LOC__ + in + let _, o1 = Lval.removeOffsetLval lv1 + and _, o2 = Lval.removeOffsetLval lv2 + in + assert (LLMap.is_sub_offset o1 o2); + f_diff_offset o1 o2 + +(* create_vertex_lval shall only be called by find_or_create_vertex *) +(* creates a new vertex for a lval, assuming it is not already present + in the graph. If it is present, there will be bugs *) +let rec create_vertex_lval (blv:Lval.t) (x:t) : V.t * t = + assert (not (LLMap.mem blv x.lmap)); + Options.debug ~level:9 "creating a vertex for %a" Lval.pretty blv; + match blv with + | BLval lv -> + begin + match lv with + (Mem e, NoOffset) -> + (* special case, when we also add another vertex and a points-to edge*) + begin + (* first find the vertex corresponding to e *) + match Lval.from_exp e with + | None -> Options.fatal "unexpected result: Lval.from (%a) = None" Exp.pretty e + | Some (BLval lv1) -> + (* find the vertex *) + let v1, x = find_or_create_vertex (BLval lv1) x in + (* then creates a vertex for bvl ONLY IF there is no successor *) + begin + match G.succ x.graph v1 with + [] -> + let v2, x = create_vertex_simple blv x in + (* finally add a points-to edge between v1 and v2 *) + let new_graph = G.add_edge x.graph v1 v2 in + v2, {x with graph = new_graph } + | [succ_v1] -> + (* if there is a successor, update lmap and vmap to add blv to that successor's set *) + let new_lmap = LLMap.add blv succ_v1 x.lmap in + let new_vmap = VMap.add succ_v1 (LSet.add blv (VMap.find succ_v1 x.vmap)) x.vmap in + succ_v1, {x with lmap = new_lmap ; vmap = new_vmap } + | _ -> Options.fatal " Invariant violated : more than 1 successor" + end + | Some (BAddrOf lv) -> find_or_create_vertex (BLval lv) x + end + | _ -> create_vertex_simple blv x + end + | BAddrOf lv -> + let v1, x = find_or_create_vertex (BLval lv) x in + create_vertex_addr lv v1 x + +(* find the vertex of an lval *) +and find_or_create_vertex (lv:Lval.t) (x:t) : V.t * t = + try (LLMap.find lv x.lmap, x) + with + Not_found -> + begin + (* try to find if an alias already exists in x *) + let map_predecessors :V.t LMap.t = LLMap.find_upper_offsets lv x.lmap in + (* for any predecessor, find all its aliases and then look for potential existing vertex *) + let f_fold_lmap lvx vx acc = + let set_aliases = VMap.find vx x.vmap in + Options.debug ~level:9 "looking for aliases of %a in set %a" Lval.pretty lv LSet.pretty set_aliases; + if LSet.cardinal set_aliases > 1 + then + let off = diff_offset lvx lv in + let f_fold_lset lvs acc = + try + let lvs = Lval.addOffsetLval off lvs in + VSet.add (LLMap.find lvs x.lmap) acc + with + Not_found -> acc + in + LSet.fold + f_fold_lset + set_aliases + acc + else + acc + in + (* set of all existing aliases *) + let vset_res = + LMap.fold + f_fold_lmap + map_predecessors + VSet.empty + in + Options.debug ~level:9 "found aliases of %a : %a" Lval.pretty lv VSet.pretty vset_res; + if VSet.is_empty vset_res + then create_vertex_lval lv x + else + begin + assert (VSet.cardinal vset_res = 1); + let v_res = VSet.choose vset_res in + (* vertex found, update the tables *) + let new_lmap = LLMap.add lv v_res x.lmap in + let new_vmap = VMap.add v_res (LSet.add lv (VMap.find v_res x.vmap)) x.vmap in + v_res, {x with lmap = new_lmap; vmap = new_vmap} + end + end + +(* TODO is there a better way to do it ? *) +let find_vertex lv x = + let lv = Lval.from_lval lv in + let v,x1 = find_or_create_vertex lv x in + if x == x1 + (* if x has not been modified, then the vertex was found, not created *) + then v + else raise Not_found + +(* remove a lval from a graph*) +let remove_lval (x:t) (lv:Lval.t) :t = + assert_invariants x; + try + let v = LLMap.find lv x.lmap in + let setv = VMap.find v x.vmap in + let new_lmap = LLMap.remove lv x.lmap in + let new_vmap = VMap.add v (LSet.remove lv setv) x.vmap in + let result = {x with lmap = new_lmap; vmap = new_vmap} in + assert_invariants result; + result + with + Not_found -> x + +(* merge of two vertices; the first vertex carries both sets, the second is removed from the graph and from lmap and vmap *) +let merge x v1 v2 = + if (V.equal v1 v2) || not (G.mem_vertex x.graph v1) || not (G.mem_vertex x.graph v2) + then x + else + let set1 = find_lset v1 x in + let set2 = find_lset v2 x in + + let new_set = LSet.union set1 set2 in + (* update lmap : every lval in v2 must now be associated with v1*) + let new_lmap = LSet.fold (fun lv2 m -> LLMap.add lv2 v1 m) set2 x.lmap in + + (* update vmap *) + let new_vmap = VMap.add v1 new_set (VMap.remove v2 x.vmap) in + (* update the graph *) + let f_fold_succ v_succ (g:G.t) : G.t = + G.add_edge g v1 v_succ + and f_fold_pred v_pred (g:G.t) : G.t = + G.add_edge g v_pred v1 + in + let g = x.graph in + (* adds all new edges *) + let g = G.fold_succ f_fold_succ g v2 g in + let g = G.fold_pred f_fold_pred g v2 g in + (* remove v2 *) + let g = G.remove_vertex g v2 in + {graph = g; lmap = new_lmap; vmap = new_vmap} + +(* functions join and unify-pointer of steensgaard's paper *) +let rec join_without_check (x:t) (v1:V.t) (v2:V.t) : t = + if (V.equal v1 v2) || not (G.mem_vertex x.graph v1 && G.mem_vertex x.graph v2) + then + x + else + let pt1 = G.succ x.graph v1 in (* TODO ask frama-c type instead of looking in the graph *) + let pt2 = G.succ x.graph v2 in + let x = merge x v1 v2 in + assert (not (G.mem_vertex x.graph v2)); + match (pt1, pt2) with + | [], _ -> x + | _, [] -> x + | [succ_v1],[succ_v2] -> + assert (succ_v1 <> v2); + assert (succ_v2 <> v1); + join_without_check x succ_v1 succ_v2 + | _, _ -> + Options.fatal "invariant broken" + +(* since the recursive version of join, unify, unify2 and merge may break the invariants *) +let join (x:t) (v1:V.t) (v2:V.t) : t = + Options.debug ~level:7 "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x; + assert_invariants x; + let res = join_without_check x v1 v2 in + Options.debug ~level:7 "graph after join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug res; + begin + try assert_invariants res + with Assert_failure _ -> + Options.debug "join(%d,%d) failed" v1 v2; + Options.debug "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x; + Options.debug "graph after join(%d,%d):@;<2>@[ %a@]" v1 v2 print_debug res; + assert_invariants res + end; + res + +let merge_set (x:t) (vs:VSet.t) : V.t * t = + let v0 = VSet.choose vs in + if VSet.cardinal vs < 2 then v0, x else begin + Options.debug ~level:7 "graph before merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug x; + assert (G.mem_vertex x.graph v0); + let result = VSet.fold (fun v acc -> merge acc v0 v) vs x in + Options.debug ~level:7 "graph after merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug result; + v0, result + end + +let rec join_succs (x:t) v = + Options.debug ~level:8 "joining successors of %d" v; + if not @@ G.mem_vertex x.graph v then x else + match G.succ x.graph v with + | [] | [_] -> x + | succs -> + let v0, x = merge_set x @@ VSet.of_list succs in + join_succs x v0 + +(* in Steensgard's paper, this is written settype(v1,ref(v2,bot)) *) +let set_type (x:t) (v1:V.t) (v2:V.t) : t = + assert_invariants x; + (* if v1 points to another node, suppress current outgoing edge (and the node if it is a constant node) *) + let g, new_vmap = + match G.succ x.graph v1 with + [] -> x.graph, x.vmap + | [v2] -> + (* if v2 is a constant node supress it directly *) + if LSet.is_empty (VMap.find v2 x.vmap) + then (G.remove_vertex x.graph v2, VMap.remove v2 x.vmap) + else (G.remove_edge x.graph v1 v2, x.vmap) + | _ -> Options.fatal "too many outgoing edges in set_type" + in + let new_g = G.add_edge g v1 v2 in + let new_x = {x with graph = new_g ; vmap = new_vmap} in + assert_invariants new_x ; new_x + +let assignment (a:t) (lv:lval) (e:exp) : t = + assert_invariants a; + if Cil.isPointerType (Cil.typeOf e) + then + let x = Lval.from_lval lv in + match Lval.from_exp e with + | None -> a + | Some y -> + let (v1,a) = find_or_create_vertex x a in + let (v2,a) = find_or_create_vertex y a in + if List.mem v2 (G.succ a.graph v1) || List.mem v1 (G.succ a.graph v2) + then + let () = + Options.warning ~source:(fst e.eloc) + "ignoring assignment of the form: %a = %a" + Printer.pp_lval lv Printer.pp_exp e; + in a + else + let a = join a v1 v2 in + let a = match y with + | BAddrOf blv -> remove_lval a (BAddrOf blv) + | _ -> a + in + let () = assert_invariants a in + a + else + a + +(* assignment x = allocate(y) *) +let assignment_x_allocate_y (a:t) (lv:lval) : t = + assert_invariants a; + let x = Lval.from_lval lv in + let (v1,a) = find_or_create_vertex x a in + match G.succ a.graph v1 with + [] -> + begin + let (v2,a) = create_cst_vertex a in + let new_a : t = set_type a v1 v2 in + assert_invariants new_a ; new_a + end + | [_v2] -> a + | _ -> Options.fatal "this should not hapen (invariant broken)" + +let is_included (a1:t) (a2:t) = + (* tests if a1 is included in a2, at least as the nodes with lval *) + assert_invariants a1; + assert_invariants a2; + Options.debug ~level:8 "testing equal %a AND à .%a" (pretty ~debug:true) a1 (pretty ~debug:true) a2; + let exception Not_included in + try + let iter_lmap (lv:Lval.t) (v1:V.t): unit = + let v2 : V.t = try LLMap.find lv a2.lmap with Not_found -> raise Not_included in + match G.succ a1.graph v1, G.succ a2.graph v2 with + [], _ -> () + | [_], [] -> raise Not_included + | [v1p], [v2p] -> + if LSet.subset (VMap.find v1p a1.vmap) (VMap.find v2p a2.vmap) + then + () + else + raise Not_included + | _ -> Options.fatal "this should not hapen (invariant broken)" + in + LLMap.iter iter_lmap a1.lmap; true + with + Not_included -> false + +let empty :t = + {graph = G.empty; lmap = LLMap.empty; vmap = VMap.empty} + +let is_empty s = + compare s empty = 0 + +(* add an int to all vertex values *) +let shift (a : t) : t = + assert_invariants a; + if is_empty a then a else + let () = Options.debug ~level:8 "before shift: node_counter=%d@.%a" !node_counter print_debug a in + let max_idx = G.fold_vertex max a.graph 0 in + let min_idx = G.fold_vertex min a.graph max_idx in + let offset = !node_counter - min_idx in + let shift x = x + offset in + let shift_vmap shift_elem vmap = + VMap.of_seq @@ Stdlib.Seq.map shift_elem @@ VMap.to_seq vmap + in + let {graph; lmap; vmap} = a in + node_counter := max_idx + offset + 1; + let result = + {graph = G.map_vertex shift graph; + lmap = LLMap.map shift lmap; + vmap = shift_vmap (fun (key, l) -> (shift key, l)) vmap} + in + let () = Options.debug ~level:8 "after shift: node_counter=%d@.%a" !node_counter print_debug result in + assert_invariants result; + result + +let union_find vmap intersections = + let module Store : UnionFind.STORE = UnionFind.StoreMap.Make (VMap) in + let module UF = UnionFind.Make (Store) in + let uf = UF.new_store () in + let refs = VMap.mapi (fun i _ -> UF.make uf i) vmap in + let put_into_uf (v1,v2) = + let r1 = VMap.find v1 refs in + let r2 = VMap.find v2 refs in + ignore @@ UF.union uf r1 r2 + in + let _vs = Seq.iter put_into_uf intersections in + let sets_to_be_joined = + let add_to_map i r sets = + let repr = UF.find uf r in + let add_to_set = function + | None -> Some (VSet.singleton i) + | Some set -> Some (VSet.add i set) + in + VMap.update (UF.get uf repr) add_to_set sets + in + VMap.fold add_to_map refs VMap.empty in + sets_to_be_joined + +let union (a1:t) (a2:t) :t = + (* naive algorithm : + 1 merge the graph and the vmap (by doing union of sets) + 2 for any node present in both a1.graph and a2.graph, merge/join them + 3 for any lval [lv] that are has an entry in both a1.lmap and a2.lmap, merge the two vertex a1.lmap[lv] + and a2.lmap[lv] + + I am not confident about this function, there are too many potential bugs and inefficiencies + *) + assert_invariants a1; + assert_invariants a2; + + Options.debug ~level:4 "Union: First graph:%a" print_graph a1; + Options.debug ~level:5 "Union: First graph:%a" print_debug a1; + Options.debug ~level:4 "Union: Second graph:%a" print_graph a2; + Options.debug ~level:5 "Union: Second graph:%a" print_debug a2; + let new_graph = + G.fold_vertex + (fun v2 g -> G.add_vertex g v2) + a2.graph + a1.graph + in + let new_graph = + G.fold_edges + (fun v2a v2b g -> G.add_edge g v2a v2b) + a2.graph + new_graph + in + let new_vmap = + VMap.union (fun _ lset1 lset2 -> Option.some @@ LSet.union lset1 lset2) + a2.vmap + a1.vmap + in + let sets_to_be_joined = + let intersections = LLMap.to_seq @@ LLMap.intersect a1.lmap a2.lmap in + union_find new_vmap @@ Seq.map (fun (_,_,x) -> x) intersections + in + let new_lmap = LLMap.union a1.lmap a2.lmap in + Options.debug ~level:7 "Union: sets to be joined:@["; + VMap.iter (fun _ set -> Options.debug ~level:7 "%a" VSet.pretty set) sets_to_be_joined; + Options.debug ~level:7 "@]"; + let new_a = {graph = new_graph; lmap = new_lmap; vmap = new_vmap} in + let merged_nodes, new_a = + VMap.fold + (fun _ set (merged_nodes, x) -> let v0, x = merge_set x set in (v0 :: merged_nodes), x) + sets_to_be_joined + ([], new_a) + in + let new_a = List.fold_left join_succs new_a merged_nodes in + Options.debug ~level:4 "Union: Result graph:%a" print_graph new_a; + Options.debug ~level:5 "Union: Result graph:%a" print_debug new_a; + begin + try assert_invariants new_a + with Assert_failure _ -> + Options.debug "union failed"; + Options.debug "Union: First graph:%a" print_graph a1; + Options.debug "Union: First graph:%a" print_debug a1; + Options.debug "Union: Second graph:%a" print_graph a2; + Options.debug "Union: Second graph:%a" print_debug a2; + Options.debug "Union: Result graph:%a" print_graph new_a; + Options.debug "Union: Result graph:%a" print_debug new_a; + assert_invariants new_a + end; + new_a + +(** a type for summaries of functions *) +type summary = + { + state : t option; + formals: lval list; + locals: lval list; + return : exp option + } + +let make_summary (s : t) (kf : kernel_function) = + let exp_return : exp option = + if Kernel_function.has_definition kf then + let return_stmt = Kernel_function.find_return kf in + match return_stmt.skind with + Return (e, _) -> e + | _ -> Options.fatal "this should not happen" + else + None + in + let s = + match exp_return with + None -> s + | Some e -> + begin + match s, Lval.from_exp e with + _, None -> s + | s, Some lv -> + let _, new_s = find_or_create_vertex lv s in + new_s + end + in + { + state = Some s; + formals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_formals kf); + locals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_locals kf); + return = exp_return + } + +let pretty_summary ?(debug=false) fmt s = + let print_list_lval fmt (l: lval list) = + let is_first = ref true in + let print_elem x = + if !is_first then is_first := false else Format.fprintf fmt "@ "; + Format.fprintf fmt "%a" Cil_datatype.Lval.pretty x + in + List.iter print_elem l + in + let print_option pp fmt x = + match x with + | Some x -> pp fmt x + | None -> Format.fprintf fmt "<none>" + in + match s.state with + | None -> if debug then Format.fprintf fmt "not found" + | Some s when is_empty s -> if debug then Format.fprintf fmt "empty" + | _ -> + begin + Format.fprintf fmt "@[formals: @[%a@]@;<3>locals: @[%a@]@;<3>returns: @[%a@]@;<3>state: @[%a@] " + print_list_lval s.formals + print_list_lval s.locals + (print_option Exp.pretty) s.return + (print_option @@ pretty ~debug) s.state; + end + +(* the algorithm: + - unify the two graphs dropping all the variables from the summary + - pair arguments with formals assigning the formal's successor as the argument's successor +*) +let call (state:t) (res:lval option) (args:exp list) (summary:summary) :t = + assert_invariants state; + let formals = summary.formals in + assert (List.length args = List.length formals); + let sum_state = shift @@ Option.get summary.state in + + (* pair up formals and their corresponding arguments, + as well as the bound result with the returned value *) + let arg_formal_pairs = + let res_ret = match res, summary.return with + | None, None -> [] + | Some res, Some ret -> + [Simplified_lval.from_lval res, Option.get @@ Simplified_lval.from_exp ret] + | None, Some _ -> [] + | Some _, None -> (* Shouldn't happen: Frama-C adds missing returns *) + Options.fatal "unexpected case: result without return" + in + let simplify_both (arg, formal) = + try + match Lval.from_exp arg with + | None -> None + | Some lv -> Some (lv, Simplified_lval.from_lval formal) + with Explicit_pointer_address loc -> + Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address + "unsupported feature: explicit pointer address: %a; analysis may be unsound" + Printer.pp_exp arg; + None + in + res_ret @ List.filter_map simplify_both @@ List.combine args formals + in + + (* for each pair (lv1,lv2) find (or create) the corresponding vertices *) + let state, vertex_pairs = + let state = ref state in + let find_vertex (lv1, lv2) = + try + let v2 = LLMap.find lv2 sum_state.lmap in + let v1, new_state = find_or_create_vertex lv1 !state in + state := new_state; + Some (v1, v2) + with Not_found -> None + in + !state, List.filter_map find_vertex arg_formal_pairs + in + + (* merge the function graph; + for every arg/formal vertex pair (v1,v2) and every edge v2→v create edge v1→v. *) + let g = + let transfer_succs (g : G.t) (v1,v2) = + let v2_succs = G.succ sum_state.graph v2 in + assert (List.length v2_succs < 2); + List.fold_left (fun g succ -> G.add_edge g v1 succ) g v2_succs + in + let g = state.graph in + let g = G.fold_vertex (fun i g -> G.add_vertex g i) sum_state.graph g in + let g = G.fold_edges (fun i j g -> G.add_edge g i j) sum_state.graph g in + List.fold_left transfer_succs g vertex_pairs + in + + (* garbage collect: remove leaf vertices from g that originate from sum_state *) + let vertices_to_add_to_g, g = + let g = ref g in + let remove_if_leaf v _ = + if G.in_degree sum_state.graph v = 0 + then let () = g := G.remove_vertex !g v in None + else Some LSet.empty + in + let remaining_vertices = VMap.filter_map remove_if_leaf sum_state.vmap in + remaining_vertices, !g + in + + let state = { + graph = g; + lmap = state.lmap; + vmap = + let left_bias _ l _ = Some l in + VMap.union left_bias state.vmap vertices_to_add_to_g} + in + + let state = List.fold_left join_succs state (List.map fst vertex_pairs) in + assert_invariants state; + state diff --git a/src/plugins/alias/abstract_state.mli b/src/plugins/alias/abstract_state.mli new file mode 100644 index 0000000000000000000000000000000000000000..1faf7e9cf19ebc7661ec34bc3911413acf6c34d3 --- /dev/null +++ b/src/plugins/alias/abstract_state.mli @@ -0,0 +1,126 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +(** Module abstract_state *) + +open Cil_types + +(** Points-to graphs datastructure. *) +module G: Graph.Sig.G + +(** NB : type Lval.t is not the same as type lval !! *) +module LSet = Simplified.Simplified_lset + + +(** external signature *) +module type S = +sig + + (** Type denothing an abstract state of the analysis. It is a graph containing + all aliases and points-to information. *) + type t + + (** access to the points-to graph *) + val get_graph: t -> G.t + + (** set of lvals stored in a vertex *) + val get_lval_set : G.V.t -> t -> LSet.t + + (** pretty printer; debug=true prints the graph, debug = false only + prints aliased variables *) + val pretty : ?debug:bool -> Format.formatter -> t -> unit + + (** dot printer; first argument is a file name *) + val print_dot : string -> t -> unit + + (** finds the vertex corresponding to a lval. May raise @Not_found + *) + val find_vertex : lval -> t -> G.V.t + + (** same as previous function, but return a set of lval. Cannot + raise an exception but may return an empty set if the lval is not + in the graph *) + val find_aliases : lval -> t -> LSet.t + + (** similar to the previous functions, but does not only give the + equivalence class of lv, but also all lv that are aliases in + other vertex of the graph *) + val find_all_aliases : lval -> t -> LSet.t + + (** find_aliases, then recursively finds other sets of lvals. We + have the property (if lval [lv] is in abstract state [x]) : + List.hd (find_transitive_closure lv x) = (find_vertex lv x, + find_aliases lv x) *) + val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list + + (** inclusion test; [is_included a1 a2] tests if, for any lvl + present in a1 (associated to a vertex v1), that it is also + present in a2 (associated to a vertex v2) and that + get_lval_set(succ(v1) is included in get_lval_set(succ(v2)) *) + val is_included : t -> t -> bool + +end + + +include S + +(** check all the invariants that must be true on an abstract value + before and after each function call or transformation of the graph) *) +val assert_invariants : t -> unit + +(** Functions for Steensgaard's algorithm, see the paper *) +val join : t -> G.V.t -> G.V.t -> t + +(** transfert functions for different kinds of assignments *) +val assignment : t -> lval -> exp -> t + +(** transfert function for malloc calls *) +val assignment_x_allocate_y : t -> lval -> t + + +(** inclusion test; [is_included a1 a2] tests if, for any lvl present + in a1 (associated to a vertex v1), that it is also present in a2 + (associated to a vertex v2) and that set(succ(v1) is included in + set(succ(v2)) *) +val is_included : t -> t -> bool + +(** union of two abstract values ; ensures that if 2 lval are + aliased in one of the two input graph (or in a points-to + relationship), then they will also be aliased/points-to in the + result *) +val union : t -> t -> t + +(** empty graph *) +val empty : t + +(** Type denoting summaries of functions *) +type summary + +(** creates a summary from a state and a function *) +val make_summary : t -> kernel_function -> summary + +(** pretty printer *) +val pretty_summary : ?debug:bool -> Format.formatter -> summary -> unit + +(** [call a res args s] computes the abstract state after the + instruction res=f(args), with f summarized by [s]. [a] is the abstract state before the call *) +val call: t -> lval option -> exp list -> summary -> t diff --git a/src/plugins/alias/analysis.ml b/src/plugins/alias/analysis.ml new file mode 100644 index 0000000000000000000000000000000000000000..8583500ff435d1dddeed6e2578b278baac1a2ab7 --- /dev/null +++ b/src/plugins/alias/analysis.ml @@ -0,0 +1,332 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +module Dataflow = Dataflow2 + +module type Table = sig + type key + type value + val find: key -> value + (** @raise Not_found if the key is not in the table. *) +end + +module type InternalTable = sig + include Table + val add : key -> value -> unit + val iter : (key -> value -> unit) -> unit +end + +module Make_table (H: Hashtbl.S) (V: sig type t val size : int end) + : InternalTable with type key = H.key and type value = V.t = struct + type key = H.key + type value = V.t + let tbl = H.create V.size + let add = H.replace tbl + let find = H.find tbl + let iter f = H.iter f tbl +end + +(* In Function_table, value None means the function has no definition *) +module Function_table = Make_table (Kernel_function.Hashtbl) (struct + type t = Abstract_state.summary option + let size = 7 + end) + +let function_compute_ref = Extlib.mk_fun "function_compute" + +(* In Stmt_table, value None means abstract state = Bottom *) +module Stmt_table = struct + include Dataflow.StartData (struct + type t = Abstract_state.t option + let size = 7 + end) + type key = stmt + type value = data +end + +let warn_unsupported_explicit_pointer pp_obj obj loc = + Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address + "unsupported feature: explicit pointer address: %a; analysis may be unsound" pp_obj obj + +let do_assignment (lv:lval) (exp:exp) (a:Abstract_state.t) : Abstract_state.t = + try Abstract_state.assignment a lv exp + with Simplified.Explicit_pointer_address loc -> + warn_unsupported_explicit_pointer Printer.pp_exp exp loc; + a + +let rec do_init (lv:lval) (init:init) state = + match init with + | SingleInit e -> Option.map (do_assignment lv e) state + | CompoundInit (_, l) -> + List.fold_left (fun state (o, init) -> do_init (Cil.addOffsetLval o lv) init state) state l + +let doFunction f = !function_compute_ref f + +let do_function_call (stmt:stmt) state (res : lval option) (ef : exp) (args: exp list) loc = + let is_malloc (s:string) : bool = + (s = "malloc") || (s = "calloc") (* todo : add all function names *) + in + match ef with + | {enode=Lval (Var v, _);_} when is_malloc v.vname -> + begin + (* special case for malloc *) + match (state,res) with + (None, _) -> None + | (Some a, None) -> (Options.warning "Memory allocation not stored (ignored)"; Some a) + | (Some a, Some lv) -> + try Some (Abstract_state.assignment_x_allocate_y a lv) + with Simplified.Explicit_pointer_address loc -> + warn_unsupported_explicit_pointer Printer.pp_stmt stmt loc; + Some a + end + | _ -> + begin + (* general case *) + let summary = + match Kernel_function.get_called ef with + | Some kf when Kernel_function.is_main kf -> None + | Some kf -> begin + try Function_table.find kf + with Not_found -> doFunction kf + end + | None -> + Options.warning ~wkey:Options.Warn.unsupported_function ~source:(fst loc) + "unsupported feature: call to function pointer: %a" Exp.pretty ef; + None + in + match (state, summary) with + (None, _) -> None + | (Some a, Some summary) -> + Some (Abstract_state.call a res args summary) + | (Some a, None) -> + Options.warning ~wkey:Options.Warn.undefined_function ~once:true ~source:(fst loc) + "function %a has no definition" Exp.pretty ef; + Some a + end + +let do_cons_init (s:stmt) (v:varinfo) f arg t loc state = + Cil.treat_constructor_as_func (do_function_call s state) v f arg t loc + +let analyse_instr (s:stmt) (i:instr) (a:Abstract_state.t option) : Abstract_state.t option = + match i with + Set (lv,exp,_) -> Option.map (do_assignment lv exp) a + | Local_init (v,AssignInit i,_) -> do_init (Var v, NoOffset) i a + | Local_init (v,ConsInit (f,arg,t),loc) -> do_cons_init s v f arg t loc a + | Code_annot _ -> a + | Skip _ -> a + | Call (res,ef,es,loc) -> (* !function_compute_ref ef *) + do_function_call s a res ef es loc + | Asm (_,_,_,loc) -> + Options.warning + ~source:(fst loc) ~wkey:Options.Warn.unsupported_asm + "unsupported feature: assembler code; skipping"; + a + +let pp_abstract_state_opt ?(debug=false) fmt v = + match v with + | None -> Format.fprintf fmt "⊥" + | Some a -> Abstract_state.pretty ~debug fmt a + +let do_instr (s:stmt) (i:instr) (a:Abstract_state.t option) : Abstract_state.t option = + Options.feedback ~level:3 "@[analysing instruction:@ %a@]" Printer.pp_stmt s; + let result = analyse_instr s i a in + Options.feedback ~level:3 "@[May-aliases after instruction@;<2>@[%a@]@;<2>are@;<2>@[%a@]@]" + Printer.pp_stmt s (pp_abstract_state_opt ~debug:false) result; + Options.debug ~level:3 "@[May-alias graph after instruction@;<2>@[%a@]@;<2>is@;<4>@[%a@]@]" + Printer.pp_stmt s (pp_abstract_state_opt ~debug:true) result; + result + +module T = struct + let name = "alias" + + let debug = true (* TODO see options *) + + type t = Abstract_state.t option + + module StmtStartData = Stmt_table + + let copy x = x (* we only have persistant data *) + + let pretty fmt a = + match a with + None -> Format.fprintf fmt "<No abstract state>" + | Some a -> Abstract_state.pretty fmt a + + let computeFirstPredecessor _ a = a + + let combinePredecessors _stmt ~old state = + match old, state with + | _, None -> assert false + | None, Some _ -> Some state (* [old] already included in [state] *) + | Some old, Some new_ -> + if Abstract_state.is_included new_ old then + None + else + Some (Some (Abstract_state.union old new_)) + + let doInstr = do_instr + + let doGuard _ _ a = + Dataflow.GUse a, Dataflow.GUse a + + let doStmt _ _ = Dataflow.SDefault + + let doEdge _ _ a = a +end + +module F = Dataflow.Forwards (T) + +let do_stmt (a: Abstract_state.t) (s:stmt) : Abstract_state.t = + match s.skind with + Instr i -> + begin + match do_instr s i (Some a) with + None -> Options.fatal "problem here" + | Some a -> a + end + | _ -> a + +let analyse_function (kf:kernel_function) = + Options.feedback ~level:2 "analysing function: %a" Kernel_function.pretty kf; + if Kernel_function.has_definition kf then + begin + let first_stmt = + try Kernel_function.find_first_stmt kf + with Kernel_function.No_Statement -> assert false + in + T.StmtStartData.add first_stmt (Some Abstract_state.empty); + F.compute [first_stmt]; + let return_stmt = Kernel_function.find_return kf in + try Stmt_table.find return_stmt + with Not_found -> + begin + let source, _ = Kernel_function.get_location kf in + Options.warning ~source ~wkey:Options.Warn.no_return_stmt + "function %a does not return; analysis may be unsound" + Kernel_function.pretty kf; + Some Abstract_state.empty + end + end + else + None + +let doFunction (kf:kernel_function) = + let final_state = analyse_function kf in + let level = if Kernel_function.is_main kf then 1 else 2 in + Options.feedback ~level "@[May-aliases at the end of function %a:@ @[%a@]" + Kernel_function.pretty kf + (pp_abstract_state_opt ~debug:false) final_state; + Options.debug ~level "May-alias graph at the end of function %a:@;<4>@[%a@]" + Kernel_function.pretty kf + (pp_abstract_state_opt ~debug:true) final_state; + let result = + match final_state with + (* final state is None if kf has no definition *) + None -> None + | Some fs -> + let summary = Abstract_state.make_summary fs kf in + Options.debug ~level:2 "Summary of function %a:@ @[%a@]" + Kernel_function.pretty kf + (Abstract_state.pretty_summary ~debug:false) summary; + Some summary + in + if Kernel_function.is_main kf then + let f_name = Options.Dot_output.get () in + begin match f_name, final_state with + | "", _ -> () + | _, None -> () + | _, Some final_state -> Abstract_state.print_dot f_name final_state + end; + None + else + (Function_table.add kf result; result) + +let () = function_compute_ref := doFunction + +let make_summary (state:Abstract_state.t) (kf:kernel_function) = + try + begin + match Function_table.find kf with + Some s -> (state, s) + | None -> Options.fatal "not implemented" + end + with + Not_found -> + begin + match doFunction kf with + Some s -> (state, s) + | None -> Options.fatal "not implemented" + end + +let computed_flag = ref false + +let is_computed () = !computed_flag + +let print_stmt_table_elt fmt k v :unit = + let print_key = Stmt.pretty in + let print_value fmt v = + match v with + | None -> Format.fprintf fmt "<Bot>" + | Some a -> Abstract_state.pretty ~debug:(Options.DebugTable.get ()) fmt a + in + Format.fprintf fmt "Before statement %a :@[<hov 2> %a@]" print_key k print_value v + +let print_function_table_elt fmt kf s : unit = + let function_name = Kernel_function.get_name kf in + match s with + | None -> Options.debug "function %s -> None" function_name + | Some s -> + Format.fprintf fmt "Summary of function %s:@;<5 2>@[%a@]@." + function_name + (Abstract_state.pretty_summary ~debug:(Options.DebugTable.get ())) s + +let compute () = + Ast.compute (); + Globals.Functions.iter (fun kf -> ignore @@ doFunction kf); + computed_flag := true; + if Options.ShowStmtTable.get () then + Stmt_table.iter (print_stmt_table_elt Format.std_formatter); + if Options.ShowFunctionTable.get () then + Function_table.iter (print_function_table_elt Format.std_formatter) + +let clear () = + computed_flag := false; + Stmt_table.clear () + +let get_state_before_stmt _kf stmt = + if is_computed () + then + try Stmt_table.find stmt with + Not_found -> None + else + None + +let get_summary kf = + if is_computed () + then + try Function_table.find kf with + Not_found -> None + else + None diff --git a/src/plugins/alias/analysis.mli b/src/plugins/alias/analysis.mli new file mode 100644 index 0000000000000000000000000000000000000000..e68e807f4c52960915b5a6f1c0b1be5085a22348 --- /dev/null +++ b/src/plugins/alias/analysis.mli @@ -0,0 +1,68 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Cil_types + +open Abstract_state + +module type Table = sig + type key + type value + val find: key -> value + (** @raise Not_found if the key is not in the table. *) +end + +(** Store the graph at each statement. *) +module Stmt_table: Table with type key = stmt and type value = Abstract_state.t option + + +(** Store the summary of each function. *) +module Function_table: + Table with type key = kernel_function and type value = Abstract_state.summary option + +(** [do_stmt a s] computes the abstract state after statement s. This + function does NOT store the result in Stmt_table. *) +val do_stmt: t -> stmt -> t + +(** [make_summary a f] computes the summary of a function (and the + next abstract state if needed) and stores the summary in + [Function_table]. *) +val make_summary: t -> kernel_function -> t * summary + +(** main analysis functions *) + +(** [compute ()] performs the may-alias analysis. It must be done once + before using functions defined in API.ml *) +val compute : unit -> unit + +(** [is_computed ()] returns true iff an analysis was done previously *) +val is_computed : unit -> bool + +(** [clear()] clears caches and imperative structures that are used by + the analysis. All accumulated data are lost. *) +val clear : unit -> unit + +(** see API.mli *) +val get_state_before_stmt : kernel_function -> stmt -> Abstract_state.t option + +(** see API.mli *) +val get_summary : kernel_function -> Abstract_state.summary option diff --git a/src/plugins/alias/dune b/src/plugins/alias/dune new file mode 100644 index 0000000000000000000000000000000000000000..240d498857ac6b2f95d76cde22adb19290d839b7 --- /dev/null +++ b/src/plugins/alias/dune @@ -0,0 +1,51 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of the Frama-C plug-in 'Alias' (alias). ;; +;; ;; +;; Copyright (C) 2022-2023 ;; +;; CEA (Commissariat à l'énergie atomique et aux énergies ;; +;; alternatives) ;; +;; ;; +;; you can redistribute it and/or modify it under the terms of the GNU ;; +;; Lesser General Public License as published by the Free Software ;; +;; Foundation, version 2.1. ;; +;; ;; +;; It is distributed in the hope that it will be useful, ;; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; +;; GNU Lesser General Public License for more details. ;; +;; ;; +;; See the GNU Lesser General Public License version 2.1 ;; +;; for more details (enclosed in the file LICENSE) ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +( rule + (alias frama-c-configure) + (deps (universe)) + (action ( progn + (echo "Alias:" %{lib-available:frama-c-alias.core} "\n") + (echo " - Frama-C:" %{lib-available:frama-c.kernel} "\n") + ) + ) +) + +( env + (release (flags -noassert)) + (_ (flags (:standard -w @a-4))) +) + +( library + (name Alias) + (public_name frama-c-alias.core) + (flags -open Frama_c_kernel :standard) + (libraries frama-c.kernel ocamlgraph unionFind) + (instrumentation (backend landmarks)) +) + +( plugin + (optional) + (name alias) + (libraries frama-c-alias.core) + (site (frama-c plugins)) +) diff --git a/src/plugins/alias/dune-project b/src/plugins/alias/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..ebb133d3d744d00b3aaa9e2385079173551e2c64 --- /dev/null +++ b/src/plugins/alias/dune-project @@ -0,0 +1,35 @@ +(lang dune 3.2) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of the Frama-C plug-in 'Alias' (alias). ;; +;; ;; +;; Copyright (C) 2022-2023 ;; +;; CEA (Commissariat à l'énergie atomique et aux énergies ;; +;; alternatives) ;; +;; ;; +;; you can redistribute it and/or modify it under the terms of the GNU ;; +;; Lesser General Public License as published by the Free Software ;; +;; Foundation, version 2.1. ;; +;; ;; +;; It is distributed in the hope that it will be useful, ;; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; +;; GNU Lesser General Public License for more details. ;; +;; ;; +;; See the GNU Lesser General Public License version 2.1 ;; +;; for more details (enclosed in the file LICENSE) ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +(using dune_site 0.1) +(generate_opam_files true) + +(name frama-c-alias) + +(package (name frama-c-alias) + (depends + ("frama-c" (and (>= 25.0) (< 27.0))) + ("unionFind" (= 20220122)) + ) +) diff --git a/src/plugins/alias/dune-workspace b/src/plugins/alias/dune-workspace new file mode 100644 index 0000000000000000000000000000000000000000..68bfa1b7e2477ba9cc2372df3840f3a32a209c71 --- /dev/null +++ b/src/plugins/alias/dune-workspace @@ -0,0 +1,27 @@ +(lang dune 3.2) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of the Frama-C plug-in 'Alias' (alias). ;; +;; ;; +;; Copyright (C) 2022-2023 ;; +;; CEA (Commissariat à l'énergie atomique et aux énergies ;; +;; alternatives) ;; +;; ;; +;; you can redistribute it and/or modify it under the terms of the GNU ;; +;; Lesser General Public License as published by the Free Software ;; +;; Foundation, version 2.1. ;; +;; ;; +;; It is distributed in the hope that it will be useful, ;; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; +;; GNU Lesser General Public License for more details. ;; +;; ;; +;; See the GNU Lesser General Public License version 2.1 ;; +;; for more details (enclosed in the file LICENSE) ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(context + (default + (env (_ (env-vars ("OCAML_LANDMARKS" "auto"))))) +) diff --git a/src/plugins/alias/frama-c-alias.opam b/src/plugins/alias/frama-c-alias.opam new file mode 100644 index 0000000000000000000000000000000000000000..d6fe954c9b693364a13646be14d8c9d363058dd8 --- /dev/null +++ b/src/plugins/alias/frama-c-alias.opam @@ -0,0 +1,38 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +depends: [ + "dune" {>= "3.2"} + "frama-c" {>= "25.0" & < "27.0"} + "unionFind" {= "20220122"} + "odoc" {with-doc} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "--promote-install-files=false" + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] + ["dune" "install" "-p" name "--create-install-files" name] +] +name: "frama-c-alias" +version: "26" +synopsis: "A Frama-C plug-in for Alias Analysis" +description: """ + A Frama-C plug-in for Alias Analysis +""" +maintainer: "https://git.frama-c.com/pub/frama-c" +authors: [ + "Tristan Le Gall" + "Jan Rochel" +] +license: "Copyright (C) 2022-2022 CEA LIST, All rights reserved. Contact CEA LIST for licensing." +homepage: "http://frama-c.com/" +bug-reports: "https://git.frama-c.com/pub/frama-c" diff --git a/src/plugins/alias/frama-c-alias.opam.template b/src/plugins/alias/frama-c-alias.opam.template new file mode 100644 index 0000000000000000000000000000000000000000..6e90e5eaa83d540d889fa0c3de6147ceeb7db967 --- /dev/null +++ b/src/plugins/alias/frama-c-alias.opam.template @@ -0,0 +1,14 @@ +name: "frama-c-alias" +version: "26" +synopsis: "A Frama-C plug-in for Alias Analysis" +description: """ + A Frama-C plug-in for Alias Analysis +""" +maintainer: "https://git.frama-c.com/pub/frama-c" +authors: [ + "Tristan Le Gall" + "Jan Rochel" +] +license: "Copyright (C) 2022-2022 CEA LIST, All rights reserved. Contact CEA LIST for licensing." +homepage: "http://frama-c.com/" +bug-reports: "https://git.frama-c.com/pub/frama-c" diff --git a/src/plugins/alias/headers/Makefile.generate-headers b/src/plugins/alias/headers/Makefile.generate-headers new file mode 100644 index 0000000000000000000000000000000000000000..54abb31b1f519ceb23ef75f65dd97ebd80eb6908 --- /dev/null +++ b/src/plugins/alias/headers/Makefile.generate-headers @@ -0,0 +1,48 @@ +########################################################################## +# # +# This file is part of the Frama-C plug-in 'Alias' (alias). # +# # +# Copyright (C) 2022-2023 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file LICENSE) # +# # +########################################################################## + +YEAR:=$(shell date +%Y) + +ifeq (${HEADER_OPEN_SOURCE},yes) +DEFAULT_HEADER_DIR:=headers/open-source +else +DEFAULT_HEADER_DIR:=headers/close-source +endif + +headers/%/LICENSE.${PLUGIN_NAME}: headers/%/LICENSE.template FORCE_LICENSES + @sed -e "s/@SHORT_NAME@/${SHORT_NAME}/" \ + -e "s/@LONG_NAME@/${LONG_NAME}/" \ + -e "s/@FROM_YEAR@/${FROM_YEAR}/" \ + -e "s/@YEAR@/${YEAR}/" \ + $< > $@ + +LICENSE.${PLUGIN_NAME}: ${DEFAULT_HEADER_DIR}/LICENSE.${PLUGIN_NAME} FORCE_LICENSES + cp $< $@ + +.PHONY: FORCE_LICENSES +FORCE_LICENSES: + +# Extend headers rule dependencies, make sure to update all license files +headers: \ + headers/open-source/LICENSE.${PLUGIN_NAME} \ + headers/close-source/LICENSE.${PLUGIN_NAME} \ + LICENSE.${PLUGIN_NAME} diff --git a/src/plugins/alias/headers/close-source/LICENSE.Alias b/src/plugins/alias/headers/close-source/LICENSE.Alias new file mode 100644 index 0000000000000000000000000000000000000000..c95856054e39110c49f28537befb0feffebcde37 --- /dev/null +++ b/src/plugins/alias/headers/close-source/LICENSE.Alias @@ -0,0 +1,10 @@ + +This file is part of the Frama-C plug-in 'Alias' (alias). + +Copyright (C) 2022-2023 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +All rights reserved. +Contact CEA LIST for licensing. + diff --git a/src/plugins/alias/headers/close-source/LICENSE.template b/src/plugins/alias/headers/close-source/LICENSE.template new file mode 100755 index 0000000000000000000000000000000000000000..674cd9bba33d1a8f21bd6faf01c90c6943d00413 --- /dev/null +++ b/src/plugins/alias/headers/close-source/LICENSE.template @@ -0,0 +1,10 @@ + +This file is part of the Frama-C plug-in '@LONG_NAME@' (@SHORT_NAME@). + +Copyright (C) @FROM_YEAR@-@YEAR@ + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +All rights reserved. +Contact CEA LIST for licensing. + diff --git a/src/plugins/alias/headers/open-source/LICENSE.Alias b/src/plugins/alias/headers/open-source/LICENSE.Alias new file mode 100644 index 0000000000000000000000000000000000000000..57a2745d01d2fc7935756153dc194f934af4ebf5 --- /dev/null +++ b/src/plugins/alias/headers/open-source/LICENSE.Alias @@ -0,0 +1,19 @@ + +This file is part of the Frama-C plug-in 'Alias' (alias). + +Copyright (C) 2022-2023 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +you can redistribute it and/or modify it under the terms of the GNU +Lesser General Public License as published by the Free Software +Foundation, version 2.1. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +See the GNU Lesser General Public License version 2.1 +for more details (enclosed in the file LICENSE) + diff --git a/src/plugins/alias/headers/open-source/LICENSE.template b/src/plugins/alias/headers/open-source/LICENSE.template new file mode 100644 index 0000000000000000000000000000000000000000..80fe4ef40c50d17af0e98eddc038f98ea6e0b3e8 --- /dev/null +++ b/src/plugins/alias/headers/open-source/LICENSE.template @@ -0,0 +1,19 @@ + +This file is part of the Frama-C plug-in '@LONG_NAME@' (@SHORT_NAME@). + +Copyright (C) @FROM_YEAR@-@YEAR@ + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +you can redistribute it and/or modify it under the terms of the GNU +Lesser General Public License as published by the Free Software +Foundation, version 2.1. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +See the GNU Lesser General Public License version 2.1 +for more details (enclosed in the file LICENSE) + diff --git a/src/plugins/alias/nix/alias.nix b/src/plugins/alias/nix/alias.nix new file mode 100644 index 0000000000000000000000000000000000000000..59e4b01d4972e571bbaf558237829d8cb4cfc445 --- /dev/null +++ b/src/plugins/alias/nix/alias.nix @@ -0,0 +1,10 @@ +{ mk_plugin, + unionFind }: + +mk_plugin { + plugin-name = "alias" ; + plugin-src = fetchGit { shallow=true ; url=./.. ; } ; + additional-build-inputs = [ + unionFind + ] ; +} diff --git a/src/plugins/alias/nix/ci.sh b/src/plugins/alias/nix/ci.sh new file mode 100755 index 0000000000000000000000000000000000000000..698565a0b4dfec45351389ca9ddc54c6c3efa703 --- /dev/null +++ b/src/plugins/alias/nix/ci.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +DEFAULT=${DEFAULT:-master} +NIX_TARGET="alias" +# <plugin> /nix /ci.sh +PLUGIN_DIR="$(dirname "$(dirname "$(readlink -f "$0")")")" + +CURRENT_BRANCH="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-}" +: "${CURRENT_BRANCH:="${CI_COMMIT_REF_NAME:-}"}" +: "${CURRENT_BRANCH:="$(git branch --show-current)"}" + +# prints +# - "$CURRENT_BRANCH" if it is a branch name in remote $1, +# - else "$DEFAULT" if it is set and $DEFAULT is a branch name in remote $1, +# - else master +get_matching_branch () { + if git ls-remote --quiet --exit-code "$1" "$CURRENT_BRANCH" >/dev/null 2>/dev/null; + then echo "$CURRENT_BRANCH" + elif git ls-remote --quiet --exit-code "$1" "$DEFAULT" >/dev/null 2>/dev/null; + then echo "$DEFAULT" + else echo master + fi +} + +TMP_DIR="$(mktemp -d)" + +cleanup () { + rm -rf $TMP_DIR +} + +trap cleanup EXIT + +mkdir -p $TMP_DIR/frama-ci +frama_ci_repo="$(readlink -f $TMP_DIR/frama-ci)" +frama_ci_url="git@git.frama-c.com:frama-c/Frama-CI.git" +frama_ci_branch="$(get_matching_branch "$frama_ci_url")" +echo "using branch $frama_ci_branch of Frama-CI repo at $frama_ci_repo" +git clone --depth=1 --branch="$frama_ci_branch" "$frama_ci_url" "$frama_ci_repo" + +source $frama_ci_repo/common-plugin-ci.sh diff --git a/src/plugins/alias/nix/pkgs.nix b/src/plugins/alias/nix/pkgs.nix new file mode 100644 index 0000000000000000000000000000000000000000..fd59e529bc8b0d037e1c2e668e603ca433633985 --- /dev/null +++ b/src/plugins/alias/nix/pkgs.nix @@ -0,0 +1,16 @@ +{ frama-c-repo ? builtins.trace "alias: defaulting frama-c-repo to ${toString ../../frama-c}" ../../frama-c }: +let + ocamlOverlay = oself: osuper: { + alias = oself.callPackage ./alias.nix {}; + }; + overlay = self: super: { + ocaml-ng = super.lib.mapAttrs ( + name: value: + if builtins.hasAttr "overrideScope'" value + then value.overrideScope' ocamlOverlay + else value + ) super.ocaml-ng; + }; + pkgs = (import (frama-c-repo + "/nix/pkgs.nix")).appendOverlays [ overlay ]; +in +pkgs diff --git a/src/plugins/alias/options.ml b/src/plugins/alias/options.ml new file mode 100644 index 0000000000000000000000000000000000000000..2f70a980efbec330d5124899c0070f6b9b86f612 --- /dev/null +++ b/src/plugins/alias/options.ml @@ -0,0 +1,82 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Plugin Registration --- *) +(* -------------------------------------------------------------------------- *) + +include Plugin.Register + (struct + let name = "Alias Analysis" + let help = "Lightweight May-Alias Analysis" + let shortname = "alias" + end) + + +module Enabled = False + (struct + let option_name = "-alias" + let help = "Allows May-Alias Analyzer" + end) + + +module ShowFunctionTable = False + (struct + let option_name = "-alias-show-function-table" + let help = "Displays the table [function -> summary] at the end of the analysis" + end) + + +module ShowStmtTable = False + (struct + let option_name = "-alias-show-stmt-table" + let help = "Displays the table [stmt -> abstract state] at the end of the analysis" + end) + + +module DebugTable = False + (struct + let option_name = "-alias-debug-table" + let help = "switch to debug mode when printing Statement or Function Tables (with options -alias-show-stmt-table and -alias-show-function-table)" + end) + + +module Dot_output = + Empty_string + (struct + let option_name = "-alias-dot-output" + let arg_name = "f" + let help = "Displays the final abstract state in Dot File <f>" + end) + +module Warn = struct + let no_return_stmt = register_warn_category "no-return" + let undefined_function = register_warn_category "undefined:fn" + let unsupported_address = register_warn_category "unsupported:addr" + let unsupported_asm = register_warn_category "unsupported:asm" + let unsupported_function = register_warn_category "unsupported:fn" + let unsafe_cast = register_warn_category "unsafe-cast" +end + +module DebugKeys = struct + let lvals = register_category "lvals" +end diff --git a/src/plugins/alias/options.mli b/src/plugins/alias/options.mli new file mode 100644 index 0000000000000000000000000000000000000000..1a5dd44638c084c430049a9b2c81dc85dc3dd199 --- /dev/null +++ b/src/plugins/alias/options.mli @@ -0,0 +1,55 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Plugin Registration --- *) +(* -------------------------------------------------------------------------- *) + +include Plugin.S + +(** Module activation *) +module Enabled : Parameter_sig.Bool + +(** Displays the table [function -> summary] at the end of the analysis *) +module ShowFunctionTable : Parameter_sig.Bool + +(** Displays the table [statement -> state] at the end of the analysis *) +module ShowStmtTable : Parameter_sig.Bool + +(** Switch to debug mode when displaying tables *) +module DebugTable : Parameter_sig.Bool + +(** Displays the final abstract state in Dot File <f> *) +module Dot_output : Parameter_sig.String + +module Warn : sig + val no_return_stmt : warn_category + val undefined_function : warn_category + val unsupported_address : warn_category + val unsupported_asm : warn_category + val unsupported_function : warn_category + val unsafe_cast : warn_category +end + +module DebugKeys : sig + val lvals : category +end diff --git a/src/plugins/alias/simplified.ml b/src/plugins/alias/simplified.ml new file mode 100644 index 0000000000000000000000000000000000000000..3a639dee7bd54b6bb7535091a5a45eec5170cf04 --- /dev/null +++ b/src/plugins/alias/simplified.ml @@ -0,0 +1,236 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Cil_types + +open Cil_datatype + +let nul_exp= + let loc = Location.unknown in + Cil.zero ~loc + +let is_nul_exp = Cil_datatype.ExpStructEq.equal nul_exp + +module HL = Lval.Hashtbl + +module HE = Exp.Hashtbl + +let cached_lval = HL.create 23 + +let cached_exp = HE.create 37 + +let clear_cache () = + HL.clear cached_lval; + HE.clear cached_exp + +exception Explicit_pointer_address of location + +let check_cast_compatibility e typ = + let type_of_e = Cil.typeOf e in + (* emit a warning for unsafe casts, but not for the NULL pointer *) + if Cil.need_cast typ type_of_e && not (Cil.isZero e) then + Options.warning + ~once:true + ~source:(fst @@ e.eloc) + ~wkey:Options.Warn.unsafe_cast + "unsafe cast from %a to %a" + Printer.pp_typ type_of_e Printer.pp_typ typ + +let rec simplify_lval (h,o) = + try HL.find cached_lval (h,o) + with Not_found -> + let res = (simplify_host h, simplify_offset o) in + HL.add cached_lval (h,o) res; + res + +and simplify_host h = + match h with + | Var _ -> h + | Mem e -> + let simp_e = simplify_exp e in + if is_nul_exp simp_e + then raise (Explicit_pointer_address e.eloc) + else Mem simp_e + +and simplify_offset o = + match o with + | NoOffset -> NoOffset + | Field(f,o) -> Field(f, simplify_offset o) + | Index(_e,o) -> Index(nul_exp, simplify_offset o) + +and simplify_exp e = + try + HE.find cached_exp e + with Not_found -> + let res = + match e.enode with + | CastE (typ, e) -> + check_cast_compatibility e typ; + simplify_exp e + | Lval lv -> {e with enode = Lval (simplify_lval lv)} + | AddrOf lv | StartOf lv -> {e with enode = AddrOf (simplify_lval lv)} + | BinOp(PlusPI, e1, _, _) | BinOp(MinusPI, e1, _, _) -> + begin + match (simplify_exp e1).enode with + | Lval _ | AddrOf _ as node -> {e with enode = node} + | _ -> raise (Explicit_pointer_address e1.eloc) + end + | _ -> e + in + HE.add cached_exp e res; + res + +type simplified_lval = + | BLval of lval + | BAddrOf of lval + +module Simplified_lval = struct + + type t = simplified_lval + + let from_lval lv = + BLval (simplify_lval lv) + + let from_exp e = + let e = simplify_exp e in + match e.enode with + Lval lv -> Some (BLval lv) + | AddrOf lv -> Some (BAddrOf lv) + | _ -> None + + let compare x1 x2 = + match (x1,x2) with + | (BLval lv1, BLval lv2) -> Cil_datatype.LvalStructEq.compare lv1 lv2 + | (BLval _, _) -> -1 + | (_, BLval _) -> 1 + | (BAddrOf lv1, BAddrOf lv2) -> Cil_datatype.LvalStructEq.compare lv1 lv2 + + let print f fmt x = + match x with + | BLval lv -> f fmt lv + | BAddrOf lv -> Format.fprintf fmt "&%a" f lv + + let pretty l = + if Options.is_debug_key_enabled Options.DebugKeys.lvals + then print Cil_types_debug.pp_lval l + else print Printer.pp_lval l + + let removeOffsetLval x = + match x with + | BLval lv -> let lv,o = Cil.removeOffsetLval lv in BLval lv, o + | BAddrOf lv -> let lv,o = Cil.removeOffsetLval lv in BAddrOf lv, o + + let addOffsetLval o x = + match x with + | BLval lv -> let lv = Cil.addOffsetLval o lv in BLval lv + | BAddrOf lv -> let lv = Cil.addOffsetLval o lv in BAddrOf lv + + let points_to x = + match x with + | BAddrOf lv -> BLval lv + | BLval lv -> + BLval (Mem (Cil.dummy_exp (Lval lv)), NoOffset) + + let is_pointer x = + match x with + | BAddrOf _ -> true + | BLval lv -> + let t = Cil.typeOfLval lv in + match Cil.unrollType t with + TPtr _ | TArray _ -> true + | _ -> false +end + +module Simplified_lmap = +struct + include Map.Make (Simplified_lval) + + let print (f_key: Format.formatter -> key -> unit) (f_val : Format.formatter -> 'a -> unit) fmt (m: 'a t) = + let is_first = ref true in + Format.fprintf fmt "{@[<hov 2>"; + iter (fun k v -> + if not !is_first + then + Format.fprintf fmt ",@," + else + is_first := false; + Format.fprintf fmt " %a -> %a" f_key k f_val v + ) + m; + Format.fprintf fmt " @]}" + + let pretty f fmt m = print Simplified_lval.pretty f fmt m +end + +module Simplified_lset = +struct + include Set.Make (Simplified_lval) + + let print (f_elt: Format.formatter -> elt -> unit) fmt (m: t) = + let is_first = ref true in + Format.fprintf fmt "{@["; + iter (fun e -> + if !is_first + then + is_first := false + else + Format.fprintf fmt ",@ "; + Format.fprintf fmt "%a" f_elt e + ) + m; + Format.fprintf fmt "@]}" + + let pretty fmt s = print Simplified_lval.pretty fmt s + + let fold_lval f s init = + let f_fold lv acc = + match lv with + | BLval lv -> f lv acc + | BAddrOf lv -> f lv acc + in + fold f_fold s init +end + +let decompose_lval (lv1: Simplified_lval.t) : (Simplified_lval.t*offset) list = + let rec list_of_offset (o: offset) : (offset*offset) list = + match o with + NoOffset -> [NoOffset,o] + | Index(e,ofs) -> + let li = + List.map + (fun (o1,o2) -> (Index(e,o1),o2)) + (list_of_offset ofs) + in + (NoOffset,o)::li + | Field(f, ofs) -> + let li = + List.map + (fun (o1,o2) -> (Field(f,o1),o2)) + (list_of_offset ofs) + in + (NoOffset,o)::li + in + let lv, off = Simplified_lval.removeOffsetLval lv1 in + List.map + (fun (o1,o2) -> (Simplified_lval.addOffsetLval o1 lv,o2)) + (list_of_offset off) + diff --git a/src/plugins/alias/simplified.mli b/src/plugins/alias/simplified.mli new file mode 100644 index 0000000000000000000000000000000000000000..3757c46d4f21d6a78b1fb615f5c8569f6904f3e2 --- /dev/null +++ b/src/plugins/alias/simplified.mli @@ -0,0 +1,83 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C plug-in 'Alias' (alias). *) +(* *) +(* Copyright (C) 2022-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file LICENSE) *) +(* *) +(**************************************************************************) + +open Cil_types + +type simplified_lval = + | BLval of lval (* lval *) + | BAddrOf of lval (* address *) + +(* exception raised when the program tries to access a memory location directly. *) +exception Explicit_pointer_address of location + +module Simplified_lval: +sig + type t = simplified_lval + + val compare: t -> t -> int + + (* result stored in cache. May raise Explicit_pointer_address *) + val from_lval: lval -> t + + (* result stored in cache. May raise Explicit_pointer_address *) + val from_exp: exp -> t option + + val pretty: Format.formatter -> t -> unit + + (* maps !Cil.removeOffsetLval to simplified_lval *) + val removeOffsetLval : t -> t * offset + + (* maps !Cil.addOffsetLval to simplified_lval *) + val addOffsetLval : offset -> t -> t + + (* (points_to x) = *x and (points_to &x) = x. Raise + Explicit_pointer_address when applied to BNone *) + val points_to : t -> t + + (* true if x is assimilable to a pointer type (explicit pointer or + memory adress or array *) + val is_pointer : t -> bool +end + +module Simplified_lmap: +sig + include Map.S with type key = Simplified_lval.t + + val pretty: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit +end + +module Simplified_lset: +sig + include Set.S with type elt = Simplified_lval.t + + val pretty: Format.formatter -> t -> unit + + (* special fold *) + val fold_lval : (lval -> 'a -> 'a) -> t -> 'a -> 'a + +end + +val decompose_lval : Simplified_lval.t -> (Simplified_lval.t*offset) list + +(** clear the two caches *) +val clear_cache : unit -> unit + diff --git a/src/plugins/alias/tests/basic/addrof.c b/src/plugins/alias/tests/basic/addrof.c new file mode 100644 index 0000000000000000000000000000000000000000..838b4527950aea8619e4674e3e121b8d31439bd1 --- /dev/null +++ b/src/plugins/alias/tests/basic/addrof.c @@ -0,0 +1,11 @@ +int main () { + int **a, ***b, **y, *x, *z, p; + a = &x; + b = &y; + if (p) + y = &z; + else + *y = x; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment1.c b/src/plugins/alias/tests/basic/assignment1.c new file mode 100644 index 0000000000000000000000000000000000000000..2851d98907fe53177b4139ba9868a78f6201cf74 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment1.c @@ -0,0 +1,11 @@ +// single pointer assignment +// {a, b, c, d} are aliased + +int main () { + + int *a=0, *b=0, *c=0, *d=0; + a = b; + b = c; + a = d; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment2.c b/src/plugins/alias/tests/basic/assignment2.c new file mode 100644 index 0000000000000000000000000000000000000000..ba0a8dc53e64428a841d94466d52a9f6cfda563a --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment2.c @@ -0,0 +1,13 @@ +// double pointer assignment +// {a, c} are aliased +// {*a, *c, b, d} are aliased + + +int main () { + + int **a=0, *b=0, **c=0, *d=0; + *a = b; + *c = d; + a = c; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment3.c b/src/plugins/alias/tests/basic/assignment3.c new file mode 100644 index 0000000000000000000000000000000000000000..203e93650c145bd0ee2a10cf547852a24551c02f --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment3.c @@ -0,0 +1,10 @@ +// address assignment +// {a, c} are aliased + +int main () { + + int *a=0, b=0, *c=0; + a = &b; + c = &b; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment4.c b/src/plugins/alias/tests/basic/assignment4.c new file mode 100644 index 0000000000000000000000000000000000000000..136a763cb531aa5b7ac9db937a41a49d60ca5041 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment4.c @@ -0,0 +1,13 @@ +// double pointer assignment +// {a, c} are aliased +// {*a, *c, b, d} are aliased + + +int main () { + + int **a=0, *b=0, **c=0, *d=0; + *a = b; + *c = d; + b = d; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment5.c b/src/plugins/alias/tests/basic/assignment5.c new file mode 100644 index 0000000000000000000000000000000000000000..03ccff7f6bf62d8eb127a9ff487c1b3bb0ecd6c4 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment5.c @@ -0,0 +1,12 @@ +// triple pointer assignment with some tricky alias +// {*a, b} are aliased +// {*(*a), *b, c, d} are aliased + +int main () { + + int ***a=0, **b=0, *c=0, *d=0; + *a = b; + *b = c; + d = **a; + return 0; +} diff --git a/src/plugins/alias/tests/basic/cast1.c b/src/plugins/alias/tests/basic/cast1.c new file mode 100644 index 0000000000000000000000000000000000000000..4a0713d879d9ae2d319aba0c359a3d8f8dedc102 --- /dev/null +++ b/src/plugins/alias/tests/basic/cast1.c @@ -0,0 +1,14 @@ +// homogeneous cast +// {a, c} are aliased +// {b, d} are aliased + + +int main () { + + int *a=0, *b=0; + float *c=0, *d=0; + a = (int*) c; + d = (float*) b; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional1.c b/src/plugins/alias/tests/basic/conditional1.c new file mode 100644 index 0000000000000000000000000000000000000000..a668cd7d083a810096ccde023c6fa83985ad2105 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional1.c @@ -0,0 +1,15 @@ +// conditional cfg +// {a, b, c} are aliased + +int main () { + + int *a=0, *b=0, *c=0; + if (a) { + a = b; + } + else { + a = c; + } + *a = 4; + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional2.c b/src/plugins/alias/tests/basic/conditional2.c new file mode 100644 index 0000000000000000000000000000000000000000..7243bebdbde9675572b75eaa0c134bd65bd65fe1 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional2.c @@ -0,0 +1,20 @@ +// conditional cfg +// {*a, *b, c} are aliased +// {*(*a), *(*b), *c, d} are aliased +// {a, b} are aliased + + +int main () { + + int ***a, ***b, **c, *d, e; + b = &c; + c = &d; + d = &e; + if (a) { + a = b; + } + else { + a = &c; + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional3.c b/src/plugins/alias/tests/basic/conditional3.c new file mode 100644 index 0000000000000000000000000000000000000000..06d7dfbc131d38402a4ddbd96245cd579a4c1d44 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional3.c @@ -0,0 +1,26 @@ +// conditional with multiple levels of indirection +// {a, b, c} are aliased +// {*a, *b, *c, i, j} are aliased +// {*(*a), *(*b), *(*c), *i, *j, x, y} are aliased +// {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} are aliased + + + +int main () { + int ****a, ****b, ****c, ***i, ***j, **x, **y, *t, *u, p; + if (p) { + a=b; + b=&i; + i=&x; + x=&t; + } + else { + a=c; + c=&j; + j=&y; + y=&u; + } + p=0; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/function1.c b/src/plugins/alias/tests/basic/function1.c new file mode 100644 index 0000000000000000000000000000000000000000..63bc345a7f779fd9c10517e951607731a896436b --- /dev/null +++ b/src/plugins/alias/tests/basic/function1.c @@ -0,0 +1,20 @@ +// function with no return +// {a, b} are aliased +// {c, d} are aliased + + +void swap(int *x, int* y) { + int*z=0; + z=x; + x=y; + y=z; +} + + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + swap(a,b); + swap(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function2.c b/src/plugins/alias/tests/basic/function2.c new file mode 100644 index 0000000000000000000000000000000000000000..e4411348cb39b56e76064ab07e3b5488281ed455 --- /dev/null +++ b/src/plugins/alias/tests/basic/function2.c @@ -0,0 +1,18 @@ +// malloc +// no alias + +#include <stdlib.h> + +int* my_malloc(int size) { + int* res=0; + res = malloc(size); + return res; +} + +int main(void) +{ + int *a=0, *b=0; + a=my_malloc(2); + b=my_malloc(3); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function3.c b/src/plugins/alias/tests/basic/function3.c new file mode 100644 index 0000000000000000000000000000000000000000..2142dcd0adefbce2ee3397a11d0c13efbb286ae2 --- /dev/null +++ b/src/plugins/alias/tests/basic/function3.c @@ -0,0 +1,23 @@ +// function with a loop inside +// {a, b} are aliased +// {c, d} are aliased + +void *f1(int *x, int* y) +{ + int *tmp = x; + + while (1) { + x=y; + y=tmp; + break; + } + return (void *) 0; +} + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + f1(a,b); + f1(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function4.c b/src/plugins/alias/tests/basic/function4.c new file mode 100644 index 0000000000000000000000000000000000000000..806b68cc3c364ead33143a0ad0a85e0cd9802a94 --- /dev/null +++ b/src/plugins/alias/tests/basic/function4.c @@ -0,0 +1,15 @@ +// funxtion with address agument +// {a, b} are aliased + +int * addr(int* x) +{ + return x; +} + +int main(void) +{ + int *a=0, *b=0, c=0; + a = addr(&c); + b = &c; + return 0; +} diff --git a/src/plugins/alias/tests/basic/function5.c b/src/plugins/alias/tests/basic/function5.c new file mode 100644 index 0000000000000000000000000000000000000000..94247a286c146fc451f4f7107846146d9a43d995 --- /dev/null +++ b/src/plugins/alias/tests/basic/function5.c @@ -0,0 +1,19 @@ +// function with multiple returns +// {a, b, c} are aliased + + +int * choice(int* x, int* y) +{ + int c=0; + if (c) + return x; + else + return y; +} + +int main(void) +{ + int *a=0, *b=0, *c=0; + c = choice(a,b); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function6.c b/src/plugins/alias/tests/basic/function6.c new file mode 100644 index 0000000000000000000000000000000000000000..416136692b9b58787dbd32ad55e216c24b5c4ad7 --- /dev/null +++ b/src/plugins/alias/tests/basic/function6.c @@ -0,0 +1,19 @@ +// function with no return +// no alias + + +void swap(int *x, int* y) { + int z=0; + z=*x; + *x=*y; + *y=z; +} + + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + swap(a,b); + swap(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/globctr.c b/src/plugins/alias/tests/basic/globctr.c new file mode 100644 index 0000000000000000000000000000000000000000..5b399b157aef468a2f7824d7cf13b636a4570036 --- /dev/null +++ b/src/plugins/alias/tests/basic/globctr.c @@ -0,0 +1,12 @@ +void f(int *x) { + int y = 0; + *x = y; +} + +int main(void) +{ + int *a=0, *b=0; + f(a); + f(b); + return 0; +} diff --git a/src/plugins/alias/tests/basic/loop.c b/src/plugins/alias/tests/basic/loop.c new file mode 100644 index 0000000000000000000000000000000000000000..1b8f58d53345c679b86556995b74d7b37bdd9ea1 --- /dev/null +++ b/src/plugins/alias/tests/basic/loop.c @@ -0,0 +1,15 @@ +// used to lead to a loop in the graph - fixed +// no alias since there is an infinite loop + +int main() +{ + while (1) { + int l[1] = {0}; + int *n_0 = & l[1]; + n_0 = & l[1] + 0; + int w = 0; + if (w) + l[0] = *(& l[1] + 0); + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/oracle/addrof.res.oracle b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8b2b579be28d8eee2dbeedad41454f7dcba4fbe9 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing addrof.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = & x; +[alias] May-aliases after instruction a = & x; are {*a, x} +[alias] analysing instruction: b = & y; +[alias] May-aliases after instruction b = & y; are {*a, x} {*b, y} +[alias] analysing instruction: y = & z; +[alias] May-aliases after instruction y = & z; are + {*a, x} {*b, y} {*(*b), *y, z} +[alias] analysing instruction: *y = x; +[alias] May-aliases after instruction *y = x; are {*(*b), *a, *y, x} {*b, a, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {*b, a, y} {*(*b), *a, *y, x, z} +[alias] May-aliases at the end of function main: {*b, a, y} {*(*b), *a, *y, x, z} diff --git a/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3c262c6c2ce8463df14d5cf6c6d31fadae384515 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: b = c; +[alias] May-aliases after instruction b = c; are {a, b, c} +[alias] analysing instruction: a = d; +[alias] May-aliases after instruction a = d; are {a, b, c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c, d} +[alias] May-aliases at the end of function main: {a, b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0ad4f006ba3b3cf35f8fae1b61a40345b12f4143 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int **a = (int **)0; +[alias] May-aliases after instruction int **a = (int **)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int **c = (int **)0; +[alias] May-aliases after instruction int **c = (int **)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *c = d; +[alias] May-aliases after instruction *c = d; are {*a, b} {*c, d} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} {*a, *c, b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {*a, *c, b, d} +[alias] May-aliases at the end of function main: {a, c} {*a, *c, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..65a7c76ee2a2b772a961b9574d747983a02c03a3 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing assignment3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int b = 0; +[alias] May-aliases after instruction int b = 0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = & b; +[alias] May-aliases after instruction a = & b; are <none> +[alias] analysing instruction: c = & b; +[alias] May-aliases after instruction c = & b; are {a, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} +[alias] May-aliases at the end of function main: {a, c} diff --git a/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c422587f1a0662ac753d85d13b48ce30d9779b0d --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment4.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int **a = (int **)0; +[alias] May-aliases after instruction int **a = (int **)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int **c = (int **)0; +[alias] May-aliases after instruction int **c = (int **)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *c = d; +[alias] May-aliases after instruction *c = d; are {*a, b} {*c, d} +[alias] analysing instruction: b = d; +[alias] May-aliases after instruction b = d; are {a, c} {*a, *c, b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {*a, *c, b, d} +[alias] May-aliases at the end of function main: {a, c} {*a, *c, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fc9d35993fc2fd1d3228b9f1888ccc80efc11155 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment5.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int ***a = (int ***)0; +[alias] May-aliases after instruction int ***a = (int ***)0; are <none> +[alias] analysing instruction: int **b = (int **)0; +[alias] May-aliases after instruction int **b = (int **)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *b = c; +[alias] May-aliases after instruction *b = c; are {*a, b} {*(*a), *b, c} +[alias] analysing instruction: d = *(*a); +[alias] May-aliases after instruction d = *(*a); are {*a, b} {*(*a), *b, c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {*a, b} {*(*a), *b, c, d} +[alias] May-aliases at the end of function main: {*a, b} {*(*a), *b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/cast1.res.oracle b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efb26a239fe217242d96a035e5f532512856f69e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing cast1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: float *c = (float *)0; +[alias] May-aliases after instruction float *c = (float *)0; are <none> +[alias] analysing instruction: float *d = (float *)0; +[alias] May-aliases after instruction float *d = (float *)0; are <none> +[alias] analysing instruction: a = (int *)c; +[alias:unsafe-cast] cast1.c:10: Warning: unsafe cast from float * to int * +[alias] May-aliases after instruction a = (int *)c; are {a, c} +[alias] analysing instruction: d = (float *)b; +[alias:unsafe-cast] cast1.c:11: Warning: unsafe cast from int * to float * +[alias] May-aliases after instruction d = (float *)b; are {a, c} {b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {b, d} +[alias] May-aliases at the end of function main: {a, c} {b, d} diff --git a/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c903b74f5fe55bbca3300a508bb311813cbdd43c --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing conditional1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} +[alias] analysing instruction: *a = 4; +[alias] May-aliases after instruction *a = 4; are {a, b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c} +[alias] May-aliases at the end of function main: {a, b, c} diff --git a/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6088f9fb04df624989e4038e8fc723c7f40e880e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing conditional2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: b = & c; +[alias] May-aliases after instruction b = & c; are {*b, c} +[alias] analysing instruction: c = & d; +[alias] May-aliases after instruction c = & d; are {*b, c} {*(*b), *c, d} +[alias] analysing instruction: d = & e; +[alias] May-aliases after instruction d = & e; are {*b, c} {*(*b), *c, d} +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] analysing instruction: a = & c; +[alias] May-aliases after instruction a = & c; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] May-aliases at the end of function main: + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..19088629ddb2ab448d832017d538ed52f23d0a08 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle @@ -0,0 +1,35 @@ +[kernel] Parsing conditional3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: b = & i; +[alias] May-aliases after instruction b = & i; are {a, b} {*a, *b, i} +[alias] analysing instruction: i = & x; +[alias] May-aliases after instruction i = & x; are + {a, b} {*a, *b, i} {*(*a), *(*b), *i, x} +[alias] analysing instruction: x = & t; +[alias] May-aliases after instruction x = & t; are + {a, b} {*a, *b, i} {*(*a), *(*b), *i, x} + {*(*(*a)), *(*(*b)), *(*i), *x, t} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} +[alias] analysing instruction: c = & j; +[alias] May-aliases after instruction c = & j; are {a, c} {*a, *c, j} +[alias] analysing instruction: j = & y; +[alias] May-aliases after instruction j = & y; are + {a, c} {*a, *c, j} {*(*a), *(*c), *j, y} +[alias] analysing instruction: y = & u; +[alias] May-aliases after instruction y = & u; are + {a, c} {*a, *c, j} {*(*a), *(*c), *j, y} + {*(*(*a)), *(*(*c)), *(*j), *y, u} +[alias] analysing instruction: p = 0; +[alias] May-aliases after instruction p = 0; are + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} +[alias] May-aliases at the end of function main: + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} diff --git a/src/plugins/alias/tests/basic/oracle/function1.res.oracle b/src/plugins/alias/tests/basic/oracle/function1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a22d297fdc0acd740dd01e992ac832c4051e6257 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function1.res.oracle @@ -0,0 +1,31 @@ +[kernel] Parsing function1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: swap(a,b); +[alias] analysing function: swap +[alias] analysing instruction: int *z = (int *)0; +[alias] May-aliases after instruction int *z = (int *)0; are <none> +[alias] analysing instruction: z = x; +[alias] May-aliases after instruction z = x; are {x, z} +[alias] analysing instruction: x = y; +[alias] May-aliases after instruction x = y; are {x, y, z} +[alias] analysing instruction: y = z; +[alias] May-aliases after instruction y = z; are {x, y, z} +[alias] May-aliases at the end of function swap: {x, y, z} +[alias] May-aliases after instruction swap(a,b); are {a, b} +[alias] analysing instruction: swap(c,d); +[alias] May-aliases after instruction swap(c,d); are {a, b} {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} {c, d} +[alias] May-aliases at the end of function main: {a, b} {c, d} +[alias] analysing function: swap +[alias] analysing instruction: int *z = (int *)0; +[alias] May-aliases after instruction int *z = (int *)0; are <none> +[alias] May-aliases at the end of function swap: {x, y, z} diff --git a/src/plugins/alias/tests/basic/oracle/function2.res.oracle b/src/plugins/alias/tests/basic/oracle/function2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1e4decb3e431ddaeca4ca82775f8bc469b5f9756 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function2.res.oracle @@ -0,0 +1,136 @@ +[kernel] Parsing function2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: a = my_malloc(2); +[alias] analysing function: my_malloc +[alias] analysing instruction: int *res = (int *)0; +[alias] May-aliases after instruction int *res = (int *)0; are <none> +[alias] analysing instruction: res = (int *)malloc((size_t)size); +[alias] May-aliases after instruction res = (int *)malloc((size_t)size); are + <none> +[alias] May-aliases at the end of function my_malloc: <none> +[alias] May-aliases after instruction a = my_malloc(2); are <none> +[alias] analysing instruction: b = my_malloc(3); +[alias] May-aliases after instruction b = my_malloc(3); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: my_malloc +[alias] analysing instruction: int *res = (int *)0; +[alias] May-aliases after instruction int *res = (int *)0; are <none> +[alias] May-aliases at the end of function my_malloc: <none> +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/basic/oracle/function3.res.oracle b/src/plugins/alias/tests/basic/oracle/function3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d32eba5759924636897ce753d362cec982b56a90 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function3.res.oracle @@ -0,0 +1,27 @@ +[kernel] Parsing function3.c (with preprocessing) +[alias] analysing function: f1 +[alias] analysing instruction: int *tmp = x; +[alias] May-aliases after instruction int *tmp = x; are {x, tmp} +[alias] analysing instruction: x = y; +[alias] May-aliases after instruction x = y; are {x, y, tmp} +[alias] analysing instruction: y = tmp; +[alias] May-aliases after instruction y = tmp; are {x, y, tmp} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are {x, y, tmp} +[alias] May-aliases at the end of function f1: {x, y, tmp} +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: f1(a,b); +[alias] May-aliases after instruction f1(a,b); are {a, b} +[alias] analysing instruction: f1(c,d); +[alias] May-aliases after instruction f1(c,d); are {a, b} {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} {c, d} +[alias] May-aliases at the end of function main: {a, b} {c, d} diff --git a/src/plugins/alias/tests/basic/oracle/function4.res.oracle b/src/plugins/alias/tests/basic/oracle/function4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..45fcb1233288f772757cf41cb588a61287b17484 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function4.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing function4.c (with preprocessing) +[alias] analysing function: addr +[alias] May-aliases at the end of function addr: <none> +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int c = 0; +[alias] May-aliases after instruction int c = 0; are <none> +[alias] analysing instruction: a = addr(& c); +[alias] May-aliases after instruction a = addr(& c); are {a, &c} +[alias] analysing instruction: b = & c; +[alias] May-aliases after instruction b = & c; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/function5.res.oracle b/src/plugins/alias/tests/basic/oracle/function5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..300762d6f2d441f3222d3ca79dcda3f7e0b4fd0d --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function5.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing function5.c (with preprocessing) +[alias] analysing function: choice +[alias] analysing instruction: int c = 0; +[alias] May-aliases after instruction int c = 0; are <none> +[alias] analysing instruction: __retres = x; +[alias] May-aliases after instruction __retres = x; are {x, __retres} +[alias] analysing instruction: __retres = y; +[alias] May-aliases after instruction __retres = y; are {y, __retres} +[alias] May-aliases at the end of function choice: {x, y, __retres} +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: c = choice(a,b); +[alias] May-aliases after instruction c = choice(a,b); are {a, b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c} +[alias] May-aliases at the end of function main: {a, b, c} diff --git a/src/plugins/alias/tests/basic/oracle/function6.res.oracle b/src/plugins/alias/tests/basic/oracle/function6.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4d8f8fa4a01fce5e95e6b5afdc4c4f24aec1c045 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function6.res.oracle @@ -0,0 +1,31 @@ +[kernel] Parsing function6.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: swap(a,b); +[alias] analysing function: swap +[alias] analysing instruction: int z = 0; +[alias] May-aliases after instruction int z = 0; are <none> +[alias] analysing instruction: z = *x; +[alias] May-aliases after instruction z = *x; are <none> +[alias] analysing instruction: *x = *y; +[alias] May-aliases after instruction *x = *y; are <none> +[alias] analysing instruction: *y = z; +[alias] May-aliases after instruction *y = z; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(a,b); are <none> +[alias] analysing instruction: swap(c,d); +[alias] May-aliases after instruction swap(c,d); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: swap +[alias] analysing instruction: int z = 0; +[alias] May-aliases after instruction int z = 0; are <none> +[alias] May-aliases at the end of function swap: <none> diff --git a/src/plugins/alias/tests/basic/oracle/globctr.res.oracle b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..64f2826db29bf339219770a5cf558ec4f579b092 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing globctr.c (with preprocessing) +[alias] analysing function: f +[alias] analysing instruction: int y = 0; +[alias] May-aliases after instruction int y = 0; are <none> +[alias] analysing instruction: *x = y; +[alias] May-aliases after instruction *x = y; are <none> +[alias] May-aliases at the end of function f: <none> +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: f(a); +[alias] May-aliases after instruction f(a); are <none> +[alias] analysing instruction: f(b); +[alias] May-aliases after instruction f(b); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/basic/oracle/loop.res.oracle b/src/plugins/alias/tests/basic/oracle/loop.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9ef827f6daf8c1920926e31460dc19ab04c72bac --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/loop.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing loop.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int l[1] = {0}; +[alias] May-aliases after instruction int l[1] = {0}; are <none> +[alias] analysing instruction: int *n_0 = & l[1]; +[alias] May-aliases after instruction int *n_0 = & l[1]; are <none> +[alias] analysing instruction: n_0 = & l[1] + 0; +[alias] May-aliases after instruction n_0 = & l[1] + 0; are <none> +[alias] analysing instruction: int w = 0; +[alias] May-aliases after instruction int w = 0; are <none> +[alias] analysing instruction: l[0] = *(& l[1] + 0); +[alias] May-aliases after instruction l[0] = *(& l[1] + 0); are <none> +[alias] analysing instruction: int l[1] = {0}; +[alias] May-aliases after instruction int l[1] = {0}; are <none> +[alias] analysing instruction: int *n_0 = & l[1]; +[alias] May-aliases after instruction int *n_0 = & l[1]; are <none> +[alias:no-return] loop.c:4: Warning: + function main does not return; analysis may be unsound +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7b9c15f79cba40c1eb3120b93a10733bee758d1e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing steensgaard.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = & x; +[alias] May-aliases after instruction a = & x; are <none> +[alias] analysing instruction: b = & y; +[alias] May-aliases after instruction b = & y; are {*b, y} +[alias] analysing instruction: y = & z; +[alias] May-aliases after instruction y = & z; are {*b, y} +[alias] analysing instruction: y = & x; +[alias] May-aliases after instruction y = & x; are {*b, a, y} +[alias] analysing instruction: c = & y; +[alias] May-aliases after instruction c = & y; are {*b, *c, a, y} {b, c} +[alias] analysing instruction: *y = 4; +[alias] May-aliases after instruction *y = 4; are {*b, *c, a, y} {b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {*b, *c, a, y} {b, c} +[alias] May-aliases at the end of function main: {*b, *c, a, y} {b, c} diff --git a/src/plugins/alias/tests/basic/oracle/switch1.res.oracle b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0819df147033b71a430fa6c56a9b42583ed83fa6 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing switch1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: int e = 0; +[alias] May-aliases after instruction int e = 0; are <none> +[alias] analysing instruction: case 1: a = d; +[alias] May-aliases after instruction case 1: a = d; are {a, d} +[alias] analysing instruction: case 2: b = d; +[alias] May-aliases after instruction case 2: b = d; are {b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, d} +[alias] May-aliases at the end of function main: {a, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/switch2.res.oracle b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..40e0e801215e67cf06dfbc103ea1341b897bd96a --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing switch2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: int e = 0; +[alias] May-aliases after instruction int e = 0; are <none> +[alias] analysing instruction: case 1: a = d; +[alias] May-aliases after instruction case 1: a = d; are {a, d} +[alias] analysing instruction: case 2: b = d; +[alias] May-aliases after instruction case 2: b = d; are {b, d} +[alias] analysing instruction: default: c = d; +[alias] May-aliases after instruction default: c = d; are {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c, d} +[alias] May-aliases at the end of function main: {a, b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..228274eef6fbd1b252d69ecb7bf0cf0c763c528e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle @@ -0,0 +1,127 @@ +[kernel] Parsing while_for1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *s = (int *)0; +[alias] May-aliases after instruction int *s = (int *)0; are <none> +[alias] analysing instruction: int idx = 0; +[alias] May-aliases after instruction int idx = 0; are <none> +[alias] analysing instruction: s = (int *)malloc((size_t)idx); +[alias] May-aliases after instruction s = (int *)malloc((size_t)idx); are <none> +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are <none> +[alias] analysing instruction: s = (int *)malloc((size_t)idx); +[alias] May-aliases after instruction s = (int *)malloc((size_t)idx); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3986565e550a94827f115749244cece16be1b6ce --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing while_for2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..382069e577e43db211419f390f12de9f17a9da35 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing while_for3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __Cont: i ++; +[alias] May-aliases after instruction __Cont: i ++; are {a, b} +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/steensgaard.c b/src/plugins/alias/tests/basic/steensgaard.c new file mode 100644 index 0000000000000000000000000000000000000000..7afb87e247941e9aa1206c86324763ac77867c17 --- /dev/null +++ b/src/plugins/alias/tests/basic/steensgaard.c @@ -0,0 +1,19 @@ +// from steensgaard's paper +// {*b, *c, a, y} are aliased +// {b, c} are aliased + + +int main () { + int *a, **b, **c, *y, x, z, p; + a = &x; + b = &y; + if (p) + y = &z; + else + y = &x; + c = &y; + *y = 4; + return 0; +} + + diff --git a/src/plugins/alias/tests/basic/switch1.c b/src/plugins/alias/tests/basic/switch1.c new file mode 100644 index 0000000000000000000000000000000000000000..c0b97a18180983bda26f3439f939f604cc58624d --- /dev/null +++ b/src/plugins/alias/tests/basic/switch1.c @@ -0,0 +1,17 @@ +// switch +// {a, b, d} are aliased + +int main () +{ + int *a=0, *b=0, *c=0, *d=0, e=0; + switch (e) { + case 1: + a=d; + break; + case 2: + b=d; + break; + } + + return 0; +} diff --git a/src/plugins/alias/tests/basic/switch2.c b/src/plugins/alias/tests/basic/switch2.c new file mode 100644 index 0000000000000000000000000000000000000000..05d162bd67a0dd14fb8010af75281c989425e705 --- /dev/null +++ b/src/plugins/alias/tests/basic/switch2.c @@ -0,0 +1,19 @@ +// switch with default +// {a, b, c, d} are aliased + +int main () +{ + int *a=0, *b=0, *c=0, *d=0, e=0; + switch (e) { + case 1: + a=d; + break; + case 2: + b=d; + break; + default: + c=d; + } + + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for1.c b/src/plugins/alias/tests/basic/while_for1.c new file mode 100644 index 0000000000000000000000000000000000000000..06ef79f5f89d2573152cf3035a59fa55d2e8baad --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for1.c @@ -0,0 +1,13 @@ +// for loop +// no alias + +#include <stdlib.h> + +int main () +{ + int* s = 0; + for (int idx = 0; idx < 10; idx++) { + s = malloc(idx); + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for2.c b/src/plugins/alias/tests/basic/while_for2.c new file mode 100644 index 0000000000000000000000000000000000000000..f98677716b7e80a6f746b6e7033a61c4069b4c7f --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for2.c @@ -0,0 +1,17 @@ +// while loops with trivial conditions +// {a, b} are aliased + +int main () +{ + int *a=0, *b=0, *c=0; + while (1) { + a = b; + break; + } + + while (0) { + a = c; + break; + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for3.c b/src/plugins/alias/tests/basic/while_for3.c new file mode 100644 index 0000000000000000000000000000000000000000..e7ffb9f39523ca14abdc8ba00b84fd55699e195b --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for3.c @@ -0,0 +1,16 @@ +// continue +// {a, b} are aliased + +int main () +{ + int *a=0, *b=0, *c=0; + for (int i=0; i<10 ;i++) { + if (1) { + a = b; + continue; + } + a = c; + } + + return 0; +} diff --git a/src/plugins/alias/tests/fixed_bugs/empty_nodes.c b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c new file mode 100644 index 0000000000000000000000000000000000000000..004a207da7443ec4a3ee2c1c21913e53641ccd0b --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c @@ -0,0 +1,12 @@ +void f(char **x, char **y, char **z) +{ + char *t; + *y = t + (*y - *x); + *z = t + (*z - *x); + *x = t; +} + +void g(char **a) +{ + f(a,a,a); +} diff --git a/src/plugins/alias/tests/fixed_bugs/gzip124.c b/src/plugins/alias/tests/fixed_bugs/gzip124.c new file mode 100644 index 0000000000000000000000000000000000000000..70a9cc2955966f21c8ea856531bf467464e66355 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/gzip124.c @@ -0,0 +1,12 @@ +int main(void) +{ + int __retres; + short prev[1]; + short *p; + short tmp_0 = (short)0; + *(& prev[1] + 0) = tmp_0; + prev[0] = (short)0; + if (0 + 0) p = & prev[1] + (int)*p; else p = & prev[*p]; + __retres = 0; + return __retres; +} diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..970b25bd3ea518640e4cdca331963fd23ab641f8 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing empty_nodes.c (with preprocessing) +[alias] analysing function: f +[alias] analysing instruction: *y = t + (*y - *x); +[alias] May-aliases after instruction *y = t + (*y - *x); are {*y, t} +[alias] analysing instruction: *z = t + (*z - *x); +[alias] May-aliases after instruction *z = t + (*z - *x); are {*y, *z, t} {y, z} +[alias] analysing instruction: *x = t; +[alias] May-aliases after instruction *x = t; are {*x, *y, *z, t} {x, y, z} +[alias] May-aliases at the end of function f: {*x, *y, *z, t} {x, y, z} +[alias] analysing function: g +[alias] analysing instruction: f(a,a,a); +[alias] May-aliases after instruction f(a,a,a); are <none> +[alias] May-aliases at the end of function g: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fd9878fef65bf1ea35de5b51eef9ccfe7b40d5a0 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing gzip124.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: short tmp_0 = (short)0; +[alias] May-aliases after instruction short tmp_0 = (short)0; are <none> +[alias] analysing instruction: *(& prev[1] + 0) = tmp_0; +[alias] May-aliases after instruction *(& prev[1] + 0) = tmp_0; are <none> +[alias] analysing instruction: prev[0] = (short)0; +[alias] May-aliases after instruction prev[0] = (short)0; are <none> +[alias] analysing instruction: p = & prev[1] + (int)*p; +[alias] May-aliases after instruction p = & prev[1] + (int)*p; are <none> +[alias] analysing instruction: p = & prev[*p]; +[alias] May-aliases after instruction p = & prev[*p]; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bdc3f9de65441a71704fe3c6c2faf4b5d51f684b --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle @@ -0,0 +1,12 @@ +[kernel] Parsing semver.c (with preprocessing) +[alias] analysing function: f +[alias] May-aliases at the end of function f: <none> +[alias] analysing function: main +[alias] analysing instruction: f((int *)*("1" + 2)); +[alias:unsafe-cast] semver.c:6: Warning: unsafe cast from char to int * +[alias:unsupported:addr] semver.c:6: Warning: + unsupported feature: explicit pointer address: (int *)*("1" + 2); analysis may be unsound +[alias] May-aliases after instruction f((int *)*("1" + 2)); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7843cab155742b5e87b1d4e3c6fd67107fca9412 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle @@ -0,0 +1,9 @@ +[kernel] Parsing tkn-2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = (int *)(& a); +[alias:unsafe-cast] tkn-2.c:6: Warning: unsafe cast from int ** to int * +[alias] tkn-2.c:6: Warning: ignoring assignment of the form: a = (int *)(& a) +[alias] May-aliases after instruction a = (int *)(& a); are <none> +[alias] analysing instruction: __retres = *a; +[alias] May-aliases after instruction __retres = *a; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..606169550d1d780734a260fb8b0af502e57a26c5 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing union_vmap.c (with preprocessing) +[alias] analysing function: CPS_ParseKey +[alias] analysing instruction: char *s2 = CPS_SplitWord((char *)"a"); +[alias] analysing function: CPS_SplitWord +[alias] May-aliases at the end of function CPS_SplitWord: <none> +[alias:unsafe-cast] union_vmap.c:11: Warning: + unsafe cast from char const * to char * +[alias] May-aliases after instruction char *s2 = CPS_SplitWord((char *)"a"); are + <none> +[alias] analysing instruction: char *s3 = CPS_SplitWord((char *)"b"); +[alias:unsafe-cast] union_vmap.c:12: Warning: + unsafe cast from char const * to char * +[alias] May-aliases after instruction char *s3 = CPS_SplitWord((char *)"b"); are + <none> +[alias] analysing instruction: *key = s3; +[alias] May-aliases after instruction *key = s3; are {*key, s3} +[alias] analysing instruction: *key = s2; +[alias] May-aliases after instruction *key = s2; are {*key, s2} +[alias] May-aliases at the end of function CPS_ParseKey: {*key, s2, s3} +[alias] analysing function: CPS_SplitWord +[alias] May-aliases at the end of function CPS_SplitWord: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/semver.c b/src/plugins/alias/tests/fixed_bugs/semver.c new file mode 100644 index 0000000000000000000000000000000000000000..d93edc0b90eb1d95415b0dd17453a639414a8d4e --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/semver.c @@ -0,0 +1,8 @@ +void f (int* x) { +} + +int main(void) +{ + f ((int*)*("1" + 2)); + return 0; +} diff --git a/src/plugins/alias/tests/fixed_bugs/tkn-2.c b/src/plugins/alias/tests/fixed_bugs/tkn-2.c new file mode 100644 index 0000000000000000000000000000000000000000..97ee64b4f9aa53e56ec9766877bad8dae52f260e --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/tkn-2.c @@ -0,0 +1,8 @@ +// leads to a loop; taken from open-source-case-studies/cerberus + +int main() +{ + int* a; + a = (int*)(& a); + return *a; +} diff --git a/src/plugins/alias/tests/fixed_bugs/union_vmap.c b/src/plugins/alias/tests/fixed_bugs/union_vmap.c new file mode 100644 index 0000000000000000000000000000000000000000..5bf04ceddf9510e34cf3465710a71896ed841990 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/union_vmap.c @@ -0,0 +1,21 @@ +// from open-source-case-studies/chrony + +char* CPS_SplitWord(char *line) +{ + return line; +} + +void CPS_ParseKey() +{ + char **key; + char *s2 = CPS_SplitWord("a"); + char *s3 = CPS_SplitWord("b"); + if (*s3) { + *key = s3; + } + else { + *key = s2; + } +} + + diff --git a/src/plugins/alias/tests/offsets/array1.c b/src/plugins/alias/tests/offsets/array1.c new file mode 100644 index 0000000000000000000000000000000000000000..34518455ecb6fae2be23331c1a9a3a1ba0251135 --- /dev/null +++ b/src/plugins/alias/tests/offsets/array1.c @@ -0,0 +1,15 @@ +// simple array +// {x, y} are aliased + +int main () { + int tab[4]; + tab[0] = 0; + tab[1] = 1; + tab[2] = tab[1] +1; + + int* x = &tab[1]; + int* y = &tab[2]; + tab[3] = *x + *y; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/array2.c b/src/plugins/alias/tests/offsets/array2.c new file mode 100644 index 0000000000000000000000000000000000000000..0ba4d222f6a4642288f2c53cfd8fcfb1d1e7b036 --- /dev/null +++ b/src/plugins/alias/tests/offsets/array2.c @@ -0,0 +1,17 @@ +// matrices (this example may be not a valid c program) +// no alias + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int **x; + *x = mat[1]; + + int* y; + *y = *x[0]; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/array3.c b/src/plugins/alias/tests/offsets/array3.c new file mode 100644 index 0000000000000000000000000000000000000000..09bd2e67a51be84ef8a466417a95f88709ef8b3d --- /dev/null +++ b/src/plugins/alias/tests/offsets/array3.c @@ -0,0 +1,15 @@ +// matrices +// {x, y} are aliased + +#include <stdlib.h> + + +int main () { + int mat[4][4]; + int* x = malloc (4* sizeof(int)); + int* y = malloc (4* sizeof(int)); + x = mat[0]; + y = mat[1]; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse1.c b/src/plugins/alias/tests/offsets/collapse1.c new file mode 100644 index 0000000000000000000000000000000000000000..624f42c3af68819390dbbaf141ef0452f9ba3c75 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse1.c @@ -0,0 +1,14 @@ + + +int main () { + int tab[4]; + tab[0] = 0; + tab[1] = 1; + tab[2] = tab[1] +1; + int x =0; + + for (int i=0;i<2;i++) + x = tab[i]; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse2.c b/src/plugins/alias/tests/offsets/collapse2.c new file mode 100644 index 0000000000000000000000000000000000000000..9c00bd24e3b5297f9d18a9fe99922e4a5d543802 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse2.c @@ -0,0 +1,15 @@ +// matrices + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int i=2; + mat[1][i]=i; + + i=i+1; + mat[1][i]=2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse3.c b/src/plugins/alias/tests/offsets/collapse3.c new file mode 100644 index 0000000000000000000000000000000000000000..8540638c809a74ad632b46ec6ce12342b30906e6 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse3.c @@ -0,0 +1,15 @@ +// matrices + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int i=2; + mat[i][1]=i; + + i=i+1; + mat[i][1]=2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/nested1.c b/src/plugins/alias/tests/offsets/nested1.c new file mode 100644 index 0000000000000000000000000000000000000000..06c14b9512b4ee4d15c4451f2d22382c2703f49c --- /dev/null +++ b/src/plugins/alias/tests/offsets/nested1.c @@ -0,0 +1,56 @@ +// nested structures and arrays +// {z1->s, z2->s, tab_y[0]} are aliased +// {t->t, z1} are aliased +// {z1->c, t->d, a} are aliased +// {z2->c, b} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *tab_y [2]; + + tab_y[0] = &x1; + tab_y[1] = &x2; + st_2_t *z1 = malloc(sizeof(st_2_t)); + st_2_t *z2 = malloc(sizeof(st_2_t)); + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + int* b = malloc(sizeof(int)); + + *a = 0; + *b = 5; + z1->s = tab_y[0]; + z2->s = tab_y[1]; + z1->c = a; + z2->c = b; + t->t = z1; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/nested2.c b/src/plugins/alias/tests/offsets/nested2.c new file mode 100644 index 0000000000000000000000000000000000000000..193bdd1adba16542da95e964e384c3651c373379 --- /dev/null +++ b/src/plugins/alias/tests/offsets/nested2.c @@ -0,0 +1,50 @@ +// nested structures and arrays +// {t->t, z1} are aliased +// {z1->c, t->d, a} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s [2]; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {2,3}; + + st_2_t *z1 = malloc(sizeof(st_2_t)); + + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + + *a = 0; + z1->s[0] = &x1; + z1->s[1] = &x2; + z1->c = a; + t->t = z1; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/oracle/array1.res.oracle b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d6bdf7ba016ca2bf534ccbde0c2f7b0fe9f36f76 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing array1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: tab[0] = 0; +[alias] May-aliases after instruction tab[0] = 0; are <none> +[alias] analysing instruction: tab[1] = 1; +[alias] May-aliases after instruction tab[1] = 1; are <none> +[alias] analysing instruction: tab[2] = tab[1] + 1; +[alias] May-aliases after instruction tab[2] = tab[1] + 1; are <none> +[alias] analysing instruction: int *x = & tab[1]; +[alias] May-aliases after instruction int *x = & tab[1]; are <none> +[alias] analysing instruction: int *y = & tab[2]; +[alias] May-aliases after instruction int *y = & tab[2]; are {x, y} +[alias] analysing instruction: tab[3] = *x + *y; +[alias] May-aliases after instruction tab[3] = *x + *y; are {x, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {x, y} +[alias] May-aliases at the end of function main: {x, y} diff --git a/src/plugins/alias/tests/offsets/oracle/array2.res.oracle b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..69f16a022f8b05688a9a9eb66a4180354fdcf323 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing array2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: *x = mat[1]; +[alias] May-aliases after instruction *x = mat[1]; are <none> +[alias] analysing instruction: *y = *(*(x + 0)); +[alias] May-aliases after instruction *y = *(*(x + 0)); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/array3.res.oracle b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6b6a66a4677d71e520481483aaa137fa7dd8529c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle @@ -0,0 +1,127 @@ +[kernel] Parsing array3.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *x = malloc((unsigned long)4 * sizeof(int)); +[alias] May-aliases after instruction + int *x = malloc((unsigned long)4 * sizeof(int)); are <none> +[alias] analysing instruction: int *y = malloc((unsigned long)4 * sizeof(int)); +[alias] May-aliases after instruction + int *y = malloc((unsigned long)4 * sizeof(int)); are <none> +[alias] analysing instruction: x = mat[0]; +[alias] May-aliases after instruction x = mat[0]; are <none> +[alias] analysing instruction: y = mat[1]; +[alias] May-aliases after instruction y = mat[1]; are {x, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {x, y} +[alias] May-aliases at the end of function main: {x, y} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9b588f2f8f2484f894680dae6ca6129528811125 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing collapse1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: tab[0] = 0; +[alias] May-aliases after instruction tab[0] = 0; are <none> +[alias] analysing instruction: tab[1] = 1; +[alias] May-aliases after instruction tab[1] = 1; are <none> +[alias] analysing instruction: tab[2] = tab[1] + 1; +[alias] May-aliases after instruction tab[2] = tab[1] + 1; are <none> +[alias] analysing instruction: int x = 0; +[alias] May-aliases after instruction int x = 0; are <none> +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are <none> +[alias] analysing instruction: x = tab[i]; +[alias] May-aliases after instruction x = tab[i]; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..34b8bd11975081e1acc6cd63c7d0011d1f3b57e3 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing collapse2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: int i = 2; +[alias] May-aliases after instruction int i = 2; are <none> +[alias] analysing instruction: mat[1][i] = i; +[alias] May-aliases after instruction mat[1][i] = i; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: mat[1][i] = 2; +[alias] May-aliases after instruction mat[1][i] = 2; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4193c3f90a212238b3a6f1452d58e097c1ae1bd1 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing collapse3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: int i = 2; +[alias] May-aliases after instruction int i = 2; are <none> +[alias] analysing instruction: mat[i][1] = i; +[alias] May-aliases after instruction mat[i][1] = i; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: mat[i][1] = 2; +[alias] May-aliases after instruction mat[i][1] = 2; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e26a96622ddd53633ec3d0978ac43635f1dc1e4f --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle @@ -0,0 +1,168 @@ +[kernel] Parsing nested1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: tab_y[0] = & x1; +[alias] May-aliases after instruction tab_y[0] = & x1; are <none> +[alias] analysing instruction: tab_y[1] = & x2; +[alias] May-aliases after instruction tab_y[1] = & x2; are <none> +[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z1 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_2_t *z2 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z2 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: int *b = malloc(sizeof(int)); +[alias] May-aliases after instruction int *b = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: *b = 5; +[alias] May-aliases after instruction *b = 5; are <none> +[alias] analysing instruction: z1->s = (struct struct_1_t *)tab_y[0]; +[alias:unsafe-cast] nested1.c:47: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s = (struct struct_1_t *)tab_y[0]; are + {z1->s, tab_y[0]} +[alias] analysing instruction: z2->s = (struct struct_1_t *)tab_y[1]; +[alias:unsafe-cast] nested1.c:48: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z2->s = (struct struct_1_t *)tab_y[1]; are + {z1->s, z2->s, tab_y[0]} +[alias] analysing instruction: z1->c = a; +[alias] May-aliases after instruction z1->c = a; are + {z1->s, z2->s, tab_y[0]} {z1->c, a} +[alias] analysing instruction: z2->c = b; +[alias] May-aliases after instruction z2->c = b; are + {z1->s, z2->s, tab_y[0]} {z1->c, a} {z2->c, b} +[alias] analysing instruction: t->t = (struct struct_2_t *)z1; +[alias:unsafe-cast] nested1.c:51: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z1; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, a} {z2->c, b} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] May-aliases at the end of function main: + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7167c4aebae1c65a02d1333dd738a7c9cccc658c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle @@ -0,0 +1,151 @@ +[kernel] Parsing nested2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 2, .b = 3}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 2, .b = 3}; are <none> +[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z1 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: z1->s[0] = (struct struct_1_t *)(& x1); +[alias:unsafe-cast] nested2.c:42: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s[0] = (struct struct_1_t *)(& x1); are + <none> +[alias] analysing instruction: z1->s[1] = (struct struct_1_t *)(& x2); +[alias:unsafe-cast] nested2.c:43: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s[1] = (struct struct_1_t *)(& x2); are + <none> +[alias] analysing instruction: z1->c = a; +[alias] May-aliases after instruction z1->c = a; are {z1->c, a} +[alias] analysing instruction: t->t = (struct struct_2_t *)z1; +[alias:unsafe-cast] nested2.c:45: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z1; are + {t->t, z1} {z1->c, a} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are {t->t, z1} {z1->c, t->d, a} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {t->t, z1} {z1->c, t->d, a} +[alias] May-aliases at the end of function main: {t->t, z1} {z1->c, t->d, a} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6fab8c1f99d32876d28e448212a5a4a026a7809c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing structure1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_2_t y = {.a = 3, .c = 4}; +[alias] May-aliases after instruction st_2_t y = {.a = 3, .c = 4}; are <none> +[alias] analysing instruction: st_1_t *p_x = & x; +[alias] May-aliases after instruction st_1_t *p_x = & x; are <none> +[alias] analysing instruction: st_2_t *p_y = & y; +[alias] May-aliases after instruction st_2_t *p_y = & y; are <none> +[alias] analysing instruction: p_x->a = 3; +[alias] May-aliases after instruction p_x->a = 3; are <none> +[alias] analysing instruction: p_x = (st_1_t *)p_y; +[alias:unsafe-cast] structure1.c:28: Warning: + unsafe cast from st_2_t * to st_1_t * +[alias] May-aliases after instruction p_x = (st_1_t *)p_y; are {p_x, p_y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {p_x, p_y} +[alias] May-aliases at the end of function main: {p_x, p_y} diff --git a/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2b2f7ecd4e531f1ec02f3d115396b6b6f0de27d0 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing structure2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4}; +[alias:unsafe-cast] structure2.c:21: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4}; are <none> +[alias] analysing instruction: y.s = (struct struct_1_t *)(& x2); +[alias:unsafe-cast] structure2.c:23: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction y.s = (struct struct_1_t *)(& x2); are + <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7ec86d402cb6980ff01296b3901039b234b94464 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle @@ -0,0 +1,33 @@ +[kernel] Parsing structure3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: + st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3}; +[alias:unsafe-cast] structure3.c:31: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3}; are <none> +[alias] analysing instruction: + st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4}; +[alias:unsafe-cast] structure3.c:32: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4}; are <none> +[alias] analysing instruction: st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5}; +[alias:unsafe-cast] structure3.c:33: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction + st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5}; are <none> +[alias] analysing instruction: z.t = (struct struct_2_t *)(& y2); +[alias:unsafe-cast] structure3.c:35: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction z.t = (struct struct_2_t *)(& y2); are + <none> +[alias] analysing instruction: y1.c = z.d; +[alias] May-aliases after instruction y1.c = z.d; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..17d462a32e0c6ec88e3c3c03b6c82ae0b907a465 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle @@ -0,0 +1,136 @@ +[kernel] Parsing structure4.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t)); +[alias] May-aliases after instruction st_1_t *y1 = malloc(sizeof(st_1_t)); are + <none> +[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: y1 = & x1; +[alias] May-aliases after instruction y1 = & x1; are <none> +[alias] analysing instruction: z->s = (struct struct_1_t *)y1; +[alias:unsafe-cast] structure4.c:37: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z->s = (struct struct_1_t *)y1; are + {z->s, y1} +[alias] analysing instruction: z->c = 6; +[alias] May-aliases after instruction z->c = 6; are {z->s, y1} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {z->s, y1} +[alias] May-aliases at the end of function main: {z->s, y1} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6ab3b8478904bba3396ee4bf1314b90cb372fb45 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle @@ -0,0 +1,153 @@ +[kernel] Parsing structure5.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t)); +[alias] May-aliases after instruction st_1_t *y1 = malloc(sizeof(st_1_t)); are + <none> +[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: y1 = & x1; +[alias] May-aliases after instruction y1 = & x1; are <none> +[alias] analysing instruction: z->s = (struct struct_1_t *)y1; +[alias:unsafe-cast] structure5.c:41: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z->s = (struct struct_1_t *)y1; are + {z->s, y1} +[alias] analysing instruction: z->c = a; +[alias] May-aliases after instruction z->c = a; are {z->s, y1} {z->c, a} +[alias] analysing instruction: t->t = (struct struct_2_t *)z; +[alias:unsafe-cast] structure5.c:43: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z; are + {z->s, y1} {t->t, z} {z->c, a} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] May-aliases at the end of function main: + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/structure1.c b/src/plugins/alias/tests/offsets/structure1.c new file mode 100644 index 0000000000000000000000000000000000000000..95cf272878359073767764d7340b0546eb21f65c --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure1.c @@ -0,0 +1,30 @@ +// simple structure +// {p_x, p_y} are aliased + + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + int a; + int c; +} st_2_t; + + +int main () { + + st_1_t x = {0,1}; + st_2_t y = {3,4}; + + st_1_t * p_x = &x; + st_2_t * p_y = &y; + + + p_x->a = 3; + p_x = p_y; + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure2.c b/src/plugins/alias/tests/offsets/structure2.c new file mode 100644 index 0000000000000000000000000000000000000000..92ff3a41783f5e35b94622b1ebe1553946938e7a --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure2.c @@ -0,0 +1,26 @@ +// structure with initialisation and pointer +// no alias + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_2_t y = {&x1,4}; + + y.s = &x2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure3.c b/src/plugins/alias/tests/offsets/structure3.c new file mode 100644 index 0000000000000000000000000000000000000000..9582ccd3f86dfe6b9b186213836c29aee37a600f --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure3.c @@ -0,0 +1,39 @@ +// double structure with initialisation and pointer +// no alias + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_2_t y1 = {&x1,3}; + st_2_t y2 = {&x2,4}; + st_3_t z = {&y1,5}; + + z.t = &y2; + y1.c = z.d; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure4.c b/src/plugins/alias/tests/offsets/structure4.c new file mode 100644 index 0000000000000000000000000000000000000000..c33bce757fec2a73fa1a55d075081c9955fa14a7 --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure4.c @@ -0,0 +1,41 @@ +// structure with malloc +// {z->s, y1} are aliased + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *y1 = malloc(sizeof(st_1_t)); + st_2_t *z = malloc(sizeof(st_2_t)); + + y1 = &x1; + z->s = y1; + z->c = 6; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure5.c b/src/plugins/alias/tests/offsets/structure5.c new file mode 100644 index 0000000000000000000000000000000000000000..eeeefafd63d3518a65fbc88f0f96bb456104f94d --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure5.c @@ -0,0 +1,48 @@ +// another structure, more complex +// {z->s, y1} are aliased +// {t->t, z} are aliased +// {z->c, t->d, a} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *y1 = malloc(sizeof(st_1_t)); + st_2_t *z = malloc(sizeof(st_2_t)); + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + + *a = 0; + y1 = &x1; + z->s = y1; + z->c = a; + t->t = z; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/ptests_config b/src/plugins/alias/tests/ptests_config new file mode 100644 index 0000000000000000000000000000000000000000..364f24e63e59237f7800393fbdf9829fc9330471 --- /dev/null +++ b/src/plugins/alias/tests/ptests_config @@ -0,0 +1 @@ +DEFAULT_SUITES=basic real_world offsets fixed_bugs diff --git a/src/plugins/alias/tests/real_world/example1.c b/src/plugins/alias/tests/real_world/example1.c new file mode 100644 index 0000000000000000000000000000000000000000..a3709a6736725db096563ff80de05329276ef3aa --- /dev/null +++ b/src/plugins/alias/tests/real_world/example1.c @@ -0,0 +1,108 @@ +// real world example +// {a->t1[0], b->t1[0]} are aliased +// {a->t2[0], b->t2[0]} are aliased +// {a->n1, b->n1} are aliased +// {a->n2, b->n2} are aliased + + +#include <stdlib.h> +#include <math.h> + +typedef struct { + double *t1[2]; + double *t2[2]; + int *n1; + int *n2; +} ty; + +void swap(int *n) +{ + if ((*n) == 1) { + (*n) = 0; + } + else { + (*n)++; + } +} + + +void *f1(ty *x) +{ + ty *tmp = x; + double *idata; + double *odata; + int idx; + + idata = (double *)malloc(10 * sizeof(double)); + + while (1) { + + idata = tmp->t2[*tmp->n2]; + + odata = tmp->t1[*tmp->n1]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 0.5*sin(idata[idx]); + } + swap(tmp->n1); + } + return (void *) NULL; +} + + +void *f2(ty *x) +{ + ty *tmp = x; + int idx; + double *idata; + double *odata; + + idata = (double*)malloc(10* sizeof(double)); + + while (1) { + + idata = tmp->t1[*tmp->n1]; + + odata = tmp->t2[*tmp->n2]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 3*idata[idx] + 1; + } + swap(tmp->n2); + } + + return (void *) NULL; +} + + +int main(void) +{ + ty *a; + ty *b; + + a = (ty *)malloc(sizeof(ty)); + b = (ty *)malloc(sizeof(ty)); + + int i; + for (i = 0; i < 2; i++) { + a->t1[i] = (double *)malloc(10 * sizeof(double)); + a->t2[i] = (double *)malloc(10 * sizeof(double)); + } + + a->n1 = (int *)malloc(sizeof(int)); + a->n2 = (int *)malloc(sizeof(int)); + *a->n1 = 1; + *a->n2 = 1; + + for (i = 0; i < 2; i++) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + } + b->n1 = a->n1; + b->n2 = a->n2; + + f1(a); + f2(b); + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/example2.c b/src/plugins/alias/tests/real_world/example2.c new file mode 100644 index 0000000000000000000000000000000000000000..18e08504e7c44a69853a32bf94ed52404942a5ec --- /dev/null +++ b/src/plugins/alias/tests/real_world/example2.c @@ -0,0 +1,108 @@ +// real world example +// {a->t1[0], b->t1[0]} are aliased +// {a->t2[0], b->t2[0]} are aliased +// {a->n1, b->n1} are aliased +// {a->n2, b->n2} are aliased + + +#include <stdlib.h> +#include <math.h> + +typedef struct { + double *t1[2]; + double *t2[2]; + int *n1; + int *n2; +} ty; + +void swap(int *n) +{ + if ((*n) == 1) { + (*n) = 0; + } + else { + (*n)++; + } +} + + +void *f1(ty *x) +{ + ty *tmp = x; + double *idata; + double *odata; + int idx; + + idata = (double *)malloc(10 * sizeof(double)); + + for (int i = 0; i < 2; i++) { + + idata = tmp->t2[*tmp->n2]; + + odata = tmp->t1[*tmp->n1]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 0.5*sin(idata[idx]); + } + swap(tmp->n1); + } + return (void *) NULL; +} + + +void *f2(ty *x) +{ + ty *tmp = x; + int idx; + double *idata; + double *odata; + + idata = (double*)malloc(10* sizeof(double)); + + for (int i = 0; i < 2; i++) { + + idata = tmp->t1[*tmp->n1]; + + odata = tmp->t2[*tmp->n2]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 3*idata[idx] + 1; + } + swap(tmp->n2); + } + + return (void *) NULL; +} + + +int main(void) +{ + ty *a; + ty *b; + + a = (ty *)malloc(sizeof(ty)); + b = (ty *)malloc(sizeof(ty)); + + int i; + for (i = 0; i < 2; i++) { + a->t1[i] = (double *)malloc(10 * sizeof(double)); + a->t2[i] = (double *)malloc(10 * sizeof(double)); + } + + a->n1 = (int *)malloc(sizeof(int)); + a->n2 = (int *)malloc(sizeof(int)); + *a->n1 = 1; + *a->n2 = 1; + + for (i = 0; i < 2; i++) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + } + b->n1 = a->n1; + b->n2 = a->n2; + + f1(a); + f2(b); + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/function1_v2.c b/src/plugins/alias/tests/real_world/function1_v2.c new file mode 100644 index 0000000000000000000000000000000000000000..3187998b7574e374a2a14dfa89ff10f8f6342763 --- /dev/null +++ b/src/plugins/alias/tests/real_world/function1_v2.c @@ -0,0 +1,26 @@ +// function with no return +// {a, b} are aliased +// {c, d} are aliased +//#include <stdio.h> +#include <stdlib.h> + +void alias(int **x, int **y) { + *x = *y; +} + + +int main(void) +{ + int *a = malloc(sizeof(int)); + *a = 0; + int *b = malloc(sizeof(int));; + *b = 42; + + alias(&a,&b); + + *a = 7; + //printf("a = %d && b = %d\n",*a,*b); + + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.old b/src/plugins/alias/tests/real_world/oracle/example1.res.old new file mode 100644 index 0000000000000000000000000000000000000000..97708d154b7fc3fc196c5926743747fe2f6276d9 --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example1.res.old @@ -0,0 +1,403 @@ +[kernel] Parsing example1.c (with preprocessing) +[alias] Parsing done +[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] In a function call, parameter (x <- *(idata + idx)) is ignored) +[alias] Warning: a function with no return is employed in an assignment +[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2) +[alias] In a function call, parameter (x <- *(idata + idx)) is ignored) +[alias] Warning: a function with no return is employed in an assignment +[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2) +[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Warning: DEBUG return stmt of f1 not in table +[alias] Warning: Analysis is continuing but will not be sound +[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2) +[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2) +[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Warning: DEBUG return stmt of f2 not in table +[alias] Warning: Analysis is continuing but will not be sound +[alias] Skipping assignment a->t1[i] = malloc() (not implemented) +[alias] Skipping assignment a->t2[i] = malloc() (not implemented) +[alias] Skipping assignment a->t1[i] = malloc() (not implemented) +[alias] Skipping assignment a->t2[i] = malloc() (not implemented) +[alias] Skipping assignment a->n1 = malloc() (not implemented) +[alias] Skipping assignment a->n2 = malloc() (not implemented) +[alias] May-aliases at the end of function main: + <list of may-alias> + {b.n1; b; } are aliased + {b.n1; b.n2; b; } are aliased + {*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased + <end of list> +[alias] Functions done +Before statement b->t1[i] = a->t1[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idx = 0; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b->t2[i] = a->t2[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement if (*n == 1) *n = 0; else (*n) ++; : + <list of may-alias> +<end of list> + +Before statement i ++; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement if (*n == 1) *n = 0; else (*n) ++; : + <list of may-alias> +<end of list> + +Before statement b->n1 = a->n1; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement if (! (idx < 10)) break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement *n = 0; : + <list of may-alias> +<end of list> + +Before statement b->n2 = a->n2; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b; } are aliased +{b.n1; b; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement (*n) ++; : + <list of may-alias> +<end of list> + +Before statement f1(a); : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +<end of list> + +Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement f2(b); : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement __retres = 0; : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement idx ++; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement ty *tmp = x; : + <list of may-alias> +<end of list> + +Before statement swap(tmp->n2); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement return; : + <list of may-alias> +<end of list> + +Before statement while (1) { + idata = tmp->t2[*(tmp->n2)]; + odata = tmp->t1[*(tmp->n1)]; + idx = 0; + while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } + swap(tmp->n1); + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement idata = tmp->t2[*(tmp->n2)]; + odata = tmp->t1[*(tmp->n1)]; + idx = 0; + while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } + swap(tmp->n1); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a = (ty *)malloc(sizeof(ty)); : + <list of may-alias> +<end of list> + +Before statement idata = tmp->t2[*(tmp->n2)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b = (ty *)malloc(sizeof(ty)); : + <list of may-alias> +<end of list> + +Before statement odata = tmp->t1[*(tmp->n1)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement i = 0; : + <list of may-alias> +<end of list> + +Before statement idx = 0; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement while (i < 2) { + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + i ++; + } : + <list of may-alias> +<end of list> + +Before statement while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement return __retres; : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement if (! (i < 2)) break; : + <list of may-alias> +<end of list> + +Before statement if (! (idx < 10)) break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +<end of list> + +Before statement break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement tmp_1 = sin(*(idata + idx)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement i ++; : + <list of may-alias> +<end of list> + +Before statement *(odata + idx) = 0.5 * tmp_1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->n1 = (int *)malloc(sizeof(int)); : + <list of may-alias> +<end of list> + +Before statement idx ++; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->n2 = (int *)malloc(sizeof(int)); : + <list of may-alias> +<end of list> + +Before statement swap(tmp->n1); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement *(a->n1) = 1; : + <list of may-alias> +<end of list> + +Before statement *(a->n2) = 1; : + <list of may-alias> +<end of list> + +Before statement i = 0; : + <list of may-alias> +<end of list> + +Before statement ty *tmp = x; : + <list of may-alias> +<end of list> + +Before statement while (i < 2) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + i ++; + } : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement while (1) { + idata = tmp->t1[*(tmp->n1)]; + odata = tmp->t2[*(tmp->n2)]; + idx = 0; + while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } + swap(tmp->n2); + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement if (! (i < 2)) break; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = tmp->t1[*(tmp->n1)]; + odata = tmp->t2[*(tmp->n2)]; + idx = 0; + while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } + swap(tmp->n2); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = tmp->t1[*(tmp->n1)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement odata = tmp->t2[*(tmp->n2)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +[alias] Analysis complete diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.oracle b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2184e66ef66ccd9e68cdee8db84944dbaa773d5f --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle @@ -0,0 +1,412 @@ +[kernel] Parsing example1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: __fc_fpclassify +[alias] May-aliases at the end of function __fc_fpclassify: ⊥ +[alias] analysing function: __fc_fpclassifyf +[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥ +[alias] analysing function: __fc_infinity +[alias] May-aliases at the end of function __fc_infinity: ⊥ +[alias] analysing function: __fc_nan +[alias] May-aliases at the end of function __fc_nan: ⊥ +[alias] analysing function: __finite +[alias] May-aliases at the end of function __finite: ⊥ +[alias] analysing function: __finitef +[alias] May-aliases at the end of function __finitef: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: acos +[alias] May-aliases at the end of function acos: ⊥ +[alias] analysing function: acosf +[alias] May-aliases at the end of function acosf: ⊥ +[alias] analysing function: acosh +[alias] May-aliases at the end of function acosh: ⊥ +[alias] analysing function: acoshf +[alias] May-aliases at the end of function acoshf: ⊥ +[alias] analysing function: acoshl +[alias] May-aliases at the end of function acoshl: ⊥ +[alias] analysing function: acosl +[alias] May-aliases at the end of function acosl: ⊥ +[alias] analysing function: asin +[alias] May-aliases at the end of function asin: ⊥ +[alias] analysing function: asinf +[alias] May-aliases at the end of function asinf: ⊥ +[alias] analysing function: asinl +[alias] May-aliases at the end of function asinl: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atan +[alias] May-aliases at the end of function atan: ⊥ +[alias] analysing function: atan2 +[alias] May-aliases at the end of function atan2: ⊥ +[alias] analysing function: atan2f +[alias] May-aliases at the end of function atan2f: ⊥ +[alias] analysing function: atan2l +[alias] May-aliases at the end of function atan2l: ⊥ +[alias] analysing function: atanf +[alias] May-aliases at the end of function atanf: ⊥ +[alias] analysing function: atanl +[alias] May-aliases at the end of function atanl: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: ceil +[alias] May-aliases at the end of function ceil: ⊥ +[alias] analysing function: ceilf +[alias] May-aliases at the end of function ceilf: ⊥ +[alias] analysing function: ceill +[alias] May-aliases at the end of function ceill: ⊥ +[alias] analysing function: cos +[alias] May-aliases at the end of function cos: ⊥ +[alias] analysing function: cosf +[alias] May-aliases at the end of function cosf: ⊥ +[alias] analysing function: cosl +[alias] May-aliases at the end of function cosl: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: exp +[alias] May-aliases at the end of function exp: ⊥ +[alias] analysing function: expf +[alias] May-aliases at the end of function expf: ⊥ +[alias] analysing function: f1 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: tmp_1 = sin(*(idata + idx)); +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias:undefined:fn] example1.c:45: Warning: function sin has no definition +[alias] May-aliases after instruction tmp_1 = sin(*(idata + idx)); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1; +[alias] May-aliases after instruction *(odata + idx) = 0.5 * tmp_1; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: swap(tmp->n1); +[alias] analysing function: swap +[alias] analysing instruction: *n = 0; +[alias] May-aliases after instruction *n = 0; are <none> +[alias] analysing instruction: (*n) ++; +[alias] May-aliases after instruction (*n) ++; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(tmp->n1); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias:no-return] example1.c:29: Warning: + function f1 does not return; analysis may be unsound +[alias] May-aliases at the end of function f1: <none> +[alias] analysing function: f2 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; +[alias] May-aliases after instruction + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: swap(tmp->n2); +[alias] May-aliases after instruction swap(tmp->n2); are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias:no-return] example1.c:53: Warning: + function f2 does not return; analysis may be unsound +[alias] May-aliases at the end of function f2: <none> +[alias] analysing function: fabs +[alias] May-aliases at the end of function fabs: ⊥ +[alias] analysing function: fabsf +[alias] May-aliases at the end of function fabsf: ⊥ +[alias] analysing function: fabsl +[alias] May-aliases at the end of function fabsl: ⊥ +[alias] analysing function: floor +[alias] May-aliases at the end of function floor: ⊥ +[alias] analysing function: floorf +[alias] May-aliases at the end of function floorf: ⊥ +[alias] analysing function: floorl +[alias] May-aliases at the end of function floorl: ⊥ +[alias] analysing function: fmod +[alias] May-aliases at the end of function fmod: ⊥ +[alias] analysing function: fmodf +[alias] May-aliases at the end of function fmodf: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: frexp +[alias] May-aliases at the end of function frexp: ⊥ +[alias] analysing function: frexpf +[alias] May-aliases at the end of function frexpf: ⊥ +[alias] analysing function: frexpl +[alias] May-aliases at the end of function frexpl: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldexp +[alias] May-aliases at the end of function ldexp: ⊥ +[alias] analysing function: ldexpf +[alias] May-aliases at the end of function ldexpf: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: log +[alias] May-aliases at the end of function log: ⊥ +[alias] analysing function: log10 +[alias] May-aliases at the end of function log10: ⊥ +[alias] analysing function: log10f +[alias] May-aliases at the end of function log10f: ⊥ +[alias] analysing function: log10l +[alias] May-aliases at the end of function log10l: ⊥ +[alias] analysing function: log2 +[alias] May-aliases at the end of function log2: ⊥ +[alias] analysing function: log2f +[alias] May-aliases at the end of function log2f: ⊥ +[alias] analysing function: log2l +[alias] May-aliases at the end of function log2l: ⊥ +[alias] analysing function: logf +[alias] May-aliases at the end of function logf: ⊥ +[alias] analysing function: logl +[alias] May-aliases at the end of function logl: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: a = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction a = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: b = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction b = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n1 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n2 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: *(a->n1) = 1; +[alias] May-aliases after instruction *(a->n1) = 1; are <none> +[alias] analysing instruction: *(a->n2) = 1; +[alias] May-aliases after instruction *(a->n2) = 1; are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->n1 = a->n1; +[alias] May-aliases after instruction b->n1 = a->n1; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} +[alias] analysing instruction: b->n2 = a->n2; +[alias] May-aliases after instruction b->n2 = a->n2; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f1(a); +[alias] May-aliases after instruction f1(a); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f2(b); +[alias] May-aliases after instruction f2(b); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] May-aliases at the end of function main: + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nan +[alias] May-aliases at the end of function nan: ⊥ +[alias] analysing function: nanf +[alias] May-aliases at the end of function nanf: ⊥ +[alias] analysing function: nanl +[alias] May-aliases at the end of function nanl: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: pow +[alias] May-aliases at the end of function pow: ⊥ +[alias] analysing function: powf +[alias] May-aliases at the end of function powf: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: round +[alias] May-aliases at the end of function round: ⊥ +[alias] analysing function: roundf +[alias] May-aliases at the end of function roundf: ⊥ +[alias] analysing function: roundl +[alias] May-aliases at the end of function roundl: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias] analysing function: sinf +[alias] May-aliases at the end of function sinf: ⊥ +[alias] analysing function: sinl +[alias] May-aliases at the end of function sinl: ⊥ +[alias] analysing function: sqrt +[alias] May-aliases at the end of function sqrt: ⊥ +[alias] analysing function: sqrtf +[alias] May-aliases at the end of function sqrtf: ⊥ +[alias] analysing function: sqrtl +[alias] May-aliases at the end of function sqrtl: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: swap +[alias] May-aliases at the end of function swap: <none> +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: tan +[alias] May-aliases at the end of function tan: ⊥ +[alias] analysing function: tanf +[alias] May-aliases at the end of function tanf: ⊥ +[alias] analysing function: tanl +[alias] May-aliases at the end of function tanl: ⊥ +[alias] analysing function: trunc +[alias] May-aliases at the end of function trunc: ⊥ +[alias] analysing function: truncf +[alias] May-aliases at the end of function truncf: ⊥ +[alias] analysing function: truncl +[alias] May-aliases at the end of function truncl: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/real_world/oracle/example2.res.oracle b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..21f8829b4dc8c670f933cedca6281dd899cd434f --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle @@ -0,0 +1,426 @@ +[kernel] Parsing example2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: __fc_fpclassify +[alias] May-aliases at the end of function __fc_fpclassify: ⊥ +[alias] analysing function: __fc_fpclassifyf +[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥ +[alias] analysing function: __fc_infinity +[alias] May-aliases at the end of function __fc_infinity: ⊥ +[alias] analysing function: __fc_nan +[alias] May-aliases at the end of function __fc_nan: ⊥ +[alias] analysing function: __finite +[alias] May-aliases at the end of function __finite: ⊥ +[alias] analysing function: __finitef +[alias] May-aliases at the end of function __finitef: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: acos +[alias] May-aliases at the end of function acos: ⊥ +[alias] analysing function: acosf +[alias] May-aliases at the end of function acosf: ⊥ +[alias] analysing function: acosh +[alias] May-aliases at the end of function acosh: ⊥ +[alias] analysing function: acoshf +[alias] May-aliases at the end of function acoshf: ⊥ +[alias] analysing function: acoshl +[alias] May-aliases at the end of function acoshl: ⊥ +[alias] analysing function: acosl +[alias] May-aliases at the end of function acosl: ⊥ +[alias] analysing function: asin +[alias] May-aliases at the end of function asin: ⊥ +[alias] analysing function: asinf +[alias] May-aliases at the end of function asinf: ⊥ +[alias] analysing function: asinl +[alias] May-aliases at the end of function asinl: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atan +[alias] May-aliases at the end of function atan: ⊥ +[alias] analysing function: atan2 +[alias] May-aliases at the end of function atan2: ⊥ +[alias] analysing function: atan2f +[alias] May-aliases at the end of function atan2f: ⊥ +[alias] analysing function: atan2l +[alias] May-aliases at the end of function atan2l: ⊥ +[alias] analysing function: atanf +[alias] May-aliases at the end of function atanf: ⊥ +[alias] analysing function: atanl +[alias] May-aliases at the end of function atanl: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: ceil +[alias] May-aliases at the end of function ceil: ⊥ +[alias] analysing function: ceilf +[alias] May-aliases at the end of function ceilf: ⊥ +[alias] analysing function: ceill +[alias] May-aliases at the end of function ceill: ⊥ +[alias] analysing function: cos +[alias] May-aliases at the end of function cos: ⊥ +[alias] analysing function: cosf +[alias] May-aliases at the end of function cosf: ⊥ +[alias] analysing function: cosl +[alias] May-aliases at the end of function cosl: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: exp +[alias] May-aliases at the end of function exp: ⊥ +[alias] analysing function: expf +[alias] May-aliases at the end of function expf: ⊥ +[alias] analysing function: f1 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are {x, tmp} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: tmp_1 = sin(*(idata + idx)); +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias:undefined:fn] example2.c:45: Warning: function sin has no definition +[alias] May-aliases after instruction tmp_1 = sin(*(idata + idx)); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1; +[alias] May-aliases after instruction *(odata + idx) = 0.5 * tmp_1; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: swap(tmp->n1); +[alias] analysing function: swap +[alias] analysing instruction: *n = 0; +[alias] May-aliases after instruction *n = 0; are <none> +[alias] analysing instruction: (*n) ++; +[alias] May-aliases after instruction (*n) ++; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(tmp->n1); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] May-aliases at the end of function f1: + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing function: f2 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are {x, tmp} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; +[alias] May-aliases after instruction + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: swap(tmp->n2); +[alias] May-aliases after instruction swap(tmp->n2); are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] May-aliases at the end of function f2: + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing function: fabs +[alias] May-aliases at the end of function fabs: ⊥ +[alias] analysing function: fabsf +[alias] May-aliases at the end of function fabsf: ⊥ +[alias] analysing function: fabsl +[alias] May-aliases at the end of function fabsl: ⊥ +[alias] analysing function: floor +[alias] May-aliases at the end of function floor: ⊥ +[alias] analysing function: floorf +[alias] May-aliases at the end of function floorf: ⊥ +[alias] analysing function: floorl +[alias] May-aliases at the end of function floorl: ⊥ +[alias] analysing function: fmod +[alias] May-aliases at the end of function fmod: ⊥ +[alias] analysing function: fmodf +[alias] May-aliases at the end of function fmodf: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: frexp +[alias] May-aliases at the end of function frexp: ⊥ +[alias] analysing function: frexpf +[alias] May-aliases at the end of function frexpf: ⊥ +[alias] analysing function: frexpl +[alias] May-aliases at the end of function frexpl: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldexp +[alias] May-aliases at the end of function ldexp: ⊥ +[alias] analysing function: ldexpf +[alias] May-aliases at the end of function ldexpf: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: log +[alias] May-aliases at the end of function log: ⊥ +[alias] analysing function: log10 +[alias] May-aliases at the end of function log10: ⊥ +[alias] analysing function: log10f +[alias] May-aliases at the end of function log10f: ⊥ +[alias] analysing function: log10l +[alias] May-aliases at the end of function log10l: ⊥ +[alias] analysing function: log2 +[alias] May-aliases at the end of function log2: ⊥ +[alias] analysing function: log2f +[alias] May-aliases at the end of function log2f: ⊥ +[alias] analysing function: log2l +[alias] May-aliases at the end of function log2l: ⊥ +[alias] analysing function: logf +[alias] May-aliases at the end of function logf: ⊥ +[alias] analysing function: logl +[alias] May-aliases at the end of function logl: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: a = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction a = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: b = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction b = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n1 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n2 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: *(a->n1) = 1; +[alias] May-aliases after instruction *(a->n1) = 1; are <none> +[alias] analysing instruction: *(a->n2) = 1; +[alias] May-aliases after instruction *(a->n2) = 1; are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->n1 = a->n1; +[alias] May-aliases after instruction b->n1 = a->n1; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} +[alias] analysing instruction: b->n2 = a->n2; +[alias] May-aliases after instruction b->n2 = a->n2; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f1(a); +[alias] May-aliases after instruction f1(a); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f2(b); +[alias] May-aliases after instruction f2(b); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] May-aliases at the end of function main: + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nan +[alias] May-aliases at the end of function nan: ⊥ +[alias] analysing function: nanf +[alias] May-aliases at the end of function nanf: ⊥ +[alias] analysing function: nanl +[alias] May-aliases at the end of function nanl: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: pow +[alias] May-aliases at the end of function pow: ⊥ +[alias] analysing function: powf +[alias] May-aliases at the end of function powf: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: round +[alias] May-aliases at the end of function round: ⊥ +[alias] analysing function: roundf +[alias] May-aliases at the end of function roundf: ⊥ +[alias] analysing function: roundl +[alias] May-aliases at the end of function roundl: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias] analysing function: sinf +[alias] May-aliases at the end of function sinf: ⊥ +[alias] analysing function: sinl +[alias] May-aliases at the end of function sinl: ⊥ +[alias] analysing function: sqrt +[alias] May-aliases at the end of function sqrt: ⊥ +[alias] analysing function: sqrtf +[alias] May-aliases at the end of function sqrtf: ⊥ +[alias] analysing function: sqrtl +[alias] May-aliases at the end of function sqrtl: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: swap +[alias] May-aliases at the end of function swap: <none> +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: tan +[alias] May-aliases at the end of function tan: ⊥ +[alias] analysing function: tanf +[alias] May-aliases at the end of function tanf: ⊥ +[alias] analysing function: tanl +[alias] May-aliases at the end of function tanl: ⊥ +[alias] analysing function: trunc +[alias] May-aliases at the end of function trunc: ⊥ +[alias] analysing function: truncf +[alias] May-aliases at the end of function truncf: ⊥ +[alias] analysing function: truncl +[alias] May-aliases at the end of function truncl: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5a63a549c73983681d3129eca2bb7d2d3191a2a3 --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle @@ -0,0 +1,133 @@ +[kernel] Parsing function1_v2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: alias +[alias] analysing instruction: *x = *y; +[alias] May-aliases after instruction *x = *y; are {x, y} +[alias] May-aliases at the end of function alias: {x, y} +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: int *b = malloc(sizeof(int)); +[alias] May-aliases after instruction int *b = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *b = 42; +[alias] May-aliases after instruction *b = 42; are <none> +[alias] analysing instruction: alias(& a,& b); +[alias] May-aliases after instruction alias(& a,& b); are {&a, &b} {a, b} +[alias] analysing instruction: *a = 7; +[alias] May-aliases after instruction *a = 7; are {&a, &b} {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {&a, &b} {a, b} +[alias] May-aliases at the end of function main: {&a, &b} {a, b} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/test_config b/src/plugins/alias/tests/test_config new file mode 100644 index 0000000000000000000000000000000000000000..e14c0a6d24720b60c9a29eb36a4bb4cd432e5b55 --- /dev/null +++ b/src/plugins/alias/tests/test_config @@ -0,0 +1,2 @@ +PLUGIN: alias +OPT: -alias -alias-verbose 3 diff --git a/src/plugins/alias/tests/unsupported/asm.c b/src/plugins/alias/tests/unsupported/asm.c new file mode 100644 index 0000000000000000000000000000000000000000..ba2e80cb752079eb603e6a82baf938ea40e72804 --- /dev/null +++ b/src/plugins/alias/tests/unsupported/asm.c @@ -0,0 +1,4 @@ +int main () { + asm("movq %0, %%rsi"); + return 0; +} diff --git a/src/plugins/alias/tests/unsupported/explicit_pointer.c b/src/plugins/alias/tests/unsupported/explicit_pointer.c new file mode 100644 index 0000000000000000000000000000000000000000..a0b5e8f2c516d9f042cb31a6870bf803430a770c --- /dev/null +++ b/src/plugins/alias/tests/unsupported/explicit_pointer.c @@ -0,0 +1,3 @@ +int main () { + return *((int*)1); +} diff --git a/src/plugins/alias/tests/unsupported/pointer_call.c b/src/plugins/alias/tests/unsupported/pointer_call.c new file mode 100644 index 0000000000000000000000000000000000000000..448ec0f752f68628673aafccdb70969d51f5a381 --- /dev/null +++ b/src/plugins/alias/tests/unsupported/pointer_call.c @@ -0,0 +1,8 @@ +int f () { + return 0; +} + +int main () { + int (*p)() = &f; + return ((*p)()); +}