From 51b197f8dec4ef360167ff41073861e8e047bf96 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 19 Oct 2023 10:59:34 +0200 Subject: [PATCH 001/128] added a new lifter in constraints, converted C to an option and tried to update transfer functions (may still need some updates) --- .devcontainer/devcontainer.json | 3 +- src/framework/constraints.ml | 63 ++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2bf28b3c6f..af25a29e3f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,7 +14,8 @@ "extensions": [ "ocamllabs.ocaml-platform", - "hackwaly.ocamlearlybird" + "hackwaly.ocamlearlybird", + "zepalmer.ocaml-indentation" ], "settings": {}, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 95a13ed516..68ce704ed7 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -463,7 +463,7 @@ struct with Deadcode -> b let sync ctx reason = lift_fun ctx D.lift S.sync ((|>) reason) `Bot - + let enter ctx r f args = let liftmap = List.map (fun (x,y) -> D.lift x, D.lift y) in lift_fun ctx liftmap S.enter ((|>) args % (|>) f % (|>) r) [] @@ -491,6 +491,67 @@ struct let event (ctx:(D.t,G.t,C.t,V.t) ctx) (e:Events.t) (octx:(D.t,G.t,C.t,V.t) ctx):D.t = lift_fun ctx D.lift S.event ((|>) (conv octx) % (|>) e) `Bot end +(** Lifts a [Spec] with the context gas variable. TODO *) +module ContextGasLifter (S:Spec) + : Spec with module D = S.D + and module G = S.G += +struct + include S + module D = S.D + module G = S.G + module C = + struct + include Printable.Option (S.C) (struct let name = "context gas" end) + end + module V = S.V + module P = S.P + + let name () = S.name ()^" with context gas" + + let context fd d = None (* TODO*) + + let unlift c = + match c with + | Some x -> x + | None -> ctx_failwith "context gas" (*TODO*) + + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = + {ctx with context = (fun () -> unlift (ctx.context ())) } + + let convOpt c = + match c with + | Some x -> Some (unlift x) + | None -> None + + (*let lift_fun ctx g h b = + try h (g (conv ctx)) + with Ctx_failure _ -> b*) + + let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () + let query ctx (type a) (q: a Queries.t): a Queries.result = + try S.query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q + let assign ctx lval expr = try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () + let vdecl ctx v = try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () + let body ctx fundec = try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () + let branch ctx e tv = try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () + let return ctx r f = try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () + let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () + let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () + let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () + let enter ctx r f args = try S.enter (conv ctx) r f args with Ctx_failure _ -> [] + let combine_env ctx r fe f args fc es f_ask = + try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () + let combine_assign ctx r fe f args fc es f_ask = + try S.combine_assign (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () + let paths_as_set ctx = try S.paths_as_set (conv ctx) with Ctx_failure _ -> [] + let threadenter ctx lval f args = try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] + let threadspawn ctx lval f args fctx = try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () + let event ctx e octx = try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + +end + module type Increment = sig val increment: increment_data option From 163123f1bc94db3e4bb4d7b17094e589891fdc47 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 19 Oct 2023 14:22:14 +0200 Subject: [PATCH 002/128] added lifter to control, added context gas in lifter, with this change 13 tests are failing --- src/framework/constraints.ml | 12 ++++++++---- src/framework/control.ml | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 68ce704ed7..c32246a0e9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -503,22 +503,22 @@ struct module C = struct include Printable.Option (S.C) (struct let name = "context gas" end) + let context_gas = ref 100 end module V = S.V module P = S.P let name () = S.name ()^" with context gas" - let context fd d = None (* TODO*) + let context fd d = if !C.context_gas == 0 then None else Some (S.context fd d) (* TODO*) let unlift c = match c with | Some x -> x | None -> ctx_failwith "context gas" (*TODO*) - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - {ctx with context = (fun () -> unlift (ctx.context ())) } + {ctx with context = (fun () -> unlift (ctx.context ())) } (*TODO eleganter?*) let convOpt c = match c with @@ -528,6 +528,11 @@ struct (*let lift_fun ctx g h b = try h (g (conv ctx)) with Ctx_failure _ -> b*) + + let enter ctx r f args = + try C.context_gas := !C.context_gas - 1; + S.enter (conv ctx) r f args + with Ctx_failure _ -> [] let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () let query ctx (type a) (q: a Queries.t): a Queries.result = @@ -540,7 +545,6 @@ struct let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - let enter ctx r f args = try S.enter (conv ctx) r f args with Ctx_failure _ -> [] let combine_env ctx r fe f args fc es f_ask = try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () let combine_assign ctx r fe f args fc es f_ask = diff --git a/src/framework/control.ml b/src/framework/control.ml index 9baa2dd1ca..7bd4588a2a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -28,6 +28,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (not arg_enabled) (module PathSensitive2) |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) |> lift true (module DeadCodeLifter) + |> lift true (module ContextGasLifter) |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) From 7f6f3e088b249c2354b8b42bd245522f3b267455 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 22 Oct 2023 18:17:15 +0200 Subject: [PATCH 003/128] changed constraints, added test case, not working if context gas = 0 --- src/framework/constraints.ml | 174 ++++++++++++++---- src/framework/control.ml | 6 +- .../01-simple-recursion-depth50.c | 17 ++ 3 files changed, 154 insertions(+), 43 deletions(-) create mode 100644 tests/regression/80-context_gas/01-simple-recursion-depth50.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index c32246a0e9..aa60ff30dd 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -6,6 +6,7 @@ open GoblintCil open MyCFG open Analyses open GobConfig +include Printf module M = Messages @@ -463,7 +464,7 @@ struct with Deadcode -> b let sync ctx reason = lift_fun ctx D.lift S.sync ((|>) reason) `Bot - + let enter ctx r f args = let liftmap = List.map (fun (x,y) -> D.lift x, D.lift y) in lift_fun ctx liftmap S.enter ((|>) args % (|>) f % (|>) r) [] @@ -501,58 +502,151 @@ struct module D = S.D module G = S.G module C = - struct - include Printable.Option (S.C) (struct let name = "context gas" end) - let context_gas = ref 100 - end + struct + include Printable.Option (S.C) (struct let name = "context gas" end) + let context_gas = ref 10 + end module V = S.V module P = S.P let name () = S.name ()^" with context gas" - let context fd d = if !C.context_gas == 0 then None else Some (S.context fd d) (* TODO*) + let context fd d = (*printf "context";*) + if !C.context_gas == 0 then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) let unlift c = match c with - | Some x -> x - | None -> ctx_failwith "context gas" (*TODO*) + | Some x -> x + | None -> ctx_failwith "context gas" (*TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - {ctx with context = (fun () -> unlift (ctx.context ())) } (*TODO eleganter?*) - - let convOpt c = + (*if C.context_gas == 0 + then + {ctx with context = (fun () -> ) } + else*) + {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + + (*let convOpt c = match c with - | Some x -> Some (unlift x) - | None -> None + | Some x -> Some (unlift x) + | None -> None*) (*let lift_fun ctx g h b = try h (g (conv ctx)) with Ctx_failure _ -> b*) - + + let rec showExprList args = + match args with + | [] -> " " + | a::t -> (CilType.Exp.show a) ^ (showExprList t) + let enter ctx r f args = - try C.context_gas := !C.context_gas - 1; - S.enter (conv ctx) r f args - with Ctx_failure _ -> [] + (*printf "enter";*) + if !C.context_gas <> 0 then + try ( + if not !AnalysisState.postsolving + then + (C.context_gas := !C.context_gas - 1; + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)) + else printf " "; + S.enter (conv ctx) r f args ) + with Ctx_failure _ -> [] + else [] + + let sync ctx reason = + (*printf "sync";*) + if !C.context_gas <> 0 then + try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let query ctx (type a) (q: a Queries.t): a Queries.result = + (*printf "query";*) + if !C.context_gas <> 0 then + try query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q + else Queries.Result.bot q + + let assign ctx lval expr = + (*printf "assign";*) + if !C.context_gas <> 0 then + try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let vdecl ctx v = + (*printf "vdecl";*) + if !C.context_gas <> 0 then + try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () + else S.D.bot () + let body ctx fundec = + (*printf "body";*) + if !C.context_gas <> 0 then + try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let branch ctx e tv = + (*printf "branch";*) + if !C.context_gas <> 0 then + try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let return ctx r f = + (*printf "return";*) + if !C.context_gas <> 0 then + try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let asm ctx = + (*printf "asm";*) + if !C.context_gas <> 0 then + try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let skip ctx = + (*printf "skip";*) + if !C.context_gas <> 0 then + try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let special ctx r f args = + (*printf "special";*) + if !C.context_gas <> 0 then + try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let combine_env ctx r fe f args fc es f_ask = + (*printf "combine_env";*) + if !C.context_gas <> 0 then + try S.combine_env (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () + else S.D.bot () - let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () - let query ctx (type a) (q: a Queries.t): a Queries.result = - try S.query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q - let assign ctx lval expr = try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () - let vdecl ctx v = try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () - let body ctx fundec = try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () - let branch ctx e tv = try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () - let return ctx r f = try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () - let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () - let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () - let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - let combine_env ctx r fe f args fc es f_ask = - try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () let combine_assign ctx r fe f args fc es f_ask = - try S.combine_assign (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () - let paths_as_set ctx = try S.paths_as_set (conv ctx) with Ctx_failure _ -> [] - let threadenter ctx lval f args = try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] - let threadspawn ctx lval f args fctx = try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () - let event ctx e octx = try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + (*printf "combine_assign";*) + if !C.context_gas <> 0 then + try S.combine_assign (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let paths_as_set ctx = + (*printf "paths_as_set";*) + if !C.context_gas <> 0 then + try S.paths_as_set (conv ctx) with Ctx_failure _ -> [S.D.bot ()] + else [S.D.bot ()] + + let threadenter ctx lval f args = + (*printf "threadenter";*) + if !C.context_gas <> 0 then + try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] + else [] + + let threadspawn ctx lval f args fctx = + (*printf "threadspawn";*) + if !C.context_gas <> 0 then + try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let event ctx e octx = + (*printf "event";*) + if !C.context_gas <> 0 then + try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () end @@ -1192,7 +1286,7 @@ struct | `Lifted2 d -> LH.replace l' x d (* | `Bot -> () *) (* Since Verify2 is broken and only checks existing keys, add it with local bottom value. - This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) + This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) | `Bot -> LH.replace l' x (S.D.bot ()) | `Top -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has top value" | `Lifted1 _ -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has global value" @@ -1830,10 +1924,10 @@ struct in PP.iter f h1; (* let k1 = Set.of_enum @@ PP.keys h1 in - let k2 = Set.of_enum @@ PP.keys h2 in - let o1 = Set.cardinal @@ Set.diff k1 k2 in - let o2 = Set.cardinal @@ Set.diff k2 k1 in - Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) + let k2 = Set.of_enum @@ PP.keys h2 in + let o1 = Set.cardinal @@ Set.diff k1 k2 in + let o2 = Set.cardinal @@ Set.diff k2 k1 in + Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) Printf.printf "locals: \tequal = %d\tleft = %d\tright = %d\tincomparable = %d\n" !eq !le !gr !uk let compare_locals_ctx h1 h2 = diff --git a/src/framework/control.ml b/src/framework/control.ml index 7bd4588a2a..9a8855b90a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -19,7 +19,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) + (module MCP.MCP2 : Spec) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) @@ -27,8 +27,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift arg_enabled (module WitnessConstraints.PathSensitive3) |> lift (not arg_enabled) (module PathSensitive2) |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift true (module ContextGasLifter) + |> lift true (module DeadCodeLifter) |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) @@ -37,6 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) + |> lift true (module ContextGasLifter) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple-recursion-depth50.c new file mode 100644 index 0000000000..866492a34d --- /dev/null +++ b/tests/regression/80-context_gas/01-simple-recursion-depth50.c @@ -0,0 +1,17 @@ +// PARAM: --enable ana.int.interval +#include + +int global; + +int main(void) +{ + f(10); +} + +int f(int i) +{ + if (i > 0){ + i--; + f(i); + } +} From 93477032db18ad51b957dd9b95aa25e288717f94 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 23 Oct 2023 12:03:01 +0200 Subject: [PATCH 004/128] just checking if the tests in github actions are now working :)), nothing major new happend --- src/framework/constraints.ml | 14 +---- src/framework/control.ml | 118 +++++++++++++++++------------------ 2 files changed, 61 insertions(+), 71 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 37a0b12f31..902767cef4 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -520,21 +520,11 @@ struct | None -> ctx_failwith "context gas" (*TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - (*if C.context_gas == 0 - then - {ctx with context = (fun () -> ) } + (*if !C.context_gas == 0 + then {ctx with context = (fun () -> )} else*) {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) - (*let convOpt c = - match c with - | Some x -> Some (unlift x) - | None -> None*) - - (*let lift_fun ctx g h b = - try h (g (conv ctx)) - with Ctx_failure _ -> b*) - let rec showExprList args = match args with | [] -> " " diff --git a/src/framework/control.ml b/src/framework/control.ml index 9a8855b90a..4857534750 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -19,25 +19,25 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift true (module ContextGasLifter) - ) in + (module MCP.MCP2 : Spec) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift true (module ContextGasLifter) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) @@ -302,10 +302,10 @@ struct | MyCFG.Assign (lval,exp) -> if M.tracing then M.trace "global_inits" "Assign %a = %a\n" d_lval lval d_exp exp; (match lval, exp with - | (Var v,o), (AddrOf (Var f,NoOffset)) - when v.vstorage <> Static && isFunctionType f.vtype -> - (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) - | _ -> () + | (Var v,o), (AddrOf (Var f,NoOffset)) + when v.vstorage <> Static && isFunctionType f.vtype -> + (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) + | _ -> () ); let res = Spec.assign {ctx with local = st} lval exp in (* Needed for privatizations (e.g. None) that do not side immediately *) @@ -529,9 +529,9 @@ struct GobSys.mkdir_or_exists save_run; GobConfig.write_file config; let module Meta = struct - type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] - let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } - end + type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] + let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } + end in (* Yojson.Safe.to_file meta Meta.json; *) Yojson.Safe.pretty_to_channel (Stdlib.open_out (Fpath.to_string meta)) Meta.json; (* the above is compact, this is pretty-printed *) @@ -583,10 +583,10 @@ struct in let print_and_calculate_uncalled = function | GFun (fn, loc) when is_bad_uncalled fn.svar loc-> - let cnt = Cilfacade.countLoc fn in - uncalled_dead := !uncalled_dead + cnt; - if get_bool "ana.dead-code.functions" then - M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) + let cnt = Cilfacade.countLoc fn in + uncalled_dead := !uncalled_dead + cnt; + if get_bool "ana.dead-code.functions" then + M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) | _ -> () in List.iter print_and_calculate_uncalled file.globals; @@ -618,35 +618,35 @@ struct NodeH.modify_opt node join by_node; ); by_loc, by_node - in - - let ask ?(node = MyCFG.dummy_node) loc = - let f (type a) (q : a Queries.t) : a = - match Hashtbl.find_option joined_by_loc loc with - | None -> Queries.Result.bot q - | Some local -> Query.ask_local_node gh node local q - in - ({ f } : Queries.ask) - in - - (* A node is dead when its abstract value is bottom in all contexts; - it holds that: bottom in all contexts iff. bottom in the join of all contexts. - Therefore, we just answer whether the (stored) join is bottom. *) - let must_be_dead node = - NodeH.find_option joined_by_node node - (* nodes that didn't make it into the result are definitely dead (hence for_all) *) - |> GobOption.for_all Spec.D.is_bot - in - - let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in - - let skipped_statements from_node edge to_node = - CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] - in - - Transform.run_transformations file active_transformations - { ask ; must_be_dead ; must_be_uncalled ; - cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; + in + + let ask ?(node = MyCFG.dummy_node) loc = + let f (type a) (q : a Queries.t) : a = + match Hashtbl.find_option joined_by_loc loc with + | None -> Queries.Result.bot q + | Some local -> Query.ask_local_node gh node local q + in + ({ f } : Queries.ask) + in + + (* A node is dead when its abstract value is bottom in all contexts; + it holds that: bottom in all contexts iff. bottom in the join of all contexts. + Therefore, we just answer whether the (stored) join is bottom. *) + let must_be_dead node = + NodeH.find_option joined_by_node node + (* nodes that didn't make it into the result are definitely dead (hence for_all) *) + |> GobOption.for_all Spec.D.is_bot + in + + let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in + + let skipped_statements from_node edge to_node = + CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] + in + + Transform.run_transformations file active_transformations + { ask ; must_be_dead ; must_be_uncalled ; + cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; ); lh, gh From c861d29b0cc741ec8ccdcc899d56f7feea3565c5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 1 Nov 2023 16:59:50 +0100 Subject: [PATCH 005/128] added two testcases; fixed a copy paste error in query; deleted debugging prints; made it compact and nice --- src/framework/constraints.ml | 156 ++++-------------- src/framework/control.ml | 2 +- .../01-simple-recursion-depth50.c | 20 ++- .../80-context_gas/02-two-recursions.c | 40 +++++ .../03-special-values-handeling.c | 22 +++ 5 files changed, 112 insertions(+), 128 deletions(-) create mode 100644 tests/regression/80-context_gas/02-two-recursions.c create mode 100644 tests/regression/80-context_gas/03-special-values-handeling.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 902767cef4..77da51ac53 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -503,140 +503,50 @@ struct module G = S.G module C = struct - include Printable.Option (S.C) (struct let name = "context gas" end) + include Printable.Option (S.C) (struct let name = "contextGas" end) let context_gas = ref 10 end module V = S.V module P = S.P - let name () = S.name ()^" with context gas" - - let context fd d = (*printf "context";*) - if !C.context_gas == 0 then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) - - let unlift c = - match c with - | Some x -> x - | None -> ctx_failwith "context gas" (*TODO*) - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - (*if !C.context_gas == 0 - then {ctx with context = (fun () -> )} - else*) - {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) - - let rec showExprList args = + let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " | a::t -> (CilType.Exp.show a) ^ (showExprList t) + let name () = S.name ()^" with context gas" + + let context fd d = + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) + then {ctx with context = (fun () -> ctx_failwith "contextGas") } + else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + let enter ctx r f args = - (*printf "enter";*) - if !C.context_gas <> 0 then - try ( - if not !AnalysisState.postsolving - then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)) - else printf " "; - S.enter (conv ctx) r f args ) - with Ctx_failure _ -> [] - else [] - - let sync ctx reason = - (*printf "sync";*) - if !C.context_gas <> 0 then - try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let query ctx (type a) (q: a Queries.t): a Queries.result = - (*printf "query";*) - if !C.context_gas <> 0 then - try query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q - else Queries.Result.bot q - - let assign ctx lval expr = - (*printf "assign";*) - if !C.context_gas <> 0 then - try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let vdecl ctx v = - (*printf "vdecl";*) - if !C.context_gas <> 0 then - try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () - else S.D.bot () - let body ctx fundec = - (*printf "body";*) - if !C.context_gas <> 0 then - try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let branch ctx e tv = - (*printf "branch";*) - if !C.context_gas <> 0 then - try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let return ctx r f = - (*printf "return";*) - if !C.context_gas <> 0 then - try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let asm ctx = - (*printf "asm";*) - if !C.context_gas <> 0 then - try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let skip ctx = - (*printf "skip";*) - if !C.context_gas <> 0 then - try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let special ctx r f args = - (*printf "special";*) - if !C.context_gas <> 0 then - try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let combine_env ctx r fe f args fc es f_ask = - (*printf "combine_env";*) - if !C.context_gas <> 0 then - try S.combine_env (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () - else S.D.bot () + if (not !AnalysisState.postsolving) && (!C.context_gas > 0) + then + (C.context_gas := !C.context_gas - 1; + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + S.enter (conv ctx) r f args - let combine_assign ctx r fe f args fc es f_ask = - (*printf "combine_assign";*) - if !C.context_gas <> 0 then - try S.combine_assign (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let paths_as_set ctx = - (*printf "paths_as_set";*) - if !C.context_gas <> 0 then - try S.paths_as_set (conv ctx) with Ctx_failure _ -> [S.D.bot ()] - else [S.D.bot ()] - - let threadenter ctx lval f args = - (*printf "threadenter";*) - if !C.context_gas <> 0 then - try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] - else [] - - let threadspawn ctx lval f args fctx = - (*printf "threadspawn";*) - if !C.context_gas <> 0 then - try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let event ctx e octx = - (*printf "event";*) - if !C.context_gas <> 0 then - try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () + let sync ctx reason = S.sync (conv ctx) reason + let query ctx q = S.query (conv ctx) q + let assign ctx lval expr = S.assign (conv ctx) lval expr + let vdecl ctx v = S.vdecl (conv ctx) v + let body ctx fundec = S.body (conv ctx) fundec + let branch ctx e tv = S.branch (conv ctx) e tv + let return ctx r f = S.return (conv ctx) r f + let asm ctx = S.asm (conv ctx) + let skip ctx = S.skip (conv ctx) + let special ctx r f args = S.special (conv ctx) r f args + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let paths_as_set ctx = S.paths_as_set (conv ctx) + let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) (*TODO*) + let event ctx e octx = S.event (conv ctx) e (conv octx) end diff --git a/src/framework/control.ml b/src/framework/control.ml index 4857534750..2576d6b1a4 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,7 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift true (module ContextGasLifter) + |> lift true (module ContextGasLifter) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple-recursion-depth50.c index 866492a34d..0b2fe05dc2 100644 --- a/tests/regression/80-context_gas/01-simple-recursion-depth50.c +++ b/tests/regression/80-context_gas/01-simple-recursion-depth50.c @@ -1,17 +1,29 @@ -// PARAM: --enable ana.int.interval +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include #include -int global; - +int a = 0; int main(void) { - f(10); + f(50); + + __goblint_check (a<20); + __goblint_check (a<15); + __goblint_check (a<10); + __goblint_check (a<5); + __goblint_check (a==0); } int f(int i) { + + if (i > 0){ i--; + a = i; f(i); } + } + + diff --git a/tests/regression/80-context_gas/02-two-recursions.c b/tests/regression/80-context_gas/02-two-recursions.c new file mode 100644 index 0000000000..03166dee31 --- /dev/null +++ b/tests/regression/80-context_gas/02-two-recursions.c @@ -0,0 +1,40 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include +#include + +int main(void) +{ + int res1 = f(10); + int res2 = g(10); + int result = res1 + res2; + __goblint_check (result == 4); // context sensitive + __goblint_check (result <= 6); // context insensitive +} + +// gets either even or odd i values +int f(int i) +{ + if (i == 0){ + return 1; + } + if (i > 0){ + i--; + g(i); + } + return 2; +} + +// gets either even or odd i values +int g(int i) +{ + if (i == 0){ + return 3; + } + if (i > 0){ + i--; + f(i); + } + return 4; +} + + diff --git a/tests/regression/80-context_gas/03-special-values-handeling.c b/tests/regression/80-context_gas/03-special-values-handeling.c new file mode 100644 index 0000000000..0599b40d28 --- /dev/null +++ b/tests/regression/80-context_gas/03-special-values-handeling.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include +#include + +int main(void) +{ + int res = f(10); + __goblint_check (res==100); +} + +// gets either even or odd i values +int f(int i) +{ + if (i == 0){ + return 100; + } + if (i > 0){ + i--; + f(i); + } + return 0; +} From badfe3b7fea676079b3e3c29f46e4ac4862ad144 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 08:50:18 +0100 Subject: [PATCH 006/128] removed prints for clean output --- src/framework/constraints.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 77da51ac53..5ae5284da0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -517,7 +517,7 @@ struct let name () = S.name ()^" with context gas" let context fd d = - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then ((*printf "gas=0\n";*) None) else Some (S.context fd d) (* TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) @@ -527,8 +527,8 @@ struct let enter ctx r f args = if (not !AnalysisState.postsolving) && (!C.context_gas > 0) then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + (C.context_gas := !C.context_gas - 1; + (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)*)); S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason From 4b89cd151676aa3df3495b46ab1f346c509f6b55 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 11:01:16 +0100 Subject: [PATCH 007/128] status after the 2. meeting with supervisor --- src/framework/constraints.ml | 8 ++++---- src/framework/control.ml | 2 +- ...le-recursion-depth50.c => 01-simple_recursion.c} | 13 +++---------- .../{02-two-recursions.c => 02-two_recursions.c} | 0 ...es-handeling.c => 03-special_values_handeling.c} | 0 tests/regression/80-context_gas/04-two_param.c | 11 +++++++++++ 6 files changed, 19 insertions(+), 15 deletions(-) rename tests/regression/80-context_gas/{01-simple-recursion-depth50.c => 01-simple_recursion.c} (58%) rename tests/regression/80-context_gas/{02-two-recursions.c => 02-two_recursions.c} (100%) rename tests/regression/80-context_gas/{03-special-values-handeling.c => 03-special_values_handeling.c} (100%) create mode 100644 tests/regression/80-context_gas/04-two_param.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 5ae5284da0..e027eb9f42 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -517,18 +517,18 @@ struct let name () = S.name ()^" with context gas" let context fd d = - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then ((*printf "gas=0\n";*) None) else Some (S.context fd d) (* TODO*) + if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) + if (!C.context_gas <= 0) then {ctx with context = (fun () -> ctx_failwith "contextGas") } else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) let enter ctx r f args = - if (not !AnalysisState.postsolving) && (!C.context_gas > 0) + if (!C.context_gas > 0) then (C.context_gas := !C.context_gas - 1; - (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)*)); + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason diff --git a/src/framework/control.ml b/src/framework/control.ml index 2576d6b1a4..8dd5e321f4 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -35,7 +35,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) + (*|> lift true (module LongjmpLifter)*) |> lift true (module ContextGasLifter) ) in GobConfig.building_spec := false; diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple_recursion.c similarity index 58% rename from tests/regression/80-context_gas/01-simple-recursion-depth50.c rename to tests/regression/80-context_gas/01-simple_recursion.c index 0b2fe05dc2..044ea12dd8 100644 --- a/tests/regression/80-context_gas/01-simple-recursion-depth50.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -2,28 +2,21 @@ #include #include -int a = 0; +int a = 5; int main(void) { - f(50); + f(5); - __goblint_check (a<20); - __goblint_check (a<15); - __goblint_check (a<10); - __goblint_check (a<5); - __goblint_check (a==0); + __goblint_check (a==0); // FAIL } int f(int i) { - - if (i > 0){ i--; a = i; f(i); } - } diff --git a/tests/regression/80-context_gas/02-two-recursions.c b/tests/regression/80-context_gas/02-two_recursions.c similarity index 100% rename from tests/regression/80-context_gas/02-two-recursions.c rename to tests/regression/80-context_gas/02-two_recursions.c diff --git a/tests/regression/80-context_gas/03-special-values-handeling.c b/tests/regression/80-context_gas/03-special_values_handeling.c similarity index 100% rename from tests/regression/80-context_gas/03-special-values-handeling.c rename to tests/regression/80-context_gas/03-special_values_handeling.c diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c new file mode 100644 index 0000000000..890e8faf62 --- /dev/null +++ b/tests/regression/80-context_gas/04-two_param.c @@ -0,0 +1,11 @@ +int main () { + f(50,50); +} + +int f (int x, int y){ + if (x == 0){ + __goblint_check (y == 0); + return 0; + } + f (--x, --y); +} \ No newline at end of file From e5de16534e14192f06be81eb4d99783d53038641 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 18:52:35 +0100 Subject: [PATCH 008/128] changed module C, no compiler errors, but implementations are not complete yet --- src/framework/constraints.ml | 46 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e027eb9f42..57d8ac5396 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -501,34 +501,54 @@ struct include S module D = S.D module G = S.G + + module PrintableInt = (*TODO*) + struct + type t = int [@@deriving eq, ord, hash] + + include Printable.Std + + let name () = "Integer" + let show x = string_of_int x + let pretty () x = Pretty.dprintf "Integer: %i" x + let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) + let to_yojson x = `String (string_of_int x) + + let arbitrary () = QCheck.int_range 0 (10000 - 1) + let relift x = x + end + module C = struct - include Printable.Option (S.C) (struct let name = "contextGas" end) - let context_gas = ref 10 + include Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) end module V = S.V module P = S.P - let rec showExprList args = (*TODO: delete, just here for printing*) + + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) let name () = S.name ()^" with context gas" let context fd d = - if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + (*if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*)*) + ((Some (S.context fd d)), 2 ) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (!C.context_gas <= 0) + (*if (!C.context_gas <= 0) then {ctx with context = (fun () -> ctx_failwith "contextGas") } - else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + else*) + {ctx with context = (fun () -> Option.get ( fst (ctx.context ()))) } (*TODO Raises Invalid_argument if o is None.?*) let enter ctx r f args = - if (!C.context_gas > 0) - then + (*if (!C.context_gas > 0) + then (C.context_gas := !C.context_gas - 1; printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + S.enter (conv ctx) r f args*) S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason @@ -541,11 +561,11 @@ struct let asm ctx = S.asm (conv ctx) let skip ctx = S.skip (conv ctx) let special ctx r f args = S.special (conv ctx) r f args - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask let paths_as_set ctx = S.paths_as_set (conv ctx) - let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) (*TODO*) + let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) let event ctx e octx = S.event (conv ctx) e (conv octx) end From ac289ee0e6623fa67707eefe3a5fea990cf6fe2d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 10:51:26 +0100 Subject: [PATCH 009/128] converted D to a Product with an Int, same for C, changed the transfer functions; code is running for simple example, improvement for the int modules need still to be done --- src/framework/constraints.ml | 134 ++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 43 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 57d8ac5396..60546435eb 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -494,13 +494,10 @@ end (** Lifts a [Spec] with the context gas variable. TODO *) module ContextGasLifter (S:Spec) - : Spec with module D = S.D - and module G = S.G + : Spec with module G = S.G = struct include S - module D = S.D - module G = S.G module PrintableInt = (*TODO*) struct @@ -513,60 +510,111 @@ struct let pretty () x = Pretty.dprintf "Integer: %i" x let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) let to_yojson x = `String (string_of_int x) - - let arbitrary () = QCheck.int_range 0 (10000 - 1) let relift x = x end - module C = - struct - include Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) - end - module V = S.V - module P = S.P + module LatticeInt = (*TODO*) + struct + include PrintableInt + + let leq x y = x <= y + let join x y = max x y + let widen = join + let meet x y = min x y + + let narrow = meet + let top () = 10000 + let is_top a = match a with + | 10000 -> true + | _ -> false + let bot () = 0 + let is_bot a = match a with + | 0 -> true + | _ -> false + + let pretty_diff () ((x:t),(y:t)): Pretty.doc = + Pretty.dprintf "%a not leq %a" pretty x pretty y + + end + module D = Lattice.Prod (S.D) (LatticeInt) + module G = S.G + + module C = Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) + module V = S.V + module P = + struct + include S.P + let of_elt (x, _) = of_elt x + end (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) - let name () = S.name ()^" with context gas" - - let context fd d = - (*if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*)*) - ((Some (S.context fd d)), 2 ) + let context_gas_start = 20 - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - (*if (!C.context_gas <= 0) - then {ctx with context = (fun () -> ctx_failwith "contextGas") } - else*) - {ctx with context = (fun () -> Option.get ( fst (ctx.context ()))) } (*TODO Raises Invalid_argument if o is None.?*) + let name () = S.name ()^" with context gas" + let startstate v = S.startstate v, context_gas_start + let exitstate v = S.exitstate v, 0 (* TODO*) + let morphstate v (d,i) = S.morphstate v d, i (* TODO*) + + let context_gas_value ctx = + snd ctx.local + + let context fd (d,i) = + if (i <= 0) then (printf "gas=0\n"; (None, 0)) else ((Some (S.context fd d)), i) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* TODO*) + if (context_gas_value ctx <= 0) + then { + ctx with context = (fun () -> ctx_failwith "contextGas") + ; local = fst ctx.local + ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) (*TODO*) + } else { + ctx with context = (fun () -> Option.get (fst (ctx.context ()))) + ; local = fst ctx.local + ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) + } (*TODO Raises Invalid_argument if o is None.?*) + + let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = (* TODO*) + (*printf "context_gas_value = %i \n" (context_gas_value ctx);*) + if (context_gas_value ctx <= 1) (* because 1 is decreased to 0, which is already conntext insensitive*) + then { + ctx with context = (fun () -> (None, 0) ) + ; local = (fst ctx.local, 0) + } else { + ctx with context = (fun () -> (fst (ctx.context ()) , context_gas_value ctx - 1)) + ; local = (fst ctx.local, context_gas_value ctx - 1) + } let enter ctx r f args = - (*if (!C.context_gas > 0) - then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); - S.enter (conv ctx) r f args*) - S.enter (conv ctx) r f args + let ctx_dec = dec_context_gas ctx in + (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args));*) + printf "enterContextGas %i in %s with \n" (context_gas_value ctx_dec) (CilType.Fundec.show f) ; + let ctx_conv = conv ctx_dec in + let liftmap_tup = List.map (fun (x,y) -> (x, context_gas_value ctx_dec), (y, context_gas_value ctx_dec)) in + liftmap_tup (S.enter ctx_conv r f args) + + let liftmap f ctx = List.map (fun (x) -> (x, context_gas_value ctx)) f - let sync ctx reason = S.sync (conv ctx) reason + let sync ctx reason = S.sync (conv ctx) reason, context_gas_value ctx let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr - let vdecl ctx v = S.vdecl (conv ctx) v - let body ctx fundec = S.body (conv ctx) fundec - let branch ctx e tv = S.branch (conv ctx) e tv - let return ctx r f = S.return (conv ctx) r f - let asm ctx = S.asm (conv ctx) - let skip ctx = S.skip (conv ctx) - let special ctx r f args = S.special (conv ctx) r f args - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask - let paths_as_set ctx = S.paths_as_set (conv ctx) - let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) + let assign ctx lval expr = S.assign (conv ctx) lval expr, context_gas_value ctx + let vdecl ctx v = S.vdecl (conv ctx) v, context_gas_value ctx + let body ctx fundec = S.body (conv ctx) fundec, context_gas_value ctx + let branch ctx e tv = S.branch (conv ctx) e tv, context_gas_value ctx + let return ctx r f = S.return (conv ctx) r f, context_gas_value ctx + let asm ctx = S.asm (conv ctx), context_gas_value ctx + let skip ctx = S.skip (conv ctx), context_gas_value ctx + let special ctx r f args = S.special (conv ctx) r f args, context_gas_value ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx + let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), context_gas_value ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), context_gas_value ctx end From 4fdb9bc16a78ef5db6edd7e962d7405a026c78c6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 17:22:50 +0100 Subject: [PATCH 010/128] moved int Printable and lattice to the corresponding file; added and improved testcases --- src/common/domains/lattice.ml | 21 +++ src/common/domains/printable.ml | 15 ++ src/framework/constraints.ml | 144 +++++++----------- .../80-context_gas/00-hardcoded_recursion.c | 41 +++++ .../80-context_gas/01-simple_recursion.c | 25 +-- .../80-context_gas/02-two_recursions.c | 49 +++--- .../03-special_values_handeling.c | 22 --- .../80-context_gas/03_three_recursions.c | 56 +++++++ .../regression/80-context_gas/04-two_param.c | 20 ++- .../80-context_gas/05-same_functions.c | 27 ++++ 10 files changed, 262 insertions(+), 158 deletions(-) create mode 100644 tests/regression/80-context_gas/00-hardcoded_recursion.c delete mode 100644 tests/regression/80-context_gas/03-special_values_handeling.c create mode 100644 tests/regression/80-context_gas/03_three_recursions.c create mode 100644 tests/regression/80-context_gas/05-same_functions.c diff --git a/src/common/domains/lattice.ml b/src/common/domains/lattice.ml index 51306d637f..393bac7fbd 100644 --- a/src/common/domains/lattice.ml +++ b/src/common/domains/lattice.ml @@ -649,3 +649,24 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y end + +(* Integer of type Lattice*) +module LInt = +struct + include Printable.PInt + + let leq x y = x <= y + let join x y = max x y + let widen = join + let meet x y = min x y + let narrow = meet + + let top () = max_int + let is_top a = a >= top () + let bot () = 0 + let is_bot a = a <= bot () + + let pretty_diff () ((x:t),(y:t)): Pretty.doc = + Pretty.dprintf "%a not leq %a" pretty x pretty y + +end \ No newline at end of file diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index b0755fb730..e744e0ff44 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -687,3 +687,18 @@ struct let to_yojson x = x (* override SimplePretty *) end + +(* Integer of type Printable*) +module PInt = +struct + type t = int [@@deriving eq, ord, hash] + + include Std + + let name () = "Integer" + let show x = string_of_int x + let pretty () x = Pretty.dprintf "Integer: %i" x + let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) + let to_yojson x = `String (string_of_int x) + let relift x = x +end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 60546435eb..fc98a9ff26 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -492,55 +492,21 @@ struct let event (ctx:(D.t,G.t,C.t,V.t) ctx) (e:Events.t) (octx:(D.t,G.t,C.t,V.t) ctx):D.t = lift_fun ctx D.lift S.event ((|>) (conv octx) % (|>) e) `Bot end +module CGName = struct let name = "contextGas" end + (** Lifts a [Spec] with the context gas variable. TODO *) module ContextGasLifter (S:Spec) - : Spec with module G = S.G + : Spec with module D = Lattice.Prod (S.D) (Lattice.LInt) + and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + and module G = S.G = struct include S - module PrintableInt = (*TODO*) - struct - type t = int [@@deriving eq, ord, hash] - - include Printable.Std - - let name () = "Integer" - let show x = string_of_int x - let pretty () x = Pretty.dprintf "Integer: %i" x - let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) - let to_yojson x = `String (string_of_int x) - let relift x = x - end - - module LatticeInt = (*TODO*) - struct - include PrintableInt - - let leq x y = x <= y - let join x y = max x y - let widen = join - let meet x y = min x y - - let narrow = meet - let top () = 10000 - let is_top a = match a with - | 10000 -> true - | _ -> false - let bot () = 0 - let is_bot a = match a with - | 0 -> true - | _ -> false - - let pretty_diff () ((x:t),(y:t)): Pretty.doc = - Pretty.dprintf "%a not leq %a" pretty x pretty y - - end - - module D = Lattice.Prod (S.D) (LatticeInt) + module D = Lattice.Prod (S.D) (Lattice.LInt) module G = S.G - module C = Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) + module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) module V = S.V module P = struct @@ -548,73 +514,65 @@ struct let of_elt (x, _) = of_elt x end - (*let rec showExprList args = (*TODO: delete, just here for printing*) - match args with - | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) + let cg_init_val = 10 (* initial value of context gas*) - let context_gas_start = 20 + (* returns context gas value of the given ctx*) + let cg_val ctx = + snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) let name () = S.name ()^" with context gas" - let startstate v = S.startstate v, context_gas_start + let startstate v = S.startstate v, cg_init_val let exitstate v = S.exitstate v, 0 (* TODO*) let morphstate v (d,i) = S.morphstate v d, i (* TODO*) - let context_gas_value ctx = - snd ctx.local - let context fd (d,i) = - if (i <= 0) then (printf "gas=0\n"; (None, 0)) else ((Some (S.context fd d)), i) - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (context_gas_value ctx <= 0) - then { - ctx with context = (fun () -> ctx_failwith "contextGas") - ; local = fst ctx.local - ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) (*TODO*) - } else { - ctx with context = (fun () -> Option.get (fst (ctx.context ()))) - ; local = fst ctx.local - ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) - } (*TODO Raises Invalid_argument if o is None.?*) - - let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = (* TODO*) - (*printf "context_gas_value = %i \n" (context_gas_value ctx);*) - if (context_gas_value ctx <= 1) (* because 1 is decreased to 0, which is already conntext insensitive*) - then { - ctx with context = (fun () -> (None, 0) ) - ; local = (fst ctx.local, 0) - } else { - ctx with context = (fun () -> (fst (ctx.context ()) , context_gas_value ctx - 1)) - ; local = (fst ctx.local, context_gas_value ctx - 1) - } + if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = + (* D.t -> S.D.t *) + let ctx' = {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, cg_val ctx) es )} in + (* C.t -> S.C.t *) + if (cg_val ctx <= 0) + then {ctx' with context = (fun () -> ctx_failwith "contextGas")} + else {ctx' with context = (fun () -> Option.get (fst (ctx'.context ())))} + + let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = + if (cg_val ctx <= 1) + then {ctx with context = (fun () -> (None, 0) ) (* context insensitive *) + ; local = (fst ctx.local, 0)} + else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) + ; local = (fst ctx.local, cg_val ctx - 1)} + + let rec showExprList args = (*TODO: delete, just here for printing*) + match args with + | [] -> " " + | a::t -> (CilType.Exp.show a) ^ (showExprList t) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args));*) - printf "enterContextGas %i in %s with \n" (context_gas_value ctx_dec) (CilType.Fundec.show f) ; - let ctx_conv = conv ctx_dec in - let liftmap_tup = List.map (fun (x,y) -> (x, context_gas_value ctx_dec), (y, context_gas_value ctx_dec)) in - liftmap_tup (S.enter ctx_conv r f args) + if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx_dec), (y, cg_val ctx_dec)) in + liftmap_tup (S.enter (conv ctx_dec) r f args) - let liftmap f ctx = List.map (fun (x) -> (x, context_gas_value ctx)) f + let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f - let sync ctx reason = S.sync (conv ctx) reason, context_gas_value ctx + let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr, context_gas_value ctx - let vdecl ctx v = S.vdecl (conv ctx) v, context_gas_value ctx - let body ctx fundec = S.body (conv ctx) fundec, context_gas_value ctx - let branch ctx e tv = S.branch (conv ctx) e tv, context_gas_value ctx - let return ctx r f = S.return (conv ctx) r f, context_gas_value ctx - let asm ctx = S.asm (conv ctx), context_gas_value ctx - let skip ctx = S.skip (conv ctx), context_gas_value ctx - let special ctx r f args = S.special (conv ctx) r f args, context_gas_value ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let assign ctx lval expr = S.assign (conv ctx) lval expr, cg_val ctx + let vdecl ctx v = S.vdecl (conv ctx) v, cg_val ctx + let body ctx fundec = S.body (conv ctx) fundec, cg_val ctx + let branch ctx e tv = S.branch (conv ctx) e tv, cg_val ctx + let return ctx r f = S.return (conv ctx) r f, cg_val ctx + let asm ctx = S.asm (conv ctx), cg_val ctx + let skip ctx = S.skip (conv ctx), cg_val ctx + let special ctx r f args = S.special (conv ctx) r f args, cg_val ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), context_gas_value ctx - let event ctx e octx = S.event (conv ctx) e (conv octx), context_gas_value ctx + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), cg_val ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas/00-hardcoded_recursion.c new file mode 100644 index 0000000000..a512bfb491 --- /dev/null +++ b/tests/regression/80-context_gas/00-hardcoded_recursion.c @@ -0,0 +1,41 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int a = 20; + +int f(int i) +{ + if (i == 5) + { + a = 4; + f(4); + } + if (i == 4) + { + a = 3; + f(3); + } + if (i == 3) + { + a = 2; + f(2); + } + if (i == 2) + { + a = 1; + f(1); + } + if (i == 1) + { + a = 0; + f(0); + } +} + +int main(void) +{ + f(5); + + // if the analysis runs fully context sensitive, "a" should be equal 0 + __goblint_check(a == 0); +} diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas/01-simple_recursion.c index 044ea12dd8..1c5460b960 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -1,22 +1,23 @@ // PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include +#include -int a = 5; -int main(void) -{ - f(5); - - __goblint_check (a==0); // FAIL -} +int num_iterat = 5; +int a = 20; int f(int i) { - if (i > 0){ - i--; - a = i; + if (i > 0) + { + a = --i; f(i); } + return 0; } +int main(void) +{ + f(num_iterat); + // if the analysis runs fully context sensitive, "a" should be equal 0 + __goblint_check(a == 0); +} diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index 03166dee31..c331977770 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,40 +1,41 @@ // PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include +#include -int main(void) -{ - int res1 = f(10); - int res2 = g(10); - int result = res1 + res2; - __goblint_check (result == 4); // context sensitive - __goblint_check (result <= 6); // context insensitive -} +int num_iterat = 10; -// gets either even or odd i values int f(int i) { - if (i == 0){ - return 1; + int res = 0; + if (i == 0) + { + res = 1; } - if (i > 0){ - i--; - g(i); + if (i > 0) + { + res = f(--i); } - return 2; + return res; } -// gets either even or odd i values int g(int i) { - if (i == 0){ - return 3; + int res = 0; + if (i == 0) + { + res = 1; } - if (i > 0){ - i--; - f(i); + if (i > 0) + { + res = g(--i); } - return 4; + return res; } +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int result = res1 + res2; + __goblint_check(result == 2); // context sensitive +} diff --git a/tests/regression/80-context_gas/03-special_values_handeling.c b/tests/regression/80-context_gas/03-special_values_handeling.c deleted file mode 100644 index 0599b40d28..0000000000 --- a/tests/regression/80-context_gas/03-special_values_handeling.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include - -int main(void) -{ - int res = f(10); - __goblint_check (res==100); -} - -// gets either even or odd i values -int f(int i) -{ - if (i == 0){ - return 100; - } - if (i > 0){ - i--; - f(i); - } - return 0; -} diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas/03_three_recursions.c new file mode 100644 index 0000000000..10ebc4ad18 --- /dev/null +++ b/tests/regression/80-context_gas/03_three_recursions.c @@ -0,0 +1,56 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int num_iterat = 5; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int result = res1 + res2 + res3; + + __goblint_check(result == 3); // context sensitive +} diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index 890e8faf62..9f47bc80b5 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,11 +1,17 @@ -int main () { - f(50,50); -} -int f (int x, int y){ - if (x == 0){ - __goblint_check (y == 0); +int num_iterat = 5; + +int f(int x, int y) +{ + if (x == 0) + { + __goblint_check(y == 0); return 0; } - f (--x, --y); + f(--x, --y); +} + +int main() +{ + f(num_iterat, num_iterat); } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c new file mode 100644 index 0000000000..5ccb402f63 --- /dev/null +++ b/tests/regression/80-context_gas/05-same_functions.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int num_iterat = 5; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = f(num_iterat); + int result = res1 + res2; + + __goblint_check(result == 2); // context sensitive +} \ No newline at end of file From 6fb946bc74d92439f79a83fb1ee17d2f485018f4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 17:34:09 +0100 Subject: [PATCH 011/128] adapted to changes from Master: added multiple --- src/framework/constraints.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index eec097a5f0..676c88ebed 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -570,8 +570,8 @@ struct let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx - let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), cg_val ctx + let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end From b72e941d087696776635a2878578a76f865459a2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 9 Nov 2023 12:29:20 +0100 Subject: [PATCH 012/128] fixed small error at enter transfer function; now decrement should work properly; only issue:1 decrement too much --- src/framework/constraints.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 676c88ebed..ba536d7922 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -544,15 +544,16 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - let rec showExprList args = (*TODO: delete, just here for printing*) + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = + (*printf "enter\n";*) let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx_dec), (y, cg_val ctx_dec)) in + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f From fb5642f13066222a850105a8695dcac12ac98e2f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 9 Nov 2023 13:18:08 +0100 Subject: [PATCH 013/128] test if not working github tests are due to longjmpLifter --- src/framework/control.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index ea4ac7de76..f4027fc364 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -35,8 +35,8 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - (*|> lift true (module LongjmpLifter)*) - |> lift true (module ContextGasLifter) + |> lift true (module LongjmpLifter) + (*|> lift true (module ContextGasLifter) *) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From faab50f1be75e3ada1e8e924cda9483fac94743f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 10 Nov 2023 14:12:39 +0100 Subject: [PATCH 014/128] Longjump enabled, working --- src/framework/constraints.ml | 3 +-- src/framework/control.ml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ba536d7922..5757ba7fec 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -550,9 +550,8 @@ struct | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = - (*printf "enter\n";*) let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) diff --git a/src/framework/control.ml b/src/framework/control.ml index f4027fc364..8cf23c3b42 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -35,8 +35,8 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - (*|> lift true (module ContextGasLifter) *) + |> lift true (module ContextGasLifter) + |> lift true (module LongjmpLifter) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From f5b5af1fc938b4fa5d67acd975a8a3dabfc74a0a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 13 Nov 2023 09:35:20 +0100 Subject: [PATCH 015/128] moved contextGasLifter upwards, hopefully fixes some of the regression tests --- src/framework/control.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index 8cf23c3b42..3a03132322 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,6 +20,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) + |> lift true (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) @@ -35,7 +36,6 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module ContextGasLifter) |> lift true (module LongjmpLifter) ) in GobConfig.building_spec := false; From 47e75773e7b634383c5c71f639bf8415939a7921 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 14 Nov 2023 15:10:54 +0100 Subject: [PATCH 016/128] made context lifter optional; added option to test cases --- src/common/util/options.schema.json | 7 +++ src/framework/control.ml | 2 +- .../80-context_gas/00-hardcoded_recursion.c | 9 +++- .../80-context_gas/01-simple_recursion.c | 2 +- .../80-context_gas/02-two_recursions.c | 2 +- .../80-context_gas/03_three_recursions.c | 2 +- .../regression/80-context_gas/04-two_param.c | 4 +- .../80-context_gas/05-same_functions.c | 2 +- .../80-context_gas/06-function_chain.c | 54 +++++++++++++++++++ 9 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 tests/regression/80-context_gas/06-function_chain.c diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 4e282b19a4..fe319d3113 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -524,6 +524,13 @@ "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true + }, + "ctx_gas": { + "title": "ana.opt.ctx_gas", + "description": + "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/src/framework/control.ml b/src/framework/control.ml index 3a03132322..884381b8e7 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,7 +20,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift true (module ContextGasLifter) + |> lift (get_bool "ana.opt.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas/00-hardcoded_recursion.c index a512bfb491..ec601d898b 100644 --- a/tests/regression/80-context_gas/00-hardcoded_recursion.c +++ b/tests/regression/80-context_gas/00-hardcoded_recursion.c @@ -1,6 +1,7 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include +int num_iterat = 5; int a = 20; int f(int i) @@ -30,11 +31,15 @@ int f(int i) a = 0; f(0); } + if (i == 0) + { + return 0; + } } int main(void) { - f(5); + f(num_iterat); // if the analysis runs fully context sensitive, "a" should be equal 0 __goblint_check(a == 0); diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas/01-simple_recursion.c index 1c5460b960..64da74b757 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index c331977770..7a10e89a83 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 10; diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas/03_three_recursions.c index 10ebc4ad18..1782887b61 100644 --- a/tests/regression/80-context_gas/03_three_recursions.c +++ b/tests/regression/80-context_gas/03_three_recursions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index 9f47bc80b5..c52df78198 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,5 +1,5 @@ - -int num_iterat = 5; +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +int num_iterat = 10; int f(int x, int y) { diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c index 5ccb402f63..bcffc498a9 100644 --- a/tests/regression/80-context_gas/05-same_functions.c +++ b/tests/regression/80-context_gas/05-same_functions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas/06-function_chain.c new file mode 100644 index 0000000000..c88835fb14 --- /dev/null +++ b/tests/regression/80-context_gas/06-function_chain.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 10; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); // context sensitive +} From 9aa8a5e910a47bf34d4a6f6120741e0110f273c3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 14 Nov 2023 15:51:39 +0100 Subject: [PATCH 017/128] adapted the hardcoded path in test-gobview to match with this repository (this should make the gobview test work); changed the testcase recursion depth (this should make the regression tests work) --- scripts/test-gobview.py | 4 ++-- tests/regression/80-context_gas/02-two_recursions.c | 2 +- tests/regression/80-context_gas/04-two_param.c | 2 +- tests/regression/80-context_gas/06-function_chain.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/test-gobview.py b/scripts/test-gobview.py index 1ac8f6a76c..cac3ab824c 100644 --- a/scripts/test-gobview.py +++ b/scripts/test-gobview.py @@ -26,8 +26,8 @@ def serve(): global p goblint_http_path = '_build/default/gobview/goblint-http-server/goblint_http.exe' p = subprocess.Popen(['./' + goblint_http_path, - '-with-goblint', '../analyzer/goblint', - '-goblint', '--set', 'files[+]', '"../analyzer/tests/regression/00-sanity/01-assert.c"']) + '-with-goblint', '../GobContextGas/goblint', + '-goblint', '--set', 'files[+]', '"../GobContextGas/tests/regression/00-sanity/01-assert.c"']) print("serving at port", PORT) thread = Thread(target=serve, args=()) diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index 7a10e89a83..4046162c82 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,7 +1,7 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include -int num_iterat = 10; +int num_iterat = 5; int f(int i) { diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index c52df78198..71ddf42758 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -int num_iterat = 10; +int num_iterat = 5; int f(int x, int y) { diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas/06-function_chain.c index c88835fb14..d897d422bb 100644 --- a/tests/regression/80-context_gas/06-function_chain.c +++ b/tests/regression/80-context_gas/06-function_chain.c @@ -1,7 +1,7 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include -int num_iterat = 10; +int num_iterat = 5; int h(int i) { From a9eaeb466d3718019b09046f8417eaa34b4ddfdb Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 17 Nov 2023 16:25:11 +0100 Subject: [PATCH 018/128] used Chain for ctxGasLifter (deleted Int module in Printable and Lattice), ana.opt.ctx_gas -> ana.context.ctx_gas; made html output of context gas prettier (by overwriting Prod), added and adapted testcases --- src/common/domains/lattice.ml | 23 +------- src/common/domains/printable.ml | 17 +----- src/common/util/options.schema.json | 14 ++--- src/framework/constraints.ml | 38 ++++++++---- src/framework/control.ml | 2 +- .../80-context_gas/02-two_recursions.c | 41 ------------- .../80-context_gas/05-same_functions.c | 27 --------- .../01-basic_multiple_param_simple.c} | 3 +- .../02-boundary_check_simple_rec.c} | 7 +-- .../03-boundary_check_multiple_rec.c} | 11 ++-- .../04-hardcoded_recursion.c} | 5 +- .../05-function_chain.c} | 5 +- .../80-context_gas_sens/06-call_in_loop.c | 31 ++++++++++ .../80-context_gas_sens/07-call_in_loop_adv.c | 29 +++++++++ .../08-circle_call_and_loops.c | 48 +++++++++++++++ .../01-multiple_param_simple.c | 18 ++++++ .../02-boundary_check_simple_rec.c | 22 +++++++ .../03-boundary_check_multiple_rec.c | 59 +++++++++++++++++++ .../81-context_gas_insens/04-function_chain.c | 54 +++++++++++++++++ .../81-context_gas_insens/05-ackermann.c | 27 +++++++++ .../81-context_gas_insens/06-call_in_loop.c | 27 +++++++++ .../07-circle_call_and_loops.c | 48 +++++++++++++++ .../81-context_gas_insens/08-loop_unrolling.c | 39 ++++++++++++ 23 files changed, 455 insertions(+), 140 deletions(-) delete mode 100644 tests/regression/80-context_gas/02-two_recursions.c delete mode 100644 tests/regression/80-context_gas/05-same_functions.c rename tests/regression/{80-context_gas/04-two_param.c => 80-context_gas_sens/01-basic_multiple_param_simple.c} (68%) rename tests/regression/{80-context_gas/01-simple_recursion.c => 80-context_gas_sens/02-boundary_check_simple_rec.c} (51%) rename tests/regression/{80-context_gas/03_three_recursions.c => 80-context_gas_sens/03-boundary_check_multiple_rec.c} (60%) rename tests/regression/{80-context_gas/00-hardcoded_recursion.c => 80-context_gas_sens/04-hardcoded_recursion.c} (72%) rename tests/regression/{80-context_gas/06-function_chain.c => 80-context_gas_sens/05-function_chain.c} (76%) create mode 100644 tests/regression/80-context_gas_sens/06-call_in_loop.c create mode 100644 tests/regression/80-context_gas_sens/07-call_in_loop_adv.c create mode 100644 tests/regression/80-context_gas_sens/08-circle_call_and_loops.c create mode 100644 tests/regression/81-context_gas_insens/01-multiple_param_simple.c create mode 100644 tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c create mode 100644 tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c create mode 100644 tests/regression/81-context_gas_insens/04-function_chain.c create mode 100644 tests/regression/81-context_gas_insens/05-ackermann.c create mode 100644 tests/regression/81-context_gas_insens/06-call_in_loop.c create mode 100644 tests/regression/81-context_gas_insens/07-circle_call_and_loops.c create mode 100644 tests/regression/81-context_gas_insens/08-loop_unrolling.c diff --git a/src/common/domains/lattice.ml b/src/common/domains/lattice.ml index 393bac7fbd..5c6c3e96ff 100644 --- a/src/common/domains/lattice.ml +++ b/src/common/domains/lattice.ml @@ -648,25 +648,4 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y -end - -(* Integer of type Lattice*) -module LInt = -struct - include Printable.PInt - - let leq x y = x <= y - let join x y = max x y - let widen = join - let meet x y = min x y - let narrow = meet - - let top () = max_int - let is_top a = a >= top () - let bot () = 0 - let is_bot a = a <= bot () - - let pretty_diff () ((x:t),(y:t)): Pretty.doc = - Pretty.dprintf "%a not leq %a" pretty x pretty y - -end \ No newline at end of file +end \ No newline at end of file diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index e744e0ff44..759e90b6c3 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -686,19 +686,4 @@ struct ) let to_yojson x = x (* override SimplePretty *) -end - -(* Integer of type Printable*) -module PInt = -struct - type t = int [@@deriving eq, ord, hash] - - include Std - - let name () = "Integer" - let show x = string_of_int x - let pretty () x = Pretty.dprintf "Integer: %i" x - let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) - let to_yojson x = `String (string_of_int x) - let relift x = x -end +end \ No newline at end of file diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index fe319d3113..b741ea1fdc 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -524,13 +524,6 @@ "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true - }, - "ctx_gas": { - "title": "ana.opt.ctx_gas", - "description": - "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", - "type": "boolean", - "default": false } }, "additionalProperties": false @@ -952,6 +945,13 @@ "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", "type": "boolean", "default": false + }, + "ctx_gas": { + "title": "ana.context.ctx_gas", + "description": + "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 5757ba7fec..f2484f8be7 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -493,20 +493,32 @@ struct end module CGName = struct let name = "contextGas" end +module IntConf = + struct + let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) + let names x = Format.asprintf "%d" x + end -(** Lifts a [Spec] with the context gas variable. TODO *) +(** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. + If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) module ContextGasLifter (S:Spec) - : Spec with module D = Lattice.Prod (S.D) (Lattice.LInt) - and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) + and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.Chain (IntConf)) and module G = S.G = struct include S - module D = Lattice.Prod (S.D) (Lattice.LInt) - module G = S.G + module Context_Gas_Prod (Base1: Printable.S) (Base2: Printable.S) = + struct + include Printable.Prod (Base1) (Base2) + let printXml f (x,y) = + BatPrintf.fprintf f "\n\n\n%s\n\n%a\nContext Gas Value\n\n%a\n\n" (XmlUtil.escape (Base1.name ())) Base1.printXml x Base2.printXml y + end - module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) + module G = S.G + module C = Context_Gas_Prod (Printable.Option (S.C) (CGName)) (Lattice.Chain (IntConf)) module V = S.V module P = struct @@ -522,8 +534,8 @@ struct let name () = S.name ()^" with context gas" let startstate v = S.startstate v, cg_init_val - let exitstate v = S.exitstate v, 0 (* TODO*) - let morphstate v (d,i) = S.morphstate v d, i (* TODO*) + let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) + let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) @@ -531,10 +543,10 @@ struct let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* D.t -> S.D.t *) let ctx' = {ctx with local = fst ctx.local - ; split = (fun d es -> ctx.split (d, cg_val ctx) es )} in + ; split = (fun d es -> ctx.split (d, cg_val ctx) es)} in (* C.t -> S.C.t *) if (cg_val ctx <= 0) - then {ctx' with context = (fun () -> ctx_failwith "contextGas")} + then {ctx' with context = (fun () -> ctx_failwith "no context (contextGas = 0)")} else {ctx' with context = (fun () -> Option.get (fst (ctx'.context ())))} let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = @@ -544,14 +556,14 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - (*let rec showExprList args = (*TODO: delete, just here for printing*) + let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) diff --git a/src/framework/control.ml b/src/framework/control.ml index 884381b8e7..ea9476e1d3 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,7 +20,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.opt.ctx_gas") (module ContextGasLifter) + |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c deleted file mode 100644 index 4046162c82..0000000000 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ /dev/null @@ -1,41 +0,0 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -#include - -int num_iterat = 5; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int result = res1 + res2; - - __goblint_check(result == 2); // context sensitive -} diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c deleted file mode 100644 index bcffc498a9..0000000000 --- a/tests/regression/80-context_gas/05-same_functions.c +++ /dev/null @@ -1,27 +0,0 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -#include - -int num_iterat = 5; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = f(num_iterat); - int result = res1 + res2; - - __goblint_check(result == 2); // context sensitive -} \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c similarity index 68% rename from tests/regression/80-context_gas/04-two_param.c rename to tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c index 71ddf42758..d1715eaced 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c @@ -1,4 +1,5 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example int num_iterat = 5; int f(int x, int y) diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c similarity index 51% rename from tests/regression/80-context_gas/01-simple_recursion.c rename to tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c index 64da74b757..0856eea230 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example + boundary check for simple recursion #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int a = 20; int f(int i) @@ -17,7 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - - // if the analysis runs fully context sensitive, "a" should be equal 0 __goblint_check(a == 0); } diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c similarity index 60% rename from tests/regression/80-context_gas/03_three_recursions.c rename to tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c index 1782887b61..558b7e436f 100644 --- a/tests/regression/80-context_gas/03_three_recursions.c +++ b/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly + boundary check for multiple recursions #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int f(int i) { @@ -50,7 +51,9 @@ int main(void) int res1 = f(num_iterat); int res2 = g(num_iterat); int res3 = h(num_iterat); - int result = res1 + res2 + res3; + int res4 = h(num_iterat); + int res5 = h(num_iterat); + int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 3); // context sensitive + __goblint_check(result == 5); } diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c similarity index 72% rename from tests/regression/80-context_gas/00-hardcoded_recursion.c rename to tests/regression/80-context_gas_sens/04-hardcoded_recursion.c index ec601d898b..d1ac462870 100644 --- a/tests/regression/80-context_gas/00-hardcoded_recursion.c +++ b/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if the context gas is reduced too much, due to the (not needed) function calls f(4) and f(3) #include -int num_iterat = 5; +int num_iterat = 2; int a = 20; int f(int i) diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas_sens/05-function_chain.c similarity index 76% rename from tests/regression/80-context_gas/06-function_chain.c rename to tests/regression/80-context_gas_sens/05-function_chain.c index d897d422bb..99b4f0a89d 100644 --- a/tests/regression/80-context_gas/06-function_chain.c +++ b/tests/regression/80-context_gas_sens/05-function_chain.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if Chain-Calls are handled properly #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int h(int i) { diff --git a/tests/regression/80-context_gas_sens/06-call_in_loop.c b/tests/regression/80-context_gas_sens/06-call_in_loop.c new file mode 100644 index 0000000000..92a751bf9d --- /dev/null +++ b/tests/regression/80-context_gas_sens/06-call_in_loop.c @@ -0,0 +1,31 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(num_iterat); + __goblint_check(res == 1); + result += res; + } + __goblint_check(result == 5); // TODO +} diff --git a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c new file mode 100644 index 0000000000..1a4dbfcebc --- /dev/null +++ b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c @@ -0,0 +1,29 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(i); + __goblint_check(res == 1); // TODO + result += res; + } + __goblint_check(result == 5); // TODO +} diff --git a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c new file mode 100644 index 0000000000..29fa50ee6e --- /dev/null +++ b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 2; // should be context gas value - 1 + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } + +} diff --git a/tests/regression/81-context_gas_insens/01-multiple_param_simple.c b/tests/regression/81-context_gas_insens/01-multiple_param_simple.c new file mode 100644 index 0000000000..9e6e4b870b --- /dev/null +++ b/tests/regression/81-context_gas_insens/01-multiple_param_simple.c @@ -0,0 +1,18 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example +int num_iterat = 100; + +int f(int x, int y) +{ + if (x == 0) + { + __goblint_check(y == 0); // UNKNOWN + return 0; + } + f(--x, --y); +} + +int main() +{ + f(num_iterat, num_iterat); +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c b/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c new file mode 100644 index 0000000000..4fd2156dc2 --- /dev/null +++ b/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example + boundary check for simple recursion +#include + +int num_iterat = 9; // should be context gas value - 1 +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); // UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c b/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c new file mode 100644 index 0000000000..ef678dc7ee --- /dev/null +++ b/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly + boundary check for multiple recursions +#include + +int num_iterat = 9; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + int result = res1 + res2 + res3 + res4 + res5; + + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/04-function_chain.c b/tests/regression/81-context_gas_insens/04-function_chain.c new file mode 100644 index 0000000000..04e2fa83b6 --- /dev/null +++ b/tests/regression/81-context_gas_insens/04-function_chain.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 9; // should be context gas value - 1 + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); // UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/05-ackermann.c b/tests/regression/81-context_gas_insens/05-ackermann.c new file mode 100644 index 0000000000..90187d5a9f --- /dev/null +++ b/tests/regression/81-context_gas_insens/05-ackermann.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// This code would result in a StackOverflow if it is analyses fully context sensitive +#include + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) { + ack (4,1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/06-call_in_loop.c b/tests/regression/81-context_gas_insens/06-call_in_loop.c new file mode 100644 index 0000000000..04545ab177 --- /dev/null +++ b/tests/regression/81-context_gas_insens/06-call_in_loop.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 1000; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + for (int i = num_iterat; i > 0; i--) + { + int result = f(i); + __goblint_check(result == 1); // UNKNOWN + } +} diff --git a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c new file mode 100644 index 0000000000..248515c7ae --- /dev/null +++ b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 20; // should be context gas value - 1 + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); //UNKNOWN + __goblint_check(res2 == 1); //UNKNOWN + } + +} diff --git a/tests/regression/81-context_gas_insens/08-loop_unrolling.c b/tests/regression/81-context_gas_insens/08-loop_unrolling.c new file mode 100644 index 0000000000..8a560cc689 --- /dev/null +++ b/tests/regression/81-context_gas_insens/08-loop_unrolling.c @@ -0,0 +1,39 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// TODO +#include + +int num_iterat = 3; + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int f(int i) +{ + if (i > 0) + { + for (; i >= 0; i--) + { + int res = g(i); + __goblint_check(res == 1); + return res; + } + } + return -1; +} + +int main(void) +{ + f(num_iterat); + return 0; +} From 80eee49e8d7bb33e5a3c7b7a3e1e3487cf713d36 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 23 Nov 2023 13:14:46 +0100 Subject: [PATCH 019/128] fixed indentation, added kCallstring module, just a first draft --- src/analyses/kCallsting.ml | 29 +++++++++++++++++++++++++++++ src/framework/constraints.ml | 8 ++++---- 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/analyses/kCallsting.ml diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallsting.ml new file mode 100644 index 0000000000..72a4d49468 --- /dev/null +++ b/src/analyses/kCallsting.ml @@ -0,0 +1,29 @@ +open GoblintCil +open Pretty +open GobPretty +open Analyses +open Cil + +module Spec (D: Lattice.S) : Analyses.MCPSpec = +struct + include Analyses.IdentitySpec + + module D = StackDomain.Dom1 + module C = StackDomain.Dom1 + + let name () = "k-callstring" + let startstate _ = D.bot () + let exitstate _ = D.bot () + + let concat_with_limit k d args = + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = k - List.length d in + let args_to_concat = take remaining_space args in + List.rev_append (List.rev args_to_concat) d + + +end \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index f2484f8be7..082622e9c0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -494,10 +494,10 @@ end module CGName = struct let name = "contextGas" end module IntConf = - struct - let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) - let names x = Format.asprintf "%d" x - end +struct + let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) + let names x = Format.asprintf "%d" x +end (** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) From df562206f754d3905c29f1822e013471e533b410 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 23 Nov 2023 18:56:35 +0100 Subject: [PATCH 020/128] added kCallstring to goblint_lib; fixed indentation --- src/analyses/kCallsting.ml | 6 ------ src/framework/control.ml | 40 +++++++++++++++++++------------------- src/goblint_lib.ml | 1 + 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallsting.ml index 72a4d49468..ec1641abff 100644 --- a/src/analyses/kCallsting.ml +++ b/src/analyses/kCallsting.ml @@ -1,8 +1,4 @@ -open GoblintCil -open Pretty -open GobPretty open Analyses -open Cil module Spec (D: Lattice.S) : Analyses.MCPSpec = struct @@ -24,6 +20,4 @@ struct let remaining_space = k - List.length d in let args_to_concat = take remaining_space args in List.rev_append (List.rev args_to_concat) d - - end \ No newline at end of file diff --git a/src/framework/control.ml b/src/framework/control.ml index 10ffa5e414..f0a55dc2f2 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,26 +20,26 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) in + (module MCP.MCP2 : Spec) + |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index cb18ad0dd7..a75e12564f 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -149,6 +149,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse module LoopTermination = LoopTermination +module KCallstring = KCallstring module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace From fe41d6b60f471d56f4690a29e23b8b310db8c8b9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 24 Nov 2023 09:45:07 +0100 Subject: [PATCH 021/128] fixed typo in file name; added new testcases; adapted existing ones --- .../{kCallsting.ml => kCallstring.ml} | 9 +++--- ...{06-call_in_loop.c => 06-loop_unrolling.c} | 4 ++- .../80-context_gas_sens/07-call_in_loop_adv.c | 2 ++ .../08-circle_call_and_loops.c | 3 +- .../80-context_gas_sens/09-main_recursion.c | 25 +++++++++++++++ .../81-context_gas_insens/04-function_chain.c | 1 + .../81-context_gas_insens/06-call_in_loop.c | 3 +- .../07-circle_call_and_loops.c | 4 +-- .../81-context_gas_insens/08-loop_unrolling.c | 32 +++++++------------ .../81-context_gas_insens/09-main_recursion.c | 24 ++++++++++++++ .../81-context_gas_insens/10-endless_loop.c | 24 ++++++++++++++ 11 files changed, 101 insertions(+), 30 deletions(-) rename src/analyses/{kCallsting.ml => kCallstring.ml} (70%) rename tests/regression/80-context_gas_sens/{06-call_in_loop.c => 06-loop_unrolling.c} (81%) create mode 100644 tests/regression/80-context_gas_sens/09-main_recursion.c create mode 100644 tests/regression/81-context_gas_insens/09-main_recursion.c create mode 100644 tests/regression/81-context_gas_insens/10-endless_loop.c diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallstring.ml similarity index 70% rename from src/analyses/kCallsting.ml rename to src/analyses/kCallstring.ml index ec1641abff..aea2a5ce91 100644 --- a/src/analyses/kCallsting.ml +++ b/src/analyses/kCallstring.ml @@ -1,17 +1,18 @@ open Analyses +open GoblintCil -module Spec (D: Lattice.S) : Analyses.MCPSpec = +module Spec : Analyses.MCPSpec = struct include Analyses.IdentitySpec module D = StackDomain.Dom1 module C = StackDomain.Dom1 - let name () = "k-callstring" + let name () = "k callstring" let startstate _ = D.bot () let exitstate _ = D.bot () - let concat_with_limit k d args = + (*let concat_with_limit k d args = let rec take n = function | [] -> [] | x :: xs when n > 0 -> x :: take (n - 1) xs @@ -19,5 +20,5 @@ struct in let remaining_space = k - List.length d in let args_to_concat = take remaining_space args in - List.rev_append (List.rev args_to_concat) d + List.rev_append (List.rev args_to_concat) d*) end \ No newline at end of file diff --git a/tests/regression/80-context_gas_sens/06-call_in_loop.c b/tests/regression/80-context_gas_sens/06-loop_unrolling.c similarity index 81% rename from tests/regression/80-context_gas_sens/06-call_in_loop.c rename to tests/regression/80-context_gas_sens/06-loop_unrolling.c index 92a751bf9d..63c29e6a47 100644 --- a/tests/regression/80-context_gas_sens/06-call_in_loop.c +++ b/tests/regression/80-context_gas_sens/06-loop_unrolling.c @@ -1,4 +1,6 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if recursion in loops are handled properly + loop unrolling +// TODO #include int num_iterat = 3; diff --git a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c index 1a4dbfcebc..d395229ea4 100644 --- a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c +++ b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c @@ -1,4 +1,6 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if recursion in loop is handled properly + iterator variable = function parameter +// TODO #include int f(int i) diff --git a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c index 29fa50ee6e..a0ff11c4da 100644 --- a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c +++ b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if recursion in loops is handled properly #include -int num_iterat = 2; // should be context gas value - 1 +int num_iterat = 2; int f(int i); diff --git a/tests/regression/80-context_gas_sens/09-main_recursion.c b/tests/regression/80-context_gas_sens/09-main_recursion.c new file mode 100644 index 0000000000..22b48103fa --- /dev/null +++ b/tests/regression/80-context_gas_sens/09-main_recursion.c @@ -0,0 +1,25 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if only recursion in main works properly + boundary check +// TODO +#include + +int num_iterat = 11; // WHY is context gas value + 1 the limit??? + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat--; + int res = main(); + __goblint_check(res == 5); + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} diff --git a/tests/regression/81-context_gas_insens/04-function_chain.c b/tests/regression/81-context_gas_insens/04-function_chain.c index 04e2fa83b6..1cafd8086e 100644 --- a/tests/regression/81-context_gas_insens/04-function_chain.c +++ b/tests/regression/81-context_gas_insens/04-function_chain.c @@ -1,4 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if function chains are handled properly + boundary check #include int num_iterat = 9; // should be context gas value - 1 diff --git a/tests/regression/81-context_gas_insens/06-call_in_loop.c b/tests/regression/81-context_gas_insens/06-call_in_loop.c index 04545ab177..9a4f139fb8 100644 --- a/tests/regression/81-context_gas_insens/06-call_in_loop.c +++ b/tests/regression/81-context_gas_insens/06-call_in_loop.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks proper handling of recursion in loops + iterator variable = function parameter #include -int num_iterat = 1000; // should be context gas value - 1 +int num_iterat = 1000; int f(int i) { diff --git a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c index 248515c7ae..8b8e1b7bc7 100644 --- a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c +++ b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks proper handling of recursions in loops #include -int num_iterat = 20; // should be context gas value - 1 +int num_iterat = 20; int f(int i); @@ -44,5 +45,4 @@ int main(void) __goblint_check(res1 == 2); //UNKNOWN __goblint_check(res2 == 1); //UNKNOWN } - } diff --git a/tests/regression/81-context_gas_insens/08-loop_unrolling.c b/tests/regression/81-context_gas_insens/08-loop_unrolling.c index 8a560cc689..8ba865cc98 100644 --- a/tests/regression/81-context_gas_insens/08-loop_unrolling.c +++ b/tests/regression/81-context_gas_insens/08-loop_unrolling.c @@ -1,39 +1,29 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 -// TODO +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if loop unrolling makes a difference for the analysis #include -int num_iterat = 3; +int num_iterat = 20; -int g(int i) +int f(int i) { int res = 0; if (i == 0) { - res = 1; + res = 2; } if (i > 0) { - res = g(--i); + res = f(--i); } return res; } -int f(int i) +int main(void) { - if (i > 0) + for (int i = 5; i > 0; i--) { - for (; i >= 0; i--) - { - int res = g(i); - __goblint_check(res == 1); - return res; - } + int res = f(num_iterat); + __goblint_check(res == 2); //UNKNOWN } - return -1; -} -int main(void) -{ - f(num_iterat); - return 0; -} +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/09-main_recursion.c b/tests/regression/81-context_gas_insens/09-main_recursion.c new file mode 100644 index 0000000000..7cf6a52e74 --- /dev/null +++ b/tests/regression/81-context_gas_insens/09-main_recursion.c @@ -0,0 +1,24 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Without context insensitive analysis: Stack Overflow +#include + +int num_iterat = 200000; + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat--; + int res = main(); + __goblint_check(res == 5); //UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} diff --git a/tests/regression/81-context_gas_insens/10-endless_loop.c b/tests/regression/81-context_gas_insens/10-endless_loop.c new file mode 100644 index 0000000000..40e7b9941e --- /dev/null +++ b/tests/regression/81-context_gas_insens/10-endless_loop.c @@ -0,0 +1,24 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis +#include + +int num_iterat = 2; + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat ++; + int res = main(); + __goblint_check(res == 5); //UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} From 432bd1eefaa34370378bd330e45019babaafa762 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 11:18:30 +0100 Subject: [PATCH 022/128] deleted kCallstring, created new Callstring Lifter, added new testcases for callstring and for context gas --- src/analyses/kCallstring.ml | 24 - src/common/util/options.schema.json | 687 ++++++++++-------- src/framework/constraints.ml | 90 +++ src/framework/control.ml | 1 + src/goblint_lib.ml | 1 - .../80-context_gas_sens/10-call_in_call.c | 55 ++ .../81-context_gas_insens/10-call_in_call.c | 55 ++ .../regression/82-callstring/01-simple_rec.c | 21 + .../82-callstring/02-multiple_rec.c | 56 ++ .../82-callstring/03-function_chain.c | 52 ++ 10 files changed, 730 insertions(+), 312 deletions(-) delete mode 100644 src/analyses/kCallstring.ml create mode 100644 tests/regression/80-context_gas_sens/10-call_in_call.c create mode 100644 tests/regression/81-context_gas_insens/10-call_in_call.c create mode 100644 tests/regression/82-callstring/01-simple_rec.c create mode 100644 tests/regression/82-callstring/02-multiple_rec.c create mode 100644 tests/regression/82-callstring/03-function_chain.c diff --git a/src/analyses/kCallstring.ml b/src/analyses/kCallstring.ml deleted file mode 100644 index aea2a5ce91..0000000000 --- a/src/analyses/kCallstring.ml +++ /dev/null @@ -1,24 +0,0 @@ -open Analyses -open GoblintCil - -module Spec : Analyses.MCPSpec = -struct - include Analyses.IdentitySpec - - module D = StackDomain.Dom1 - module C = StackDomain.Dom1 - - let name () = "k callstring" - let startstate _ = D.bot () - let exitstate _ = D.bot () - - (*let concat_with_limit k d args = - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = k - List.length d in - let args_to_concat = take remaining_space args in - List.rev_append (List.rev args_to_concat) d*) -end \ No newline at end of file diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 25efdfef57..8e16dbda68 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -31,8 +31,7 @@ }, "verify": { "title": "verify", - "description": - "Verify that the solver reached a post-fixpoint. Beware that disabling this also disables output of warnings since post-processing of the results is done in the verification phase!", + "description": "Verify that the solver reached a post-fixpoint. Beware that disabling this also disables output of warnings since post-processing of the results is done in the verification phase!", "type": "boolean", "default": true }, @@ -40,27 +39,34 @@ "title": "mainfun", "description": "Sets the name of the main functions.", "type": "array", - "items": { "type": "string" }, - "default": [ "main" ] + "items": { + "type": "string" + }, + "default": [ + "main" + ] }, "exitfun": { "title": "exitfun", "description": "Sets the name of the cleanup functions.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "otherfun": { "title": "otherfun", "description": "Sets the name of other functions.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "allglobs": { "title": "allglobs", - "description": - "Prints access information about all globals, not just races.", + "description": "Prints access information about all globals, not just races.", "type": "boolean", "default": false }, @@ -78,10 +84,16 @@ }, "result": { "title": "result", - "description": - "Result style: none, fast_xml, json, pretty, json-messages, sarif.", + "description": "Result style: none, fast_xml, json, pretty, json-messages, sarif.", "type": "string", - "enum": ["none", "fast_xml", "json", "pretty", "json-messages", "sarif"], + "enum": [ + "none", + "fast_xml", + "json", + "pretty", + "json-messages", + "sarif" + ], "default": "none" }, "solver": { @@ -98,8 +110,7 @@ }, "allfuns": { "title": "allfuns", - "description": - "Analyzes all the functions (not just beginning from main). This requires exp.earlyglobs!", + "description": "Analyzes all the functions (not just beginning from main). This requires exp.earlyglobs!", "type": "boolean", "default": false }, @@ -111,10 +122,13 @@ }, "colors": { "title": "colors", - "description": - "Colored output (via ANSI escape codes). 'auto': enabled if stdout is a terminal (instead of a pipe); 'always', 'never'.", + "description": "Colored output (via ANSI escape codes). 'auto': enabled if stdout is a terminal (instead of a pipe); 'always', 'never'.", "type": "string", - "enum": ["auto", "always", "never"], + "enum": [ + "auto", + "always", + "never" + ], "default": "auto" }, "g2html": { @@ -125,8 +139,7 @@ }, "save_run": { "title": "save_run", - "description": - "Save the result of the solver, the current configuration and meta-data about the run to this directory (if set). The data can then be loaded (without solving again) to do post-processing like generating output in a different format or comparing results.", + "description": "Save the result of the solver, the current configuration and meta-data about the run to this directory (if set). The data can then be loaded (without solving again) to do post-processing like generating output in a different format or comparing results.", "type": "string", "default": "" }, @@ -138,24 +151,27 @@ }, "compare_runs": { "title": "compare_runs", - "description": - "Load these saved runs and compare the results. Note that currently only two runs can be compared!", + "description": "Load these saved runs and compare the results. Note that currently only two runs can be compared!", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "warn_at": { "title": "warn_at", - "description": - "When to output warnings. Values: 'post' (default): after solving; 'never': no warnings; 'early': for debugging - outputs warnings already while solving (may lead to spurious warnings/asserts that would disappear after narrowing).", + "description": "When to output warnings. Values: 'post' (default): after solving; 'never': no warnings; 'early': for debugging - outputs warnings already while solving (may lead to spurious warnings/asserts that would disappear after narrowing).", "type": "string", - "enum": ["post", "never", "early"], + "enum": [ + "post", + "never", + "early" + ], "default": "post" }, "gobview": { "title": "gobview", - "description": - "Include additional information for GobView (e.g., the Goblint warning messages) in the directory specified by 'save_run'.", + "description": "Include additional information for GobView (e.g., the Goblint warning messages) in the directory specified by 'save_run'.", "type": "boolean", "default": false }, @@ -184,8 +200,7 @@ }, "keep": { "title": "pre.keep", - "description": - "Keep the intermediate output of running the C preprocessor.", + "description": "Keep the intermediate output of running the C preprocessor.", "type": "boolean", "default": false }, @@ -199,21 +214,27 @@ "title": "pre.includes", "description": "List of directories to include.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "kernel_includes": { "title": "pre.kernel_includes", "description": "List of kernel directories to include.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "custom_includes": { "title": "pre.custom_includes", "description": "List of custom directories to include.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "kernel-root": { @@ -226,7 +247,9 @@ "title": "pre.cppflags", "description": "Pre-processing parameters.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "compdb": { @@ -235,8 +258,7 @@ "properties": { "original-path": { "title": "pre.compdb.original-path", - "description": - "Original absolute path of Compilation Database. Used to reroot all absolute paths in there if moved, e.g. in container mounts.", + "description": "Original absolute path of Compilation Database. Used to reroot all absolute paths in there if moved, e.g. in container mounts.", "type": "string", "default": "" }, @@ -281,7 +303,11 @@ "type": "string", "description": "Specify the c standard used for parsing.", "default": "c99", - "enum": ["c90", "c99", "c11"] + "enum": [ + "c90", + "c99", + "c11" + ] }, "gnu89inline": { "title": "cil.gnu89inline", @@ -313,7 +339,10 @@ "title": "server.mode", "description": "Server transport mode", "type": "string", - "enum": ["stdio", "unix"], + "enum": [ + "stdio", + "unix" + ], "default": "stdio" }, "unix-socket": { @@ -340,10 +369,22 @@ "title": "ana.activated", "description": "Lists of activated analyses.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [ - "expRelation", "base", "threadid", "threadflag", "threadreturn", - "escape", "mutexEvents", "mutex", "access", "race", "mallocWrapper", "mhp", + "expRelation", + "base", + "threadid", + "threadflag", + "threadreturn", + "escape", + "mutexEvents", + "mutex", + "access", + "race", + "mallocWrapper", + "mhp", "assert" ] }, @@ -351,17 +392,31 @@ "title": "ana.path_sens", "description": "List of path-sensitive analyses", "type": "array", - "items": { "type": "string" }, - "default": [ "mutex", "malloc_null", "uninit", "expsplit","activeSetjmp","memLeak" ] + "items": { + "type": "string" + }, + "default": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak" + ] }, "ctx_insens": { "title": "ana.ctx_insens", "description": "List of context-insensitive analyses", "type": "array", - "items": { "type": "string" }, - "default": [ "stack_loc", "stack_trace_set" ] + "items": { + "type": "string" + }, + "default": [ + "stack_loc", + "stack_trace_set" + ] }, - "setjmp" : { + "setjmp": { "title": "ana.setjmp", "description": "Setjmp/Longjmp analysis", "type": "object", @@ -370,7 +425,11 @@ "title": "ana.setjmp.split", "description": "Split returns of setjmp", "type": "string", - "enum": ["none", "coarse", "precise"], + "enum": [ + "none", + "coarse", + "precise" + ], "default": "precise" } }, @@ -382,15 +441,13 @@ "properties": { "def_exc": { "title": "ana.int.def_exc", - "description": - "Use IntDomain.DefExc: definite value/exclusion set.", + "description": "Use IntDomain.DefExc: definite value/exclusion set.", "type": "boolean", "default": true }, "interval": { "title": "ana.int.interval", - "description": - "Use IntDomain.Interval32: (Z.t * Z.t) option.", + "description": "Use IntDomain.Interval32: (Z.t * Z.t) option.", "type": "boolean", "default": false }, @@ -402,30 +459,30 @@ }, "enums": { "title": "ana.int.enums", - "description": - "Use IntDomain.Enums: Inclusion/Exclusion sets. Go to top on arithmetic operations (except for some easy cases, e.g. multiplication with 0). Joins on widen, i.e. precise integers as long as not derived from arithmetic expressions.", + "description": "Use IntDomain.Enums: Inclusion/Exclusion sets. Go to top on arithmetic operations (except for some easy cases, e.g. multiplication with 0). Joins on widen, i.e. precise integers as long as not derived from arithmetic expressions.", "type": "boolean", "default": false }, "congruence": { "title": "ana.int.congruence", - "description": - "Use IntDomain.Congruence: (c, m) option, meaning congruent to c modulo m", + "description": "Use IntDomain.Congruence: (c, m) option, meaning congruent to c modulo m", "type": "boolean", "default": false }, "refinement": { "title": "ana.int.refinement", - "description": - "Use mutual refinement of integer domains. Either 'never', 'once' or 'fixpoint'. Counterintuitively, may reduce precision unless ana.int.interval_narrow_by_meet is also enabled.", + "description": "Use mutual refinement of integer domains. Either 'never', 'once' or 'fixpoint'. Counterintuitively, may reduce precision unless ana.int.interval_narrow_by_meet is also enabled.", "type": "string", - "enum": ["never", "once", "fixpoint"], + "enum": [ + "never", + "once", + "fixpoint" + ], "default": "never" }, "def_exc_widen_by_join": { "title": "ana.int.def_exc_widen_by_join", - "description": - "Perform def_exc widening by joins. Gives threshold-widening like behavior, with thresholds given by the ranges of different integer types.", + "description": "Perform def_exc widening by joins. Gives threshold-widening like behavior, with thresholds given by the ranges of different integer types.", "type": "boolean", "default": false }, @@ -437,17 +494,18 @@ }, "interval_threshold_widening": { "title": "ana.int.interval_threshold_widening", - "description": - "Use constants appearing in program as threshold for widening", + "description": "Use constants appearing in program as threshold for widening", "type": "boolean", "default": false }, "interval_threshold_widening_constants": { "title": "ana.int.interval_threshold_widening_constants", - "description": - "Which constants in the program should be considered as threshold constants (all/comparisons)", + "description": "Which constants in the program should be considered as threshold constants (all/comparisons)", "type": "string", - "enum": ["all", "comparisons"], + "enum": [ + "all", + "comparisons" + ], "default": "all" } }, @@ -459,8 +517,7 @@ "properties": { "interval": { "title": "ana.float.interval", - "description": - "Use FloatDomain: (float * float) option.", + "description": "Use FloatDomain: (float * float) option.", "type": "boolean", "default": false } @@ -499,8 +556,7 @@ "properties": { "debug": { "title": "ana.pml.debug", - "description": - "Insert extra assertions into Promela code for debugging.", + "description": "Insert extra assertions into Promela code for debugging.", "type": "boolean", "default": true } @@ -513,15 +569,13 @@ "properties": { "hashcons": { "title": "ana.opt.hashcons", - "description": - "Should we try to save memory and speed up equality by hashconsing?", + "description": "Should we try to save memory and speed up equality by hashconsing?", "type": "boolean", "default": true }, "equal": { "title": "ana.opt.equal", - "description": - "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", + "description": "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true } @@ -542,9 +596,22 @@ "title": "ana.autotune.activated", "description": "Lists of activated tuning options.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [ - "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds", "memsafetySpecification", "tmpSpecialAnalysis" + "congruence", + "singleThreaded", + "specification", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "loopUnrollHeuristic", + "arrayDomain", + "octagon", + "wideningThresholds", + "memsafetySpecification", + "tmpSpecialAnalysis" ] } }, @@ -577,8 +644,7 @@ }, "wp": { "title": "ana.wp", - "description": - "Weakest precondition feasibility analysis for SV-COMP violations", + "description": "Weakest precondition feasibility analysis for SV-COMP violations", "type": "boolean", "default": false }, @@ -610,15 +676,13 @@ }, "interval": { "title": "ana.base.context.interval", - "description": - "Integer values of the Interval domain in function contexts.", + "description": "Integer values of the Interval domain in function contexts.", "type": "boolean", "default": true }, "interval_set": { "title": "ana.base.context.interval_set", - "description": - "Integer values of the IntervalSet domain in function contexts.", + "description": "Integer values of the IntervalSet domain in function contexts.", "type": "boolean", "default": true } @@ -637,39 +701,42 @@ "properties": { "keep-expr": { "title": "ana.base.partition-arrays.keep-expr", - "description": - "When using the partitioning which expression should be used for partitioning ('first', 'last')", + "description": "When using the partitioning which expression should be used for partitioning ('first', 'last')", "type": "string", - "enum": ["first", "last"], + "enum": [ + "first", + "last" + ], "default": "first" }, "partition-by-const-on-return": { "title": "ana.base.partition-arrays.partition-by-const-on-return", - "description": - "When using the partitioning should arrays be considered partitioned according to a constant if a var in the expression used for partitioning goes out of scope?", + "description": "When using the partitioning should arrays be considered partitioned according to a constant if a var in the expression used for partitioning goes out of scope?", "type": "boolean", "default": false }, "smart-join": { "title": "ana.base.partition-arrays.smart-join", - "description": - "When using the partitioning should the join of two arrays partitioned according to different expressions be partitioned as well if possible? If keep-expr is 'last' this behavior is enabled regardless of the flag value. Caution: Not always advantageous.", + "description": "When using the partitioning should the join of two arrays partitioned according to different expressions be partitioned as well if possible? If keep-expr is 'last' this behavior is enabled regardless of the flag value. Caution: Not always advantageous.", "type": "boolean", "default": false } }, "additionalProperties": false }, - "arrays":{ + "arrays": { "title": "ana.base.arrays", "type": "object", "properties": { "domain": { "title": "ana.base.arrays.domain", - "description": - "The domain that should be used for arrays. When employing the partition array domain, make sure to enable the expRelation analysis as well. When employing the unrolling array domain, make sure to set the ana.base.arrays.unrolling-factor >0.", + "description": "The domain that should be used for arrays. When employing the partition array domain, make sure to enable the expRelation analysis as well. When employing the unrolling array domain, make sure to set the ana.base.arrays.unrolling-factor >0.", "type": "string", - "enum": ["trivial", "partitioned", "unroll"], + "enum": [ + "trivial", + "partitioned", + "unroll" + ], "default": "trivial" }, "unrolling-factor": { @@ -687,10 +754,15 @@ "properties": { "domain": { "title": "ana.base.structs.domain", - "description": - "The domain that should be used for structs. simple/sets/keyed/combined-all/combined-sk", + "description": "The domain that should be used for structs. simple/sets/keyed/combined-all/combined-sk", "type": "string", - "enum": ["simple", "sets", "keyed", "combined-all", "combined-sk"], + "enum": [ + "simple", + "sets", + "keyed", + "combined-all", + "combined-sk" + ], "default": "simple" }, "key": { @@ -699,22 +771,19 @@ "properties": { "forward": { "title": "ana.base.structs.key.forward", - "description": - "Whether the struct key should be picked going from first field to last.", + "description": "Whether the struct key should be picked going from first field to last.", "type": "boolean", "default": true }, "avoid-ints": { "title": "ana.base.structs.key.avoid-ints", - "description": - "Whether integers should be avoided for key.", + "description": "Whether integers should be avoided for key.", "type": "boolean", "default": true }, "prefer-ptrs": { "title": "ana.base.structs.key.prefer-ptrs", - "description": - "Whether pointers should be preferred for key.", + "description": "Whether pointers should be preferred for key.", "type": "boolean", "default": true } @@ -726,10 +795,23 @@ }, "privatization": { "title": "ana.base.privatization", - "description": - "Which privatization to use? none/mutex-oplus/mutex-meet/mutex-meet-tid/protection/protection-read/mine/mine-nothread/mine-W/mine-W-noinit/lock/write/write+lock", + "description": "Which privatization to use? none/mutex-oplus/mutex-meet/mutex-meet-tid/protection/protection-read/mine/mine-nothread/mine-W/mine-W-noinit/lock/write/write+lock", "type": "string", - "enum": ["none", "mutex-oplus", "mutex-meet", "protection", "protection-read", "mine", "mine-nothread", "mine-W", "mine-W-noinit", "lock", "write", "write+lock","mutex-meet-tid"], + "enum": [ + "none", + "mutex-oplus", + "mutex-meet", + "protection", + "protection-read", + "mine", + "mine-nothread", + "mine-W", + "mine-W-noinit", + "lock", + "write", + "write+lock", + "mutex-meet-tid" + ], "default": "protection-read" }, "priv": { @@ -738,15 +820,13 @@ "properties": { "not-started": { "title": "ana.base.priv.not-started", - "description": - "Exclude writes from threads that may not be started yet", + "description": "Exclude writes from threads that may not be started yet", "type": "boolean", "default": true }, "must-joined": { "title": "ana.base.priv.must-joined", - "description": - "Exclude writes from threads that must have been joined", + "description": "Exclude writes from threads that must have been joined", "type": "boolean", "default": true } @@ -773,7 +853,10 @@ "title": "ana.base.invariant.unassume", "description": "How many times to unassume an invariant: once or until fixpoint (at least twice as expensive).", "type": "string", - "enum": ["once", "fixpoint"], + "enum": [ + "once", + "fixpoint" + ], "default": "once" } }, @@ -801,20 +884,24 @@ "properties": { "wrappers": { "title": "ana.malloc.wrappers", - "description": - "Loads a list of known malloc wrapper functions.", + "description": "Loads a list of known malloc wrapper functions.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [ - "kmalloc", "__kmalloc", "usb_alloc_urb", "__builtin_alloca", + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", "kzalloc" ] }, "unique_address_count": { - "title": "ana.malloc.unique_address_count", - "description": "Number of unique memory addresses allocated for each malloc node.", - "type": "integer", - "default": 0 + "title": "ana.malloc.unique_address_count", + "description": "Number of unique memory addresses allocated for each malloc node.", + "type": "integer", + "default": 0 } }, "additionalProperties": false @@ -831,25 +918,30 @@ }, "domain": { "title": "ana.apron.domain", - "description": - "Which domain should be used for the Apron analysis. Can be 'octagon', 'interval' or 'polyhedra'", + "description": "Which domain should be used for the Apron analysis. Can be 'octagon', 'interval' or 'polyhedra'", "type": "string", - "enum": ["octagon", "interval", "polyhedra", "affeq"], + "enum": [ + "octagon", + "interval", + "polyhedra", + "affeq" + ], "default": "octagon" }, "threshold_widening": { "title": "ana.apron.threshold_widening", - "description": - "Use constants appearing in program as threshold for widening", + "description": "Use constants appearing in program as threshold for widening", "type": "boolean", "default": false }, "threshold_widening_constants": { "title": "ana.apron.threshold_widening_constants", - "description": - "Which constants in the programm should be considered as threshold constants", + "description": "Which constants in the programm should be considered as threshold constants", "type": "string", - "enum": ["all", "comparisons"], + "enum": [ + "all", + "comparisons" + ], "default": "all" }, "invariant": { @@ -880,10 +972,19 @@ }, "privatization": { "title": "ana.relation.privatization", - "description": - "Which relation privatization to use? top/protection/protection-path/mutex-meet/mutex-meet-tid/mutex-meet-tid-cluster12/mutex-meet-tid-cluster2/mutex-meet-tid-cluster-max/mutex-meet-tid-cluster-power", + "description": "Which relation privatization to use? top/protection/protection-path/mutex-meet/mutex-meet-tid/mutex-meet-tid-cluster12/mutex-meet-tid-cluster2/mutex-meet-tid-cluster-max/mutex-meet-tid-cluster-power", "type": "string", - "enum": ["top", "protection", "protection-path", "mutex-meet", "mutex-meet-tid", "mutex-meet-tid-cluster12", "mutex-meet-tid-cluster2", "mutex-meet-tid-cluster-max", "mutex-meet-tid-cluster-power"], + "enum": [ + "top", + "protection", + "protection-path", + "mutex-meet", + "mutex-meet-tid", + "mutex-meet-tid-cluster12", + "mutex-meet-tid-cluster2", + "mutex-meet-tid-cluster-max", + "mutex-meet-tid-cluster-power" + ], "default": "mutex-meet" }, "priv": { @@ -892,15 +993,13 @@ "properties": { "not-started": { "title": "ana.relation.priv.not-started", - "description": - "Exclude writes from threads that may not be started yet", + "description": "Exclude writes from threads that may not be started yet", "type": "boolean", "default": true }, "must-joined": { "title": "ana.relation.priv.must-joined", - "description": - "Exclude writes from threads that must have been joined", + "description": "Exclude writes from threads that must have been joined", "type": "boolean", "default": true } @@ -941,15 +1040,19 @@ "properties": { "widen": { "title": "ana.context.widen", - "description": - "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", + "description": "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", "type": "boolean", "default": false - }, + }, "ctx_gas": { "title": "ana.context.ctx_gas", - "description": - "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false + }, + "callstring": { + "title": "ana.context.callstring", + "description": "If enabled, the last k elements of the callstack are used as context", "type": "boolean", "default": false } @@ -962,25 +1065,27 @@ "properties": { "domain": { "title": "ana.thread.domain", - "description": - "Which domain should be used for the thread ids. Can be 'history' or 'plain'", + "description": "Which domain should be used for the thread ids. Can be 'history' or 'plain'", "type": "string", - "enum": ["history", "plain"], + "enum": [ + "history", + "plain" + ], "default": "history" }, - "include-node" : { + "include-node": { "title": "ana.thread.include-node", - "description": - "Whether the node at which a thread is created is part of its threadid", + "description": "Whether the node at which a thread is created is part of its threadid", "type": "boolean", - "default" : true + "default": true }, "wrappers": { "title": "ana.thread.wrappers", - "description": - "Loads a list of known thread spawn (pthread_create) wrapper functions.", + "description": "Loads a list of known thread spawn (pthread_create) wrapper functions.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "unique_thread_id_count": { @@ -1021,7 +1126,7 @@ "type": "boolean", "default": false }, - "volatile" :{ + "volatile": { "title": "ana.race.volatile", "description": "Report races for volatile variables.", "type": "boolean", @@ -1030,7 +1135,7 @@ }, "additionalProperties": false }, - "dead-code" : { + "dead-code": { "title": "ana.dead-code", "type": "object", "properties": { @@ -1055,7 +1160,7 @@ }, "additionalProperties": false }, - "extract-pthread" : { + "extract-pthread": { "title": "ana.extract-pthread", "type": "object", "properties": { @@ -1110,8 +1215,7 @@ "properties": { "load": { "title": "incremental.load", - "description": - "Load incremental analysis results, in case any exist.", + "description": "Load incremental analysis results, in case any exist.", "type": "boolean", "default": false }, @@ -1123,8 +1227,7 @@ }, "only-rename": { "title": "incremental.only-rename", - "description": - "Only reset IDs of unchanged objects in the AST. Do not reuse solver results. This option is mainly useful for benchmarking purposes.", + "description": "Only reset IDs of unchanged objects in the AST. Do not reuse solver results. This option is mainly useful for benchmarking purposes.", "type": "boolean", "default": false }, @@ -1142,15 +1245,13 @@ }, "stable": { "title": "incremental.stable", - "description": - "Reuse the stable set and selectively destabilize it (recommended).", + "description": "Reuse the stable set and selectively destabilize it (recommended).", "type": "boolean", "default": true }, "wpoint": { "title": "incremental.wpoint", - "description": - "Reuse the wpoint set (not recommended). Reusing the wpoint will combine existing results at previous widening points.", + "description": "Reuse the wpoint set (not recommended). Reusing the wpoint will combine existing results at previous widening points.", "type": "boolean", "default": false }, @@ -1160,8 +1261,7 @@ "properties": { "enabled": { "title": "incremental.reluctant.enabled", - "description": - "Destabilize nodes in changed functions reluctantly", + "description": "Destabilize nodes in changed functions reluctantly", "type": "boolean", "default": false } @@ -1170,16 +1270,18 @@ }, "compare": { "title": "incremental.compare", - "description": - "Which comparison should be used for functions? 'ast'/'cfg' (cfg comparison also differentiates which nodes of a function have changed)", + "description": "Which comparison should be used for functions? 'ast'/'cfg' (cfg comparison also differentiates which nodes of a function have changed)", "type": "string", - "enum": ["ast", "cfg"], + "enum": [ + "ast", + "cfg" + ], "default": "ast" }, "detect-renames": { "title": "incremental.detect-renames", "description": "If Goblint should try to detect renamed local variables, function parameters, functions and global variables", - "type":"boolean", + "type": "boolean", "default": true }, "force-reanalyze": { @@ -1188,8 +1290,7 @@ "properties": { "funs": { "title": "incremental.force-reanalyze.funs", - "description": - "List of functions that are to be re-analayzed from scratch", + "description": "List of functions that are to be re-analayzed from scratch", "type": "array", "items": { "type": "string" @@ -1217,7 +1318,11 @@ "title": "incremental.restart.sided.vars", "description": "Side-effected variables to restart. Globals are non-function entry nodes. Write-only is a subset of globals.", "type": "string", - "enum": ["all", "global", "write-only"], + "enum": [ + "all", + "global", + "write-only" + ], "default": "all" }, "fuel": { @@ -1255,7 +1360,7 @@ }, "postsolver": { "title": "incremental.postsolver", - "type" : "object", + "type": "object", "properties": { "enabled": { "title": "incremental.postsolver.enabled", @@ -1263,8 +1368,8 @@ "type": "boolean", "default": true }, - "superstable-reached" : { - "title": "incremental.postsolver.superstable-reached", + "superstable-reached": { + "title": "incremental.postsolver.superstable-reached", "description": "Consider superstable set reached, may be faster but can lead to spurious warnings", "type": "boolean", "default": false @@ -1328,15 +1433,13 @@ "properties": { "spawn": { "title": "sem.unknown_function.spawn", - "description": - "Unknown function call spawns reachable functions", + "description": "Unknown function call spawns reachable functions", "type": "boolean", "default": true }, "call": { "title": "sem.unknown_function.call", - "description": - "Unknown function call calls reachable functions", + "description": "Unknown function call calls reachable functions", "type": "boolean", "default": true }, @@ -1346,15 +1449,13 @@ "properties": { "globals": { "title": "sem.unknown_function.invalidate.globals", - "description": - "Unknown function call invalidates all globals", + "description": "Unknown function call invalidates all globals", "type": "boolean", "default": true }, "args": { "title": "sem.unknown_function.invalidate.args", - "description": - "Unknown function call invalidates arguments passed to it", + "description": "Unknown function call invalidates arguments passed to it", "type": "boolean", "default": true } @@ -1367,8 +1468,7 @@ "properties": { "args": { "title": "sem.unknown_function.read.args", - "description": - "Unknown function call reads arguments passed to it", + "description": "Unknown function call reads arguments passed to it", "type": "boolean", "default": true } @@ -1384,8 +1484,7 @@ "properties": { "dead_code": { "title": "sem.builtin_unreachable.dead_code", - "description": - "__builtin_unreachable is assumed to be dead code", + "description": "__builtin_unreachable is assumed to be dead code", "type": "boolean", "default": false } @@ -1399,8 +1498,7 @@ "properties": { "dead_code": { "title": "sem.noreturn.dead_code", - "description": - "For the purposes of detecting dead code, assume that functions marked noreturn don't return.", + "description": "For the purposes of detecting dead code, assume that functions marked noreturn don't return.", "type": "boolean", "default": false } @@ -1413,10 +1511,13 @@ "properties": { "signed_overflow": { "title": "sem.int.signed_overflow", - "description": - "How to handle overflows of signed types. Values: 'assume_top' (default): Assume signed overflow results in a top value; 'assume_none': Assume program is free of signed overflows; 'assume_wraparound': Assume signed types wrap-around and two's complement representation of signed integers", + "description": "How to handle overflows of signed types. Values: 'assume_top' (default): Assume signed overflow results in a top value; 'assume_none': Assume program is free of signed overflows; 'assume_wraparound': Assume signed types wrap-around and two's complement representation of signed integers", "type": "string", - "enum": ["assume_top", "assume_none", "assume_wraparound"], + "enum": [ + "assume_top", + "assume_none", + "assume_wraparound" + ], "default": "assume_top" } }, @@ -1430,7 +1531,10 @@ "title": "sem.null-pointer.dereference", "description": "NULL pointer dereference handling. assume_top: assume it results in a top value, assume_none: assume it doesn't happen", "type": "string", - "enum": ["assume_top", "assume_none"], + "enum": [ + "assume_top", + "assume_none" + ], "default": "assume_none" } }, @@ -1442,8 +1546,7 @@ "properties": { "fail": { "title": "sem.malloc.fail", - "description": - "Consider the case where malloc or calloc fails.", + "description": "Consider the case where malloc or calloc fails.", "type": "boolean", "default": false } @@ -1456,8 +1559,7 @@ "properties": { "fail": { "title": "sem.lock.fail", - "description": - "Takes the possible failing of locking operations into account.", + "description": "Takes the possible failing of locking operations into account.", "type": "boolean", "default": false } @@ -1487,12 +1589,16 @@ "properties": { "activated": { "title": "trans.activated", - "description": - "Lists of activated transformations. Transformations happen after analyses.", + "description": "Lists of activated transformations. Transformations happen after analyses.", "type": "array", "items": { "type": "string", - "enum": ["partial", "expeval", "assert", "remove_dead_code"] + "enum": [ + "partial", + "expeval", + "assert", + "remove_dead_code" + ] }, "default": [] }, @@ -1502,18 +1608,17 @@ "properties": { "query_file_name": { "title": "trans.expeval.query_file_name", - "description": - "Path to the JSON file containing an expression evaluation query.", + "description": "Path to the JSON file containing an expression evaluation query.", "type": "string", "default": "" } }, "additionalProperties": false }, - "output" : { + "output": { "title": "trans.output", "description": "Output filename for transformations that output a transformed file.", - "type":"string", + "type": "string", "default": "transformed.c" } }, @@ -1530,15 +1635,13 @@ "properties": { "enabled": { "title": "annotation.int.enabled", - "description": - "Enable manual annotation of functions with desired precision, i.e., the activated IntDomains.", + "description": "Enable manual annotation of functions with desired precision, i.e., the activated IntDomains.", "type": "boolean", "default": false }, "privglobs": { "title": "annotation.int.privglobs", - "description": - "Enables handling of privatized globals, by setting the precision to the heighest value, when annotation.int.enabled is true.", + "description": "Enables handling of privatized globals, by setting the precision to the heighest value, when annotation.int.enabled is true.", "type": "boolean", "default": true } @@ -1551,8 +1654,7 @@ "properties": { "enabled": { "title": "annotation.float.enabled", - "description": - "Enable manual annotation of functions with desired precision, i.e., the activated FloatDomains.", + "description": "Enable manual annotation of functions with desired precision, i.e., the activated FloatDomains.", "type": "boolean", "default": false } @@ -1566,7 +1668,20 @@ "type": "array", "items": { "type": "string", - "enum": ["base.no-non-ptr", "base.non-ptr", "base.no-int", "base.int", "base.no-interval", "base.no-interval_set","base.interval", "base.interval_set","relation.no-context", "relation.context", "no-widen", "widen"] + "enum": [ + "base.no-non-ptr", + "base.non-ptr", + "base.no-int", + "base.int", + "base.no-interval", + "base.no-interval_set", + "base.interval", + "base.interval_set", + "relation.no-context", + "relation.context", + "no-widen", + "widen" + ] }, "default": [] } @@ -1578,7 +1693,16 @@ "type": "array", "items": { "type": "string", - "enum": ["no-def_exc", "def_exc", "no-interval", "interval", "no-enums", "enums", "no-congruence", "congruence"] + "enum": [ + "no-def_exc", + "def_exc", + "no-interval", + "interval", + "no-enums", + "enums", + "no-congruence", + "congruence" + ] }, "default": [] } @@ -1611,8 +1735,7 @@ }, "priv-distr-init": { "title": "exp.priv-distr-init", - "description": - "Distribute global initializations to all global invariants for more consistent widening dynamics.", + "description": "Distribute global initializations to all global invariants for more consistent widening dynamics.", "type": "boolean", "default": false }, @@ -1643,8 +1766,7 @@ }, "earlyglobs": { "title": "exp.earlyglobs", - "description": - "Side-effecting of globals right after initialization.", + "description": "Side-effecting of globals right after initialization.", "type": "boolean", "default": false }, @@ -1658,20 +1780,20 @@ "title": "exp.unique", "description": "For types that have only one value.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "forward": { "title": "exp.forward", - "description": - "Use implicit forward propagation instead of the demand driven approach.", + "description": "Use implicit forward propagation instead of the demand driven approach.", "type": "boolean", "default": false }, "volatiles_are_top": { "title": "exp.volatiles_are_top", - "description": - "volatile and extern keywords set variables permanently to top", + "description": "volatile and extern keywords set variables permanently to top", "type": "boolean", "default": true }, @@ -1689,18 +1811,20 @@ }, "exclude_from_earlyglobs": { "title": "exp.exclude_from_earlyglobs", - "description": - "Global variables that should be handled flow-sensitively when using earlyglobs.", + "description": "Global variables that should be handled flow-sensitively when using earlyglobs.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, - "exclude_from_invalidation" : { + "exclude_from_invalidation": { "title": "exp.exclude_from_invalidation", - "description": - "Global variables that should not be invalidated. This assures the analysis that such globals are only modified through known code", + "description": "Global variables that should not be invalidated. This assures the analysis that such globals are only modified through known code", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "g2html_path": { @@ -1711,10 +1835,11 @@ }, "extraspecials": { "title": "exp.extraspecials", - "description": - "List of functions that must be analyzed as unknown extern functions", + "description": "List of functions that must be analyzed as unknown extern functions", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "default": [] }, "no-narrow": { @@ -1725,15 +1850,13 @@ }, "basic-blocks": { "title": "exp.basic-blocks", - "description": - "Only keep values for basic blocks instead of for every node. Should take longer but need less space.", + "description": "Only keep values for basic blocks instead of for every node. Should take longer but need less space.", "type": "boolean", "default": false }, "fast_global_inits": { "title": "exp.fast_global_inits", - "description": - "Only generate one 'a[any_index] = x' for all assignments a[...] = x for a global array a[n].", + "description": "Only generate one 'a[any_index] = x' for all assignments a[...] = x for a global array a[n].", "type": "boolean", "default": true }, @@ -1741,27 +1864,27 @@ "title": "exp.architecture", "description": "Architecture for analysis, currently for witness", "type": "string", - "enum": ["64bit", "32bit"], + "enum": [ + "64bit", + "32bit" + ], "default": "64bit" }, "gcc_path": { "title": "exp.gcc_path", - "description": - "Location of gcc. Used to combine source files with cilly. Change to gcc-9 or another version on OS X (with gcc being clang by default cilly will fail otherwise).", + "description": "Location of gcc. Used to combine source files with cilly. Change to gcc-9 or another version on OS X (with gcc being clang by default cilly will fail otherwise).", "type": "string", "default": "/usr/bin/gcc" }, "cpp-path": { "title": "exp.cpp-path", - "description": - "Path to C preprocessor (cpp) to use. If empty, then automatically searched.", + "description": "Path to C preprocessor (cpp) to use. If empty, then automatically searched.", "type": "string", "default": "" }, "unrolling-factor": { "title": "exp.unrolling-factor", - "description": - "Sets the unrolling factor for the loopUnrollingVisitor.", + "description": "Sets the unrolling factor for the loopUnrollingVisitor.", "type": "integer", "default": 0 }, @@ -1843,43 +1966,37 @@ }, "timeout": { "title": "dbg.timeout", - "description": - "Stop solver after this time. 0 means no timeout. Supports optional units h, m, s. E.g. 1m6s = 01m06s = 66; 6h = 6*60*60.", + "description": "Stop solver after this time. 0 means no timeout. Supports optional units h, m, s. E.g. 1m6s = 01m06s = 66; 6h = 6*60*60.", "type": "string", "default": "0" }, "solver-stats-interval": { "title": "dbg.solver-stats-interval", - "description": - "Interval in seconds to print statistics while solving. Set to 0 to deactivate.", + "description": "Interval in seconds to print statistics while solving. Set to 0 to deactivate.", "type": "integer", "default": 10 }, "solver-signal": { "title": "dbg.solver-signal", - "description": - "Signal to print statistics while solving. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", + "description": "Signal to print statistics while solving. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", "type": "string", "default": "sigusr1" }, "backtrace-signal": { "title": "dbg.backtrace-signal", - "description": - "Signal to print a raw backtrace on stderr. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", + "description": "Signal to print a raw backtrace on stderr. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", "type": "string", "default": "sigusr2" }, "solver-progress": { "title": "dbg.solver-progress", - "description": - "Used for debugging. Prints out a symbol on solving a rhs.", + "description": "Used for debugging. Prints out a symbol on solving a rhs.", "type": "boolean", "default": false }, "print_wpoints": { "title": "dbg.print_wpoints", - "description": - "Print the widening points after solving (does not include the removed wpoints during solving by the slr solvers). Currently only implemented in: slr*, td3.", + "description": "Print the widening points after solving (does not include the removed wpoints during solving by the slr solvers). Currently only implemented in: slr*, td3.", "type": "boolean", "default": false }, @@ -1908,8 +2025,7 @@ "properties": { "widen": { "title": "dbg.limit.widen", - "description": - "Limit for number of widenings per node (0 = no limit).", + "description": "Limit for number of widenings per node (0 = no limit).", "type": "integer", "default": 0 } @@ -1918,15 +2034,13 @@ }, "warn_with_context": { "title": "dbg.warn_with_context", - "description": - "Keep warnings for different contexts apart (currently only done for asserts).", + "description": "Keep warnings for different contexts apart (currently only done for asserts).", "type": "boolean", "default": false }, "regression": { "title": "dbg.regression", - "description": - "Only output warnings for assertions that have an unexpected result (no comment, comment FAIL, comment UNKNOWN)", + "description": "Only output warnings for assertions that have an unexpected result (no comment, comment FAIL, comment UNKNOWN)", "type": "boolean", "default": false }, @@ -2001,22 +2115,19 @@ }, "print_tids": { "title": "dbg.print_tids", - "description": - "Should the analysis print information on the encountered TIDs", + "description": "Should the analysis print information on the encountered TIDs", "type": "boolean", "default": false }, "print_protection": { "title": "dbg.print_protection", - "description": - "Should the analysis print information on which globals are protected by which mutex?", + "description": "Should the analysis print information on which globals are protected by which mutex?", "type": "boolean", "default": false }, - "run_cil_check" : { + "run_cil_check": { "title": "dbg.run_cil_check", - "description": - "Should the analysis call Check.checkFile after creating the CFG (helpful to verify that transformations respect CIL's invariants.", + "description": "Should the analysis call Check.checkFile after creating the CFG (helpful to verify that transformations respect CIL's invariants.", "type": "boolean", "default": false } @@ -2185,23 +2296,29 @@ "properties": { "term": { "title": "solvers.td3.term", - "description": - "Should the td3 solver use the phased/terminating strategy?", + "description": "Should the td3 solver use the phased/terminating strategy?", "type": "boolean", "default": true }, "side_widen": { "title": "solvers.td3.side_widen", - "description": - "When to widen in side. never: never widen, always: always widen, sides: widen if there are multiple side-effects from the same var resulting in a new value, cycle: widen if a called or a start var get destabilized, unstable_called: widen if any called var gets destabilized, unstable_self: widen if side-effected var gets destabilized, sides-pp: widen if there are multiple side-effects from the same program point resulting in a new value, sides-local: Widen with contributions from variables from which multiple side-effects leading to a new value originate.", + "description": "When to widen in side. never: never widen, always: always widen, sides: widen if there are multiple side-effects from the same var resulting in a new value, cycle: widen if a called or a start var get destabilized, unstable_called: widen if any called var gets destabilized, unstable_self: widen if side-effected var gets destabilized, sides-pp: widen if there are multiple side-effects from the same program point resulting in a new value, sides-local: Widen with contributions from variables from which multiple side-effects leading to a new value originate.", "type": "string", - "enum": ["never", "always", "sides", "cycle", "unstable_called", "unstable_self", "sides-pp","sides-local"], + "enum": [ + "never", + "always", + "sides", + "cycle", + "unstable_called", + "unstable_self", + "sides-pp", + "sides-local" + ], "default": "sides" }, "space": { "title": "solvers.td3.space", - "description": - "Should the td3 solver only keep values at widening points?", + "description": "Should the td3 solver only keep values at widening points?", "type": "boolean", "default": false }, @@ -2213,8 +2330,7 @@ }, "space_restore": { "title": "solvers.td3.space_restore", - "description": - "Should the td3-space solver restore values for non-widening-points? Not needed for generating warnings, but needed for inspecting output!", + "description": "Should the td3-space solver restore values for non-widening-points? Not needed for generating warnings, but needed for inspecting output!", "type": "boolean", "default": true }, @@ -2230,10 +2346,10 @@ "type": "boolean", "default": true }, - "skip-unchanged-rhs" : { - "title" : "solvers.td3.skip-unchanged-rhs", - "description" : "Skip evaluation of RHS if all dependencies are unchanged - INCOMPATIBLE WITH RESTARTING", - "type" : "boolean", + "skip-unchanged-rhs": { + "title": "solvers.td3.skip-unchanged-rhs", + "description": "Skip evaluation of RHS if all dependencies are unchanged - INCOMPATIBLE WITH RESTARTING", + "type": "boolean", "default": false }, "restart": { @@ -2277,8 +2393,7 @@ "properties": { "restart_count": { "title": "solvers.slr4.restart_count", - "description": - "How many times SLR4 is allowed to switch from restarting iteration to increasing iteration.", + "description": "How many times SLR4 is allowed to switch from restarting iteration to increasing iteration.", "type": "integer", "default": 1 } @@ -2312,7 +2427,10 @@ "title": "witness.graphml.id", "description": "Which witness node IDs to use? node/enumerate", "type": "string", - "enum": ["node", "enumerate"], + "enum": [ + "node", + "enumerate" + ], "default": "node" }, "minimize": { @@ -2323,8 +2441,7 @@ }, "uncil": { "title": "witness.graphml.uncil", - "description": - "Try to undo CIL control flow transformations in witness", + "description": "Try to undo CIL control flow transformations in witness", "type": "boolean", "default": false }, @@ -2349,22 +2466,19 @@ "properties": { "loop-head": { "title": "witness.invariant.loop-head", - "description": - "Emit invariants at loop heads", + "description": "Emit invariants at loop heads", "type": "boolean", "default": true }, "after-lock": { "title": "witness.invariant.after-lock", - "description": - "Emit invariants after mutex locking", + "description": "Emit invariants after mutex locking", "type": "boolean", "default": true }, "other": { "title": "witness.invariant.other", - "description": - "Emit invariants at all other locations", + "description": "Emit invariants at all other locations", "type": "boolean", "default": true }, @@ -2382,8 +2496,7 @@ }, "full": { "title": "witness.invariant.full", - "description": - "Whether to dump assertions about all local variables or limitting it to modified ones where possible.", + "description": "Whether to dump assertions about all local variables or limitting it to modified ones where possible.", "type": "boolean", "default": true }, @@ -2514,4 +2627,4 @@ } }, "additionalProperties": false -} +} \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 7d2c6054a7..a550437462 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -588,6 +588,96 @@ struct end +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context*) +module CallstringLifter (S:Spec) + : Spec with module C = Printable.Liszt (CilType.Fundec) + and module G = S.G += +struct + include S + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Liszt (CilType.Fundec) + let dummy = [] + let callDepthHeight = 10 + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = callDepthHeight - List.length elem in + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + end + + module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) + module G = S.G + module C = CallStack + module V = S.V + module P = + struct + include S.P + let of_elt (x, _) = of_elt x + end + + let name () = S.name ()^" with k callstring approach" + let startstate v = S.startstate v, [] + let exitstate v = S.exitstate v, [] + let morphstate v (d,l) = S.morphstate v d, l + + (* returns the call stack of the given ctx*) + let stack ctx = + snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) + + let context fd (d,l) = l + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = + (* D.t -> S.D.t *) + {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, stack ctx) es) + ; context = (fun () -> ctx_failwith "no context (k Callstring)") + } + + let print f ctx ctx' = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx); + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx'); + printf "\n\n" + + let enter ctx r f args = + let new_stack = CallStack.push (stack ctx) [f] in + let ctx' = {ctx with context = (fun () -> new_stack) + ; local = (fst ctx.local, new_stack)} in + if not !AnalysisState.postsolving then print f ctx ctx'; + let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) + liftmap_tup (S.enter (conv ctx') r f args) + + let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f + + let sync ctx reason = S.sync (conv ctx) reason, stack ctx + let query ctx q = S.query (conv ctx) q + let assign ctx lval expr = S.assign (conv ctx) lval expr, stack ctx + let vdecl ctx v = S.vdecl (conv ctx) v, stack ctx + let body ctx fundec = S.body (conv ctx) fundec, stack ctx + let branch ctx e tv = S.branch (conv ctx) e tv, stack ctx + let return ctx r f = S.return (conv ctx) r f, stack ctx + let asm ctx = S.asm (conv ctx), stack ctx + let skip ctx = S.skip (conv ctx), stack ctx + let special ctx r f args = S.special (conv ctx) r f args, stack ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx + let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx + let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) + let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx + +end + module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index f0a55dc2f2..4beaccc29c 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,6 +21,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) + |> lift (get_bool "ana.context.callstring") (module CallstringLifter) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a75e12564f..cb18ad0dd7 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -149,7 +149,6 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse module LoopTermination = LoopTermination -module KCallstring = KCallstring module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/80-context_gas_sens/10-call_in_call.c b/tests/regression/80-context_gas_sens/10-call_in_call.c new file mode 100644 index 0000000000..4d25cb89ad --- /dev/null +++ b/tests/regression/80-context_gas_sens/10-call_in_call.c @@ -0,0 +1,55 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +// TODO: is this behavior correct? +#include + +int num_iterat = 8; // should be context gas value - 2 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/10-call_in_call.c b/tests/regression/81-context_gas_insens/10-call_in_call.c new file mode 100644 index 0000000000..c355c92603 --- /dev/null +++ b/tests/regression/81-context_gas_insens/10-call_in_call.c @@ -0,0 +1,55 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +// TODO: is this behavior correct? +#include + +int num_iterat = 9; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); // UNKNOWN +} \ No newline at end of file diff --git a/tests/regression/82-callstring/01-simple_rec.c b/tests/regression/82-callstring/01-simple_rec.c new file mode 100644 index 0000000000..f974ce63ce --- /dev/null +++ b/tests/regression/82-callstring/01-simple_rec.c @@ -0,0 +1,21 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 12; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); +} diff --git a/tests/regression/82-callstring/02-multiple_rec.c b/tests/regression/82-callstring/02-multiple_rec.c new file mode 100644 index 0000000000..31f99c3533 --- /dev/null +++ b/tests/regression/82-callstring/02-multiple_rec.c @@ -0,0 +1,56 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 2; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); +} diff --git a/tests/regression/82-callstring/03-function_chain.c b/tests/regression/82-callstring/03-function_chain.c new file mode 100644 index 0000000000..47c4c3ae21 --- /dev/null +++ b/tests/regression/82-callstring/03-function_chain.c @@ -0,0 +1,52 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 9; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); +} From 133fa2eaaa9373eba6215e75ff6babd3738ef7f4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 12:30:56 +0100 Subject: [PATCH 023/128] fixed a typo in a file name --- .../{10-endless_loop.c => 11-endless_loop.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/regression/81-context_gas_insens/{10-endless_loop.c => 11-endless_loop.c} (100%) diff --git a/tests/regression/81-context_gas_insens/10-endless_loop.c b/tests/regression/81-context_gas_insens/11-endless_loop.c similarity index 100% rename from tests/regression/81-context_gas_insens/10-endless_loop.c rename to tests/regression/81-context_gas_insens/11-endless_loop.c From 3d6aba41132f5160dafa8fd317c920b4300afdf7 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 18:57:21 +0100 Subject: [PATCH 024/128] made the callstring approach modular (different types of callstack elements), currently two types: stmt and fundec, added option to emable and disable both lifters --- src/common/util/options.schema.json | 12 +++- src/framework/constraints.ml | 86 +++++++++++++++++++++-------- src/framework/control.ml | 3 +- 3 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index b65986fafe..5f3771e273 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -1075,9 +1075,15 @@ "type": "boolean", "default": false }, - "callstring": { - "title": "ana.context.callstring", - "description": "If enabled, the last k elements of the callstack are used as context", + "callstring_fundec": { + "title": "ana.context.callstring_fundec", + "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Fundec", + "type": "boolean", + "default": false + }, + "callstring_stmt": { + "title": "ana.context.callstring_stmt", + "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Stmt", "type": "boolean", "default": false } diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a550437462..712ab5fc73 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -532,7 +532,7 @@ struct let cg_val ctx = snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - let name () = S.name ()^" with context gas" + let name () = S.name ()^" with context gas (" ^ (string_of_int cg_init_val) ^")" let startstate v = S.startstate v, cg_init_val let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i @@ -561,7 +561,7 @@ struct | [] -> " " | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) - let enter ctx r f args = + let enter ctx r f args = let ctx_dec = dec_context_gas ctx in if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in @@ -588,19 +588,29 @@ struct end -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context*) -module CallstringLifter (S:Spec) - : Spec with module C = Printable.Liszt (CilType.Fundec) - and module G = S.G +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module CallstringLifter (S:Spec) (CT:Callstack_Type) + : Spec with module G = S.G = struct include S (* simulates a call stack of depth k*) module CallStack = struct - include Printable.Liszt (CilType.Fundec) + include Printable.Liszt (CT) let dummy = [] - let callDepthHeight = 10 + let depth = 2 let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -608,9 +618,13 @@ struct | x :: xs when n > 0 -> x :: take (n - 1) xs | _ -> [] in - let remaining_space = callDepthHeight - List.length elem in - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem + let remaining_space = depth - List.length elem in (*TODO: if we stick with the list it must be assumed that the list length can be larger than the depth*) + if remaining_space >= 0 + then + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + else + List.rev(take depth (List.rev elem)) end module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) @@ -623,7 +637,7 @@ struct let of_elt (x, _) = of_elt x end - let name () = S.name ()^" with k callstring approach" + let name () = S.name ()^" with k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" let startstate v = S.startstate v, [] let exitstate v = S.exitstate v, [] let morphstate v (d,l) = S.morphstate v d, l @@ -638,22 +652,15 @@ struct (* D.t -> S.D.t *) {ctx with local = fst ctx.local ; split = (fun d es -> ctx.split (d, stack ctx) es) - ; context = (fun () -> ctx_failwith "no context (k Callstring)") + ; context = (fun () -> ctx_failwith "no context (k Callstring)") (* TODO: correct?*) } - let print f ctx ctx' = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx); - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx'); - printf "\n\n" - let enter ctx r f args = - let new_stack = CallStack.push (stack ctx) [f] in + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (stack ctx) elem in let ctx' = {ctx with context = (fun () -> new_stack) ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then print f ctx ctx'; + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) liftmap_tup (S.enter (conv ctx') r f args) @@ -675,9 +682,42 @@ struct let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx +end +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "Fundec" + let pushElem f args ctx = [f] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" end +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "Stmt" + let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> [stmt] + | _ -> printf "not a stmt\n"; [] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +module CallstringLifter_Fundec (S:Spec) = CallstringLifter (S:Spec) (Fundec) +module CallstringLifter_Stmt (S:Spec) = CallstringLifter (S:Spec) (Stmt) + module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index 4beaccc29c..a75daf238d 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,7 +21,8 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.callstring") (module CallstringLifter) + |> lift (get_bool "ana.context.callstring_fundec") (module CallstringLifter_Fundec) + |> lift (get_bool "ana.context.callstring_stmt") (module CallstringLifter_Stmt) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) From 14c2e588e4a2bba07ebf68c352ed9962a88671a7 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 19:40:10 +0100 Subject: [PATCH 025/128] deleted main tracking from Callstring lifter; added testcases --- src/framework/constraints.ml | 22 ++++--- .../82-callstring_Fundec/01-simple_rec_sens.c | 22 +++++++ .../82-callstring_Fundec/02-simple_rec_ins.c | 22 +++++++ .../03-multiple_rec_sens.c | 59 +++++++++++++++++++ .../04-multiple_rec_ins.c | 59 +++++++++++++++++++ .../05-function_chain_sens.c} | 4 +- .../06-function_chain_ins.c | 54 +++++++++++++++++ .../01-simple_rec_sens.c} | 5 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 22 +++++++ .../03-multiple_rec_sens.c} | 7 ++- .../83-callstring_Stmt/04-multiple_rec_ins.c | 59 +++++++++++++++++++ .../05-function_chain_sens.c | 54 +++++++++++++++++ .../06-function_chain_ins.c | 54 +++++++++++++++++ 13 files changed, 429 insertions(+), 14 deletions(-) create mode 100644 tests/regression/82-callstring_Fundec/01-simple_rec_sens.c create mode 100644 tests/regression/82-callstring_Fundec/02-simple_rec_ins.c create mode 100644 tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c create mode 100644 tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c rename tests/regression/{82-callstring/03-function_chain.c => 82-callstring_Fundec/05-function_chain_sens.c} (82%) create mode 100644 tests/regression/82-callstring_Fundec/06-function_chain_ins.c rename tests/regression/{82-callstring/01-simple_rec.c => 83-callstring_Stmt/01-simple_rec_sens.c} (58%) create mode 100644 tests/regression/83-callstring_Stmt/02-simple_rec_ins.c rename tests/regression/{82-callstring/02-multiple_rec.c => 83-callstring_Stmt/03-multiple_rec_sens.c} (78%) create mode 100644 tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c create mode 100644 tests/regression/83-callstring_Stmt/05-function_chain_sens.c create mode 100644 tests/regression/83-callstring_Stmt/06-function_chain_ins.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 712ab5fc73..84ba1368b3 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -561,7 +561,7 @@ struct | [] -> " " | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) - let enter ctx r f args = + let enter ctx r f args = let ctx_dec = dec_context_gas ctx in if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in @@ -610,7 +610,7 @@ struct module CallStack = struct include Printable.Liszt (CT) let dummy = [] - let depth = 2 + let depth = 10 let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -656,13 +656,17 @@ struct } let enter ctx r f args = - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) - ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); - let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) - liftmap_tup (S.enter (conv ctx') r f args) + let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) + if CilType.Fundec.show f = "main" + then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) + else( + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (stack ctx) elem in + let ctx' = {ctx with context = (fun () -> new_stack) + ; local = (fst ctx.local, new_stack)} in + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); + liftmap_tup new_stack (S.enter (conv ctx') r f args)) + let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c new file mode 100644 index 0000000000..a8dd15ebb4 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 9; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c new file mode 100644 index 0000000000..c597ec80ea --- /dev/null +++ b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c new file mode 100644 index 0000000000..547f9b4c44 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 9; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c new file mode 100644 index 0000000000..e23af9a938 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/82-callstring/03-function_chain.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c similarity index 82% rename from tests/regression/82-callstring/03-function_chain.c rename to tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 47c4c3ae21..71fbbf59b4 100644 --- a/tests/regression/82-callstring/03-function_chain.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include @@ -49,4 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); + + __goblint_check(result == 1); } diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c new file mode 100644 index 0000000000..5b294209d2 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 12; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} diff --git a/tests/regression/82-callstring/01-simple_rec.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c similarity index 58% rename from tests/regression/82-callstring/01-simple_rec.c rename to tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index f974ce63ce..20e0209508 100644 --- a/tests/regression/82-callstring/01-simple_rec.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -1,8 +1,8 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set // Basic example #include -int num_iterat = 12; +int num_iterat = 10; int a = 20; int f(int i) @@ -18,4 +18,5 @@ int f(int i) int main(void) { f(num_iterat); + __goblint_check(a == 0); } diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c new file mode 100644 index 0000000000..a48ae17192 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/82-callstring/02-multiple_rec.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c similarity index 78% rename from tests/regression/82-callstring/02-multiple_rec.c rename to tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index 31f99c3533..28b9748c2c 100644 --- a/tests/regression/82-callstring/02-multiple_rec.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -1,8 +1,8 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include -int num_iterat = 2; +int num_iterat = 10; int f(int i) { @@ -53,4 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); } diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c new file mode 100644 index 0000000000..6eeefacc91 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c new file mode 100644 index 0000000000..422bcb4b7b --- /dev/null +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 10; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); +} diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c new file mode 100644 index 0000000000..c17d01d09f --- /dev/null +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 13; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} From 269b47a030c0a2b5fecb4cfa84703f74e1a19003 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 28 Nov 2023 14:59:24 +0100 Subject: [PATCH 026/128] added new testcases, a few explanations in constraints --- src/framework/constraints.ml | 10 ++-- .../03-multiple_rec_sens.c | 1 + .../05-function_chain_sens.c | 2 +- .../07-call_in_call_sens.c | 54 +++++++++++++++++++ .../82-callstring_Fundec/08-ackermann.c | 27 ++++++++++ .../09-circle_call_and_loops.c | 48 +++++++++++++++++ .../10-circle_call_and_big_loop.c | 46 ++++++++++++++++ .../11-big_call_and_loop.c | 49 +++++++++++++++++ .../05-function_chain_sens.c | 2 +- .../83-callstring_Stmt/07-call_in_call.c | 54 +++++++++++++++++++ .../08-circle_call_and_big_loop.c | 46 ++++++++++++++++ 11 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 tests/regression/82-callstring_Fundec/07-call_in_call_sens.c create mode 100644 tests/regression/82-callstring_Fundec/08-ackermann.c create mode 100644 tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c create mode 100644 tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c create mode 100644 tests/regression/82-callstring_Fundec/11-big_call_and_loop.c create mode 100644 tests/regression/83-callstring_Stmt/07-call_in_call.c create mode 100644 tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 84ba1368b3..3b1c76b5c1 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -610,7 +610,7 @@ struct module CallStack = struct include Printable.Liszt (CT) let dummy = [] - let depth = 10 + let depth = 10 (* must be >= 0 *) let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -618,7 +618,7 @@ struct | x :: xs when n > 0 -> x :: take (n - 1) xs | _ -> [] in - let remaining_space = depth - List.length elem in (*TODO: if we stick with the list it must be assumed that the list length can be larger than the depth*) + let remaining_space = depth - List.length elem in if remaining_space >= 0 then let remaining_stack = take remaining_space (List.rev stack) in @@ -659,12 +659,12 @@ struct let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) if CilType.Fundec.show f = "main" then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) - else( + else ( let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) + let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); (* just for debugging purpose*) liftmap_tup new_stack (S.enter (conv ctx') r f args)) diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 547f9b4c44..87fe4778d7 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -49,6 +49,7 @@ int h(int i) int main(void) { int res1 = f(num_iterat); + __goblint_check(res1 == 1); int res2 = g(num_iterat); int res3 = h(num_iterat); int res4 = h(num_iterat); diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 71fbbf59b4..9eb4a15bef 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -2,7 +2,7 @@ // Checks if function chains are handled properly #include -int num_iterat = 9; +int num_iterat = 11; int h(int i) { diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c new file mode 100644 index 0000000000..0d26f57944 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 9; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c new file mode 100644 index 0000000000..6ecb4766ef --- /dev/null +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// This code would result in a StackOverflow if it is analyses fully context sensitive +#include + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) { + ack (4,1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c new file mode 100644 index 0000000000..94847d7873 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed +#include + +int num_iterat = 200; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); //UNKNOWN + __goblint_check(res2 == 1); //UNKNOWN + } +} diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c new file mode 100644 index 0000000000..35f9a66f7c --- /dev/null +++ b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c new file mode 100644 index 0000000000..3591b8f4da --- /dev/null +++ b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c @@ -0,0 +1,49 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result +// TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) +#include + +int num_iterat = 90; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(9); + int res2 = g(9); + __goblint_check(res1 == 1); // TODO + __goblint_check(res2 == 2); // TODO + for (int i = 10; i > 0; i--) + { + int res3 = f(num_iterat); + int res4 = g(num_iterat); + __goblint_check(res3 == 1); // TODO + __goblint_check(res4 == 2); // TODO + } +} diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index 422bcb4b7b..c3094efe4e 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -2,7 +2,7 @@ // Checks if function chains are handled properly #include -int num_iterat = 10; +int num_iterat = 12; int h(int i) { diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c new file mode 100644 index 0000000000..47e6dd515b --- /dev/null +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c new file mode 100644 index 0000000000..60d5d95f29 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} From 4bfbfac0b7dc9e018f700de9a7f14933c0fd0f54 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 4 Dec 2023 13:46:54 +0100 Subject: [PATCH 027/128] moved callstring ana from lifter to analysis (must be tested), adapted testcases --- src/analyses/callstringAnalysis.ml | 100 +++++++++++++ src/common/util/options.schema.json | 16 +-- src/framework/constraints.ml | 134 ------------------ src/framework/control.ml | 2 - src/goblint_lib.ml | 1 + .../80-context_gas_sens/06-loop_unrolling.c | 5 +- .../80-context_gas_sens/09-main_recursion.c | 15 ++ .../80-context_gas_sens/10-call_in_call.c | 3 +- .../81-context_gas_insens/10-call_in_call.c | 1 - .../82-callstring_Fundec/01-simple_rec_sens.c | 2 +- .../82-callstring_Fundec/02-simple_rec_ins.c | 2 +- .../03-multiple_rec_sens.c | 2 +- .../04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../07-call_in_call_sens.c | 2 +- .../82-callstring_Fundec/08-ackermann.c | 2 +- .../09-circle_call_and_loops.c | 2 +- .../10-circle_call_and_big_loop.c | 2 +- .../11-big_call_and_loop.c | 4 +- .../82-callstring_Fundec/12-loop_unrolling.c | 34 +++++ .../83-callstring_Stmt/01-simple_rec_sens.c | 2 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 2 +- .../83-callstring_Stmt/03-multiple_rec_sens.c | 2 +- .../83-callstring_Stmt/04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../83-callstring_Stmt/07-call_in_call.c | 2 +- .../08-circle_call_and_big_loop.c | 2 +- 29 files changed, 177 insertions(+), 174 deletions(-) create mode 100644 src/analyses/callstringAnalysis.ml create mode 100644 tests/regression/82-callstring_Fundec/12-loop_unrolling.c diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml new file mode 100644 index 0000000000..01a459183a --- /dev/null +++ b/src/analyses/callstringAnalysis.ml @@ -0,0 +1,100 @@ +open GoblintCil +open Analyses +open Printf + +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module Spec (CT:Callstack_Type) : MCPSpec= +struct + include Analyses.IdentitySpec + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Liszt (CT) + let dummy = [] + let depth = 10 (* must be >= 0 *) + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = depth - List.length elem in + if remaining_space >= 0 + then + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + else + List.rev(take depth (List.rev elem)) + end + + module D = Lattice.FakeSingleton(CallStack) + module C = CallStack + module V = EmptyV + module G = Lattice.Unit + + let name () = "k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" + let startstate v = [] + let exitstate v = [] + + let context fd d = d + + let enter ctx r f args = + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (ctx.local) elem in + let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) + ; local = new_stack} in + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) + [ctx.local, new_stack] +end + +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "Fundec" + let pushElem f args ctx = [f] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" +end + +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "Stmt" + let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> [stmt] + | _ -> printf "not a stmt\n"; [] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +module CallstringLifter_Fundec = Spec (Fundec) +module CallstringLifter_Stmt = Spec (Stmt) + +let _ = + MCP.register_analysis (module CallstringLifter_Fundec : MCPSpec); + MCP.register_analysis (module CallstringLifter_Stmt : MCPSpec) + + diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 5f3771e273..f97fa3df21 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -612,7 +612,9 @@ "wideningThresholds", "memsafetySpecification", "termination", - "tmpSpecialAnalysis" + "tmpSpecialAnalysis", + "callstring_fundec", + "callstring_stmt" ] }, "default": [ @@ -1074,18 +1076,6 @@ "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", "type": "boolean", "default": false - }, - "callstring_fundec": { - "title": "ana.context.callstring_fundec", - "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Fundec", - "type": "boolean", - "default": false - }, - "callstring_stmt": { - "title": "ana.context.callstring_stmt", - "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Stmt", - "type": "boolean", - "default": false } }, "additionalProperties": false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 3b1c76b5c1..aaca114c84 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -588,140 +588,6 @@ struct end -(* Specifies the type of the callstack elements for the CallstringLifter*) -module type Callstack_Type = -sig - include CilType.S - val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) -end - -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context - With the CT argument it is possible to specify the type of the Callstack elements -*) -module CallstringLifter (S:Spec) (CT:Callstack_Type) - : Spec with module G = S.G -= -struct - include S - - (* simulates a call stack of depth k*) - module CallStack = struct - include Printable.Liszt (CT) - let dummy = [] - let depth = 10 (* must be >= 0 *) - - let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = depth - List.length elem in - if remaining_space >= 0 - then - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem - else - List.rev(take depth (List.rev elem)) - end - - module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) - module G = S.G - module C = CallStack - module V = S.V - module P = - struct - include S.P - let of_elt (x, _) = of_elt x - end - - let name () = S.name ()^" with k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" - let startstate v = S.startstate v, [] - let exitstate v = S.exitstate v, [] - let morphstate v (d,l) = S.morphstate v d, l - - (* returns the call stack of the given ctx*) - let stack ctx = - snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - - let context fd (d,l) = l - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = - (* D.t -> S.D.t *) - {ctx with local = fst ctx.local - ; split = (fun d es -> ctx.split (d, stack ctx) es) - ; context = (fun () -> ctx_failwith "no context (k Callstring)") (* TODO: correct?*) - } - - let enter ctx r f args = - let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) - if CilType.Fundec.show f = "main" - then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) - else ( - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) - ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); (* just for debugging purpose*) - liftmap_tup new_stack (S.enter (conv ctx') r f args)) - - - let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f - - let sync ctx reason = S.sync (conv ctx) reason, stack ctx - let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr, stack ctx - let vdecl ctx v = S.vdecl (conv ctx) v, stack ctx - let body ctx fundec = S.body (conv ctx) fundec, stack ctx - let branch ctx e tv = S.branch (conv ctx) e tv, stack ctx - let return ctx r f = S.return (conv ctx) r f, stack ctx - let asm ctx = S.asm (conv ctx), stack ctx - let skip ctx = S.skip (conv ctx), stack ctx - let special ctx r f args = S.special (conv ctx) r f args, stack ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx - let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx - let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) - let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx - let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx -end - -module Fundec:Callstack_Type = struct - include CilType.Fundec - let stackTypeName = "Fundec" - let pushElem f args ctx = [f] - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; - printf "\n\n" -end - -module Stmt:Callstack_Type = struct - include CilType.Stmt - let stackTypeName = "Stmt" - let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) - | Statement stmt -> [stmt] - | _ -> printf "not a stmt\n"; [] - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; - printf "\n\n" -end - -(* Lifters for the Callstring approach with different Callstack element types*) -module CallstringLifter_Fundec (S:Spec) = CallstringLifter (S:Spec) (Fundec) -module CallstringLifter_Stmt (S:Spec) = CallstringLifter (S:Spec) (Stmt) - module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index a75daf238d..f0a55dc2f2 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,8 +21,6 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.callstring_fundec") (module CallstringLifter_Fundec) - |> lift (get_bool "ana.context.callstring_stmt") (module CallstringLifter_Stmt) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 70f331b5ac..4c6e1fd22e 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -149,6 +149,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse module LoopTermination = LoopTermination +module CallstringAnalysis = CallstringAnalysis module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/80-context_gas_sens/06-loop_unrolling.c b/tests/regression/80-context_gas_sens/06-loop_unrolling.c index 63c29e6a47..b95c7a8638 100644 --- a/tests/regression/80-context_gas_sens/06-loop_unrolling.c +++ b/tests/regression/80-context_gas_sens/06-loop_unrolling.c @@ -26,8 +26,9 @@ int main(void) for (int i = 5; i > 0; i--) { res = f(num_iterat); - __goblint_check(res == 1); + __goblint_check(res == 1); result += res; } - __goblint_check(result == 5); // TODO + __goblint_check(res == 1); + __goblint_check(result == 5); //TODO } diff --git a/tests/regression/80-context_gas_sens/09-main_recursion.c b/tests/regression/80-context_gas_sens/09-main_recursion.c index 22b48103fa..01bf3a0c64 100644 --- a/tests/regression/80-context_gas_sens/09-main_recursion.c +++ b/tests/regression/80-context_gas_sens/09-main_recursion.c @@ -5,6 +5,21 @@ int num_iterat = 11; // WHY is context gas value + 1 the limit??? +/* +main mit 11: 10 -> 9 +main mit 10: 9 -> 8 +main mit 9: 8 -> 7 +main mit 8: 7 -> 6 +main mit 7: 6 -> 5 +main mit 6: 5 -> 4 +main mit 5: 4 -> 3 +main mit 4: 3 -> 2 +main mit 3: 2 -> 1 +main mit 2: 1 -> 0 +main mit 1: 0 -> 0 +main mit 0: 0 -> 0 +*/ + int main(void) { if (num_iterat > 0) diff --git a/tests/regression/80-context_gas_sens/10-call_in_call.c b/tests/regression/80-context_gas_sens/10-call_in_call.c index 4d25cb89ad..b3eac1d382 100644 --- a/tests/regression/80-context_gas_sens/10-call_in_call.c +++ b/tests/regression/80-context_gas_sens/10-call_in_call.c @@ -1,6 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set // Interesting if nested recursions are handled properly -// TODO: is this behavior correct? #include int num_iterat = 8; // should be context gas value - 2 @@ -49,7 +48,7 @@ int h(int i) int main(void) { - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + int res = f(g(h(num_iterat))); // h(8) = 3; g(3) = 2; f(2) = 1 __goblint_check(res == 1); } \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/10-call_in_call.c b/tests/regression/81-context_gas_insens/10-call_in_call.c index c355c92603..db60a35b80 100644 --- a/tests/regression/81-context_gas_insens/10-call_in_call.c +++ b/tests/regression/81-context_gas_insens/10-call_in_call.c @@ -1,6 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set // Interesting if nested recursions are handled properly -// TODO: is this behavior correct? #include int num_iterat = 9; // should be context gas value - 1 diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c index a8dd15ebb4..7548fe63dc 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c index c597ec80ea..77c544e794 100644 --- a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 87fe4778d7..3bef88d1b3 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c index e23af9a938..61e53c45d8 100644 --- a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 9eb4a15bef..c65bb8bdd4 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c index 5b294209d2..c9f7653e9f 100644 --- a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c index 0d26f57944..11ae47b759 100644 --- a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c index 6ecb4766ef..8082e2f082 100644 --- a/tests/regression/82-callstring_Fundec/08-ackermann.c +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // This code would result in a StackOverflow if it is analyses fully context sensitive #include diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c index 94847d7873..3fd8175e7f 100644 --- a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c index 35f9a66f7c..9ca346bac4 100644 --- a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c index 3591b8f4da..941756bdce 100644 --- a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c +++ b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c @@ -1,9 +1,9 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result // TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) #include -int num_iterat = 90; +int num_iterat = 10; int f(int i) { diff --git a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c new file mode 100644 index 0000000000..15f54a1b80 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c @@ -0,0 +1,34 @@ +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if recursion in loops are handled properly + loop unrolling +// TODO +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(num_iterat); + __goblint_check(res == 1); + result += res; + } + __goblint_check(res == 1); + __goblint_check(result == 5); //TODO +} diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index 20e0209508..b7bf539693 100644 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c index a48ae17192..da58b8a881 100644 --- a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index 28b9748c2c..7dc7e04a98 100644 --- a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c index 6eeefacc91..5614802151 100644 --- a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index c3094efe4e..085210b8a2 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c index c17d01d09f..8debbe9f46 100644 --- a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c index 47e6dd515b..7ef3a83194 100644 --- a/tests/regression/83-callstring_Stmt/07-call_in_call.c +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c index 60d5d95f29..38e7051736 100644 --- a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c +++ b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed #include From bf50b020b306455d8e45de86cd0d145809cdd1c5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 5 Dec 2023 16:53:48 +0100 Subject: [PATCH 028/128] used options.schema.json for variable storing; used different Lattice in callstring; adapted callstringAna -> should be working, missing: only callstring context is used for the analysis --- src/analyses/callstringAnalysis.ml | 25 +++++++++++-------------- src/common/util/options.schema.json | 12 ++++++++++++ src/framework/constraints.ml | 13 +++++-------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 01a459183a..94a4e93aab 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -1,6 +1,7 @@ -open GoblintCil open Analyses open Printf +open GoblintCil +open GobConfig (* Specifies the type of the callstack elements for the CallstringLifter*) module type Callstack_Type = @@ -14,15 +15,14 @@ end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context With the CT argument it is possible to specify the type of the Callstack elements *) -module Spec (CT:Callstack_Type) : MCPSpec= +module Spec (CT:Callstack_Type) : MCPSpec = struct include Analyses.IdentitySpec (* simulates a call stack of depth k*) module CallStack = struct include Printable.Liszt (CT) - let dummy = [] - let depth = 10 (* must be >= 0 *) + let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -39,12 +39,12 @@ struct List.rev(take depth (List.rev elem)) end - module D = Lattice.FakeSingleton(CallStack) + module D = Lattice.Fake(CallStack) module C = CallStack module V = EmptyV module G = Lattice.Unit - let name () = "k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" + let name () = "callstring_"^ CT.stackTypeName let startstate v = [] let exitstate v = [] @@ -53,7 +53,7 @@ struct let enter ctx r f args = let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (ctx.local) elem in - let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) + let ctx' = {ctx with context = (fun () -> new_stack) ; local = new_stack} in if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) [ctx.local, new_stack] @@ -61,7 +61,7 @@ end module Fundec:Callstack_Type = struct include CilType.Fundec - let stackTypeName = "Fundec" + let stackTypeName = "fundec" let pushElem f args ctx = [f] let printStack f expL listA listB = @@ -75,7 +75,7 @@ end module Stmt:Callstack_Type = struct include CilType.Stmt - let stackTypeName = "Stmt" + let stackTypeName = "stmt" let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) | Statement stmt -> [stmt] | _ -> printf "not a stmt\n"; [] @@ -90,11 +90,8 @@ module Stmt:Callstack_Type = struct end (* Lifters for the Callstring approach with different Callstack element types*) -module CallstringLifter_Fundec = Spec (Fundec) -module CallstringLifter_Stmt = Spec (Stmt) - let _ = - MCP.register_analysis (module CallstringLifter_Fundec : MCPSpec); - MCP.register_analysis (module CallstringLifter_Stmt : MCPSpec) + MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec) (* name: callstring_stmt*) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index f97fa3df21..c4ac24d8d5 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -1076,6 +1076,18 @@ "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", "type": "boolean", "default": false + }, + "ctx_gas_value": { + "title": "ana.context.ctx_gas_value", + "description": "Number of calls that are analyzed context sensitive. Used for the ContextGasLifter. Must be >= 0!", + "type": "integer", + "default": 10 + }, + "callStack_height": { + "title": "ana.context.callStack_height", + "description": "Number of elements of the callStack that should be used as context for the callsting analysis. Must be >= 0!", + "type": "integer", + "default": 10 } }, "additionalProperties": false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 78617f49f4..04fd21b372 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -526,14 +526,12 @@ struct let of_elt (x, _) = of_elt x end - let cg_init_val = 10 (* initial value of context gas*) - (* returns context gas value of the given ctx*) let cg_val ctx = snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - let name () = S.name ()^" with context gas (" ^ (string_of_int cg_init_val) ^")" - let startstate v = S.startstate v, cg_init_val + let name () = S.name ()^" with context gas" + let startstate v = S.startstate v, (get_int "ana.context.ctx_gas_value") let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i @@ -556,14 +554,14 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - let rec showExprList args = (*TODO: delete, just here for printing*) + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) @@ -585,7 +583,6 @@ struct let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's possible to decrease the counter also here*) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx - end module type Increment = From e88eccd1dd3a0f4bed9a9c5571cc40b7d43ea84d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 5 Dec 2023 19:12:28 +0100 Subject: [PATCH 029/128] built right context for callstring analysis in mcp; deleted unnecessary entry in options.schema.json; some random modules due to a lot of installations BECAUSE GOBLINTS MAKE AND MAKE INSTALL IS NOT WORKING AND I DONT KNOW WHY! --- node_modules/.package-lock.json | 19 +++++ node_modules/resolve-url/.jshintrc | 44 +++++++++++ node_modules/resolve-url/LICENSE | 21 +++++ node_modules/resolve-url/bower.json | 15 ++++ node_modules/resolve-url/changelog.md | 15 ++++ node_modules/resolve-url/component.json | 15 ++++ node_modules/resolve-url/package.json | 34 ++++++++ node_modules/resolve-url/readme.md | 83 ++++++++++++++++++++ node_modules/resolve-url/resolve-url.js | 47 +++++++++++ node_modules/resolve-url/test/resolve-url.js | 70 +++++++++++++++++ node_modules/urix/.jshintrc | 42 ++++++++++ node_modules/urix/LICENSE | 21 +++++ node_modules/urix/index.js | 17 ++++ node_modules/urix/package.json | 25 ++++++ node_modules/urix/readme.md | 46 +++++++++++ node_modules/urix/test/index.js | 43 ++++++++++ package-lock.json | 38 +++++++++ package.json | 6 ++ src/analyses/mCP.ml | 18 +++-- src/common/util/options.schema.json | 12 +-- 20 files changed, 619 insertions(+), 12 deletions(-) create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/resolve-url/.jshintrc create mode 100644 node_modules/resolve-url/LICENSE create mode 100644 node_modules/resolve-url/bower.json create mode 100644 node_modules/resolve-url/changelog.md create mode 100644 node_modules/resolve-url/component.json create mode 100644 node_modules/resolve-url/package.json create mode 100644 node_modules/resolve-url/readme.md create mode 100644 node_modules/resolve-url/resolve-url.js create mode 100644 node_modules/resolve-url/test/resolve-url.js create mode 100644 node_modules/urix/.jshintrc create mode 100644 node_modules/urix/LICENSE create mode 100644 node_modules/urix/index.js create mode 100644 node_modules/urix/package.json create mode 100644 node_modules/urix/readme.md create mode 100644 node_modules/urix/test/index.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000000..1ea8705627 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,19 @@ +{ + "name": "GobContextGas", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + } + } +} diff --git a/node_modules/resolve-url/.jshintrc b/node_modules/resolve-url/.jshintrc new file mode 100644 index 0000000000..aaf335801c --- /dev/null +++ b/node_modules/resolve-url/.jshintrc @@ -0,0 +1,44 @@ +{ + "bitwise": true, + "camelcase": true, + "curly": false, + "eqeqeq": true, + "es3": true, + "forin": true, + "immed": false, + "indent": false, + "latedef": "nofunc", + "newcap": false, + "noarg": true, + "noempty": true, + "nonew": false, + "plusplus": false, + "quotmark": false, + "undef": true, + "unused": "vars", + "strict": false, + "trailing": true, + "maxparams": 5, + "maxdepth": false, + "maxstatements": false, + "maxcomplexity": false, + "maxlen": 100, + + "asi": true, + "expr": true, + "globalstrict": true, + "smarttabs": true, + "sub": true, + + "node": true, + "browser": true, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false, + "define": false + } +} diff --git a/node_modules/resolve-url/LICENSE b/node_modules/resolve-url/LICENSE new file mode 100644 index 0000000000..0595be3671 --- /dev/null +++ b/node_modules/resolve-url/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/resolve-url/bower.json b/node_modules/resolve-url/bower.json new file mode 100644 index 0000000000..31aa6f4ea7 --- /dev/null +++ b/node_modules/resolve-url/bower.json @@ -0,0 +1,15 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "authors": ["Simon Lydell"], + "license": "MIT", + "main": "resolve-url.js", + "keywords": [ + "resolve", + "url" + ], + "ignore": [ + ".*" + ] +} diff --git a/node_modules/resolve-url/changelog.md b/node_modules/resolve-url/changelog.md new file mode 100644 index 0000000000..2a4a6304ca --- /dev/null +++ b/node_modules/resolve-url/changelog.md @@ -0,0 +1,15 @@ +### Version 0.2.1 (2014-02-25) ### + +- Fix edge case when (accidentally) supplying only one argument, and that + argument happens to be a falsy value such as `undefined` or `null`. + + +### Version 0.2.0 (2014-02-24) ### + +- Disallow passing 0 arguments. It’s weird and inconsistent between browsers. + (Backwards incompatible change.) + + +### Version 0.1.0 (2014-02-23) ### + +- Initial release. diff --git a/node_modules/resolve-url/component.json b/node_modules/resolve-url/component.json new file mode 100644 index 0000000000..f37cf00554 --- /dev/null +++ b/node_modules/resolve-url/component.json @@ -0,0 +1,15 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "license": "MIT", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "main": "resolve-url.js", + "repo": "lydell/resolve-url", + "keywords": [ + "resolve", + "url" + ], + "scripts": [ + "resolve-url.js" + ] +} diff --git a/node_modules/resolve-url/package.json b/node_modules/resolve-url/package.json new file mode 100644 index 0000000000..9442366332 --- /dev/null +++ b/node_modules/resolve-url/package.json @@ -0,0 +1,34 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "author": "Simon Lydell", + "license": "MIT", + "main": "resolve-url.js", + "repository": "lydell/resolve-url", + "keywords": [ + "resolve", + "url" + ], + "scripts": { + "test": "jshint resolve-url.js test/ && testling -u" + }, + "devDependencies": { + "testling": "~1.6.0", + "jshint": "~2.4.3", + "tape": "~2.5.0" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "chrome/latest", + "firefox/latest", + "opera/12", + "opera/latest", + "safari/5", + "iphone/6", + "android-browser/4" + ] + } +} diff --git a/node_modules/resolve-url/readme.md b/node_modules/resolve-url/readme.md new file mode 100644 index 0000000000..edfff7357c --- /dev/null +++ b/node_modules/resolve-url/readme.md @@ -0,0 +1,83 @@ +Overview +======== + +[![browser support](https://ci.testling.com/lydell/resolve-url.png)](https://ci.testling.com/lydell/resolve-url) + +Like Node.js’ [`path.resolve`]/[`url.resolve`] for the browser. + +```js +var resolveUrl = require("resolve-url") + +window.location +// https://example.com/articles/resolving-urls/edit + +resolveUrl("remove") +// https://example.com/articles/resolving-urls/remove + +resolveUrl("/static/scripts/app.js") +// https://example.com/static/scripts/app.js + +// Imagine /static/scripts/app.js contains `//# sourceMappingURL=../source-maps/app.js.map` +resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map") +// https://example.com/static/source-maps/app.js.map + +resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee") +// https://example.com/static/coffee/app.coffee + +resolveUrl("//cdn.example.com/jquery.js") +// https://cdn.example.com/jquery.js + +resolveUrl("http://foo.org/") +// http://foo.org/ +``` + + +Installation +============ + +- `npm install resolve-url` +- `bower install resolve-url` +- `component install lydell/resolve-url` + +Works with CommonJS, AMD and browser globals, through UMD. + + +Usage +===== + +### `resolveUrl(...urls)` ### + +Pass one or more urls. Resolves the last one to an absolute url, using the +previous ones and `window.location`. + +It’s like starting out on `window.location`, and then clicking links with the +urls as `href` attributes in order, from left to right. + +Unlike Node.js’ [`path.resolve`], this function always goes through all of the +arguments, from left to right. `path.resolve` goes from right to left and only +in the worst case goes through them all. Should that matter. + +Actually, the function is _really_ like clicking a lot of links in series: An +actual `` gets its `href` attribute set for each url! This means that the +url resolution of the browser is used, which makes this module really +light-weight. + +Also note that this functions deals with urls, not paths, so in that respect it +has more in common with Node.js’ [`url.resolve`]. But the arguments are more +like [`path.resolve`]. + +[`path.resolve`]: http://nodejs.org/api/path.html#path_path_resolve_from_to +[`url.resolve`]: http://nodejs.org/api/url.html#url_url_resolve_from_to + + +Tests +===== + +Run `npm test`, which lints the code and then gives you a link to open in a +browser of choice (using `testling`). + + +License +======= + +[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/resolve-url/resolve-url.js b/node_modules/resolve-url/resolve-url.js new file mode 100644 index 0000000000..19e8d040ec --- /dev/null +++ b/node_modules/resolve-url/resolve-url.js @@ -0,0 +1,47 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +void (function(root, factory) { + if (typeof define === "function" && define.amd) { + define(factory) + } else if (typeof exports === "object") { + module.exports = factory() + } else { + root.resolveUrl = factory() + } +}(this, function() { + + function resolveUrl(/* ...urls */) { + var numUrls = arguments.length + + if (numUrls === 0) { + throw new Error("resolveUrl requires at least one argument; got none.") + } + + var base = document.createElement("base") + base.href = arguments[0] + + if (numUrls === 1) { + return base.href + } + + var head = document.getElementsByTagName("head")[0] + head.insertBefore(base, head.firstChild) + + var a = document.createElement("a") + var resolved + + for (var index = 1; index < numUrls; index++) { + a.href = arguments[index] + resolved = a.href + base.href = resolved + } + + head.removeChild(base) + + return resolved + } + + return resolveUrl + +})); diff --git a/node_modules/resolve-url/test/resolve-url.js b/node_modules/resolve-url/test/resolve-url.js new file mode 100644 index 0000000000..18532edd32 --- /dev/null +++ b/node_modules/resolve-url/test/resolve-url.js @@ -0,0 +1,70 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var test = require("tape") + +var resolveUrl = require("../") + +"use strict" + +test("resolveUrl", function(t) { + + t.plan(7) + + t.equal(typeof resolveUrl, "function", "is a function") + + t.equal( + resolveUrl("https://example.com/"), + "https://example.com/" + ) + + var loc = "https://example.com/articles/resolving-urls/edit" + + t.equal( + resolveUrl(loc, "remove"), + "https://example.com/articles/resolving-urls/remove" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js"), + "https://example.com/static/scripts/app.js" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map"), + "https://example.com/static/source-maps/app.js.map" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee"), + "https://example.com/static/coffee/app.coffee" + ) + + t.equal( + resolveUrl(loc, "//cdn.example.com/jquery.js"), + "https://cdn.example.com/jquery.js" + ) + +}) + +test("edge cases", function(t) { + + t.plan(4) + + t["throws"](resolveUrl, /at least one argument/, "throws with no arguments") + + var accidentallyUndefined + var result + t.doesNotThrow( + function() { result = resolveUrl(accidentallyUndefined) }, + "undefined is still an argument" + ) + t.ok(result.match(/\/undefined$/), "undefined is stringified") + + t.equal( + resolveUrl("http://foo.org/test", undefined, {}, ["a/b"], null), + "http://foo.org/a/null", + "arguments are stringified" + ) + +}) diff --git a/node_modules/urix/.jshintrc b/node_modules/urix/.jshintrc new file mode 100644 index 0000000000..9d1a618361 --- /dev/null +++ b/node_modules/urix/.jshintrc @@ -0,0 +1,42 @@ +{ + "bitwise": true, + "camelcase": true, + "curly": false, + "eqeqeq": true, + "es3": false, + "forin": true, + "immed": false, + "indent": false, + "latedef": "nofunc", + "newcap": false, + "noarg": true, + "noempty": true, + "nonew": false, + "plusplus": false, + "quotmark": true, + "undef": true, + "unused": "vars", + "strict": false, + "trailing": true, + "maxparams": 5, + "maxdepth": false, + "maxstatements": false, + "maxcomplexity": false, + "maxlen": 100, + + "asi": true, + "expr": true, + "globalstrict": true, + "smarttabs": true, + "sub": true, + + "node": true, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false + } +} diff --git a/node_modules/urix/LICENSE b/node_modules/urix/LICENSE new file mode 100644 index 0000000000..0595be3671 --- /dev/null +++ b/node_modules/urix/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/urix/index.js b/node_modules/urix/index.js new file mode 100644 index 0000000000..dc6ef2700f --- /dev/null +++ b/node_modules/urix/index.js @@ -0,0 +1,17 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") + +"use strict" + +function urix(aPath) { + if (path.sep === "\\") { + return aPath + .replace(/\\/g, "/") + .replace(/^[a-z]:\/?/i, "/") + } + return aPath +} + +module.exports = urix diff --git a/node_modules/urix/package.json b/node_modules/urix/package.json new file mode 100644 index 0000000000..992e329594 --- /dev/null +++ b/node_modules/urix/package.json @@ -0,0 +1,25 @@ +{ + "name": "urix", + "version": "0.1.0", + "author": "Simon Lydell", + "license": "MIT", + "description": "Makes Windows-style paths more unix and URI friendly.", + "main": "index.js", + "repository": "lydell/urix", + "keywords": [ + "path", + "url", + "uri", + "unix", + "windows", + "backslash", + "slash" + ], + "scripts": { + "test": "jshint index.js test/ && mocha" + }, + "devDependencies": { + "mocha": "^1.17.1", + "jshint": "^2.4.4" + } +} diff --git a/node_modules/urix/readme.md b/node_modules/urix/readme.md new file mode 100644 index 0000000000..b258b98635 --- /dev/null +++ b/node_modules/urix/readme.md @@ -0,0 +1,46 @@ +[![Build Status](https://travis-ci.org/lydell/urix.png?branch=master)](https://travis-ci.org/lydell/urix) + +Overview +======== + +Makes Windows-style paths more unix and URI friendly. Useful if you work with +paths that eventually will be used in URLs. + +```js +var urix = require("urix") + +// On Windows: +urix("c:\\users\\you\\foo") +// /users/you/foo + +// On unix-like systems: +urix("c:\\users\\you\\foo") +// c:\users\you\foo +``` + + +Installation +============ + +`npm install urix` + +```js +var urix = require("urix") +``` + + +Usage +===== + +### `urix(path)` ### + +On Windows, replaces all backslashes with slashes and uses a slash instead of a +drive letter and a colon for absolute paths. + +On unix-like systems it is a no-op. + + +License +======= + +[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/urix/test/index.js b/node_modules/urix/test/index.js new file mode 100644 index 0000000000..5333f24635 --- /dev/null +++ b/node_modules/urix/test/index.js @@ -0,0 +1,43 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") +var assert = require("assert") +var urix = require("../") + +"use stict" + +function test(testPath, expected) { + path.sep = "\\" + assert.equal(urix(testPath), expected) + path.sep = "/" + assert.equal(urix(testPath), testPath) +} + +describe("urix", function() { + + it("is a function", function() { + assert.equal(typeof urix, "function") + }) + + + it("converts backslashes to slashes", function() { + test("a\\b\\c", "a/b/c") + test("\\a\\b\\c", "/a/b/c") + test("a/b\\c", "a/b/c") + test("\\\\a\\\\\\b///c", "//a///b///c") + }) + + + it("changes the drive letter to a slash", function() { + test("c:\\a", "/a") + test("C:\\a", "/a") + test("z:\\a", "/a") + test("c:a", "/a") + test("c:/a", "/a") + test("c:\\\\a", "//a") + test("c://a", "//a") + test("c:\\//a", "///a") + }) + +}) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..4f5e3ab2f2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,38 @@ +{ + "name": "GobContextGas", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "GobContextGas", + "dependencies": { + "resolve-url": "^0.2.1", + "urix": "^0.1.0" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + } + }, + "dependencies": { + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..8d7a4d3861 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "resolve-url": "^0.2.1", + "urix": "^0.1.0" + } +} diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 50f6d5409b..f9e914b4a1 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -76,11 +76,15 @@ struct List.map f in let xs = get_string_list "ana.activated" in + let callstring_enabled = (mem "callstring_fundec" xs) || (mem "callstring_stmt" xs) in + let cont_callstring = filter (fun x -> x <> "callstring_fundec" && x <> "callstring_stmt") xs in (*the contexts that are insensitive due to the callstring approach*) let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; path_sens := map' find_id @@ get_string_list "ana.path_sens"; - cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + if callstring_enabled + then cont_inse := map' find_id cont_callstring + else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; check_deps !activated; activated := topo_sort_an !activated; activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; @@ -105,7 +109,7 @@ struct let ys = fold_left one_el [] xs in List.rev ys, !dead - let context fd x = + let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> if mem n !cont_inse then @@ -180,13 +184,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 55b223ba0e..7d4d6c7805 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -586,9 +586,7 @@ "wideningThresholds", "memsafetySpecification", "termination", - "tmpSpecialAnalysis", - "callstring_fundec", - "callstring_stmt" + "tmpSpecialAnalysis" ] }, "default": [ @@ -690,7 +688,11 @@ "title": "ana.base.strings.domain", "description": "Domain for string literals.", "type": "string", - "enum": ["unit", "flat", "disjoint"], + "enum": [ + "unit", + "flat", + "disjoint" + ], "default": "flat" } }, @@ -2298,7 +2300,7 @@ }, "memleak": { "title": "warn.memleak", - "type":"object", + "type": "object", "properties": { "memcleanup": { "title": "warn.memleak.memcleanup", From 1cdefeb8f842c9de04e94e1f7d250b4bdfb9f176 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 6 Dec 2023 12:06:22 +0100 Subject: [PATCH 030/128] now also multiple calls are handled properly by the callstring Ana; added testcaseses using both callstring Anas --- node_modules/.package-lock.json | 19 ----- node_modules/resolve-url/.jshintrc | 44 ---------- node_modules/resolve-url/LICENSE | 21 ----- node_modules/resolve-url/bower.json | 15 ---- node_modules/resolve-url/changelog.md | 15 ---- node_modules/resolve-url/component.json | 15 ---- node_modules/resolve-url/package.json | 34 -------- node_modules/resolve-url/readme.md | 83 ------------------- node_modules/resolve-url/resolve-url.js | 47 ----------- node_modules/resolve-url/test/resolve-url.js | 70 ---------------- node_modules/urix/.jshintrc | 42 ---------- node_modules/urix/LICENSE | 21 ----- node_modules/urix/index.js | 17 ---- node_modules/urix/package.json | 25 ------ node_modules/urix/readme.md | 46 ---------- node_modules/urix/test/index.js | 43 ---------- package-lock.json | 38 --------- src/analyses/callstringAnalysis.ml | 16 ++-- .../84-callstring_both/01-simple_rec_sens.c | 22 +++++ .../84-callstring_both/02-simple_rec_ins.c | 22 +++++ .../84-callstring_both/03-multiple_rec_sens.c | 59 +++++++++++++ .../84-callstring_both/04-multiple_rec_ins.c | 59 +++++++++++++ 22 files changed, 171 insertions(+), 602 deletions(-) delete mode 100644 node_modules/.package-lock.json delete mode 100644 node_modules/resolve-url/.jshintrc delete mode 100644 node_modules/resolve-url/LICENSE delete mode 100644 node_modules/resolve-url/bower.json delete mode 100644 node_modules/resolve-url/changelog.md delete mode 100644 node_modules/resolve-url/component.json delete mode 100644 node_modules/resolve-url/package.json delete mode 100644 node_modules/resolve-url/readme.md delete mode 100644 node_modules/resolve-url/resolve-url.js delete mode 100644 node_modules/resolve-url/test/resolve-url.js delete mode 100644 node_modules/urix/.jshintrc delete mode 100644 node_modules/urix/LICENSE delete mode 100644 node_modules/urix/index.js delete mode 100644 node_modules/urix/package.json delete mode 100644 node_modules/urix/readme.md delete mode 100644 node_modules/urix/test/index.js delete mode 100644 package-lock.json create mode 100644 tests/regression/84-callstring_both/01-simple_rec_sens.c create mode 100644 tests/regression/84-callstring_both/02-simple_rec_ins.c create mode 100644 tests/regression/84-callstring_both/03-multiple_rec_sens.c create mode 100644 tests/regression/84-callstring_both/04-multiple_rec_ins.c diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json deleted file mode 100644 index 1ea8705627..0000000000 --- a/node_modules/.package-lock.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "GobContextGas", - "lockfileVersion": 2, - "requires": true, - "packages": { - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - } - } -} diff --git a/node_modules/resolve-url/.jshintrc b/node_modules/resolve-url/.jshintrc deleted file mode 100644 index aaf335801c..0000000000 --- a/node_modules/resolve-url/.jshintrc +++ /dev/null @@ -1,44 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": false, - "eqeqeq": true, - "es3": true, - "forin": true, - "immed": false, - "indent": false, - "latedef": "nofunc", - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": false, - "undef": true, - "unused": "vars", - "strict": false, - "trailing": true, - "maxparams": 5, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 100, - - "asi": true, - "expr": true, - "globalstrict": true, - "smarttabs": true, - "sub": true, - - "node": true, - "browser": true, - "globals": { - "describe": false, - "it": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false, - "define": false - } -} diff --git a/node_modules/resolve-url/LICENSE b/node_modules/resolve-url/LICENSE deleted file mode 100644 index 0595be3671..0000000000 --- a/node_modules/resolve-url/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/resolve-url/bower.json b/node_modules/resolve-url/bower.json deleted file mode 100644 index 31aa6f4ea7..0000000000 --- a/node_modules/resolve-url/bower.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "authors": ["Simon Lydell"], - "license": "MIT", - "main": "resolve-url.js", - "keywords": [ - "resolve", - "url" - ], - "ignore": [ - ".*" - ] -} diff --git a/node_modules/resolve-url/changelog.md b/node_modules/resolve-url/changelog.md deleted file mode 100644 index 2a4a6304ca..0000000000 --- a/node_modules/resolve-url/changelog.md +++ /dev/null @@ -1,15 +0,0 @@ -### Version 0.2.1 (2014-02-25) ### - -- Fix edge case when (accidentally) supplying only one argument, and that - argument happens to be a falsy value such as `undefined` or `null`. - - -### Version 0.2.0 (2014-02-24) ### - -- Disallow passing 0 arguments. It’s weird and inconsistent between browsers. - (Backwards incompatible change.) - - -### Version 0.1.0 (2014-02-23) ### - -- Initial release. diff --git a/node_modules/resolve-url/component.json b/node_modules/resolve-url/component.json deleted file mode 100644 index f37cf00554..0000000000 --- a/node_modules/resolve-url/component.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "license": "MIT", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "main": "resolve-url.js", - "repo": "lydell/resolve-url", - "keywords": [ - "resolve", - "url" - ], - "scripts": [ - "resolve-url.js" - ] -} diff --git a/node_modules/resolve-url/package.json b/node_modules/resolve-url/package.json deleted file mode 100644 index 9442366332..0000000000 --- a/node_modules/resolve-url/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "author": "Simon Lydell", - "license": "MIT", - "main": "resolve-url.js", - "repository": "lydell/resolve-url", - "keywords": [ - "resolve", - "url" - ], - "scripts": { - "test": "jshint resolve-url.js test/ && testling -u" - }, - "devDependencies": { - "testling": "~1.6.0", - "jshint": "~2.4.3", - "tape": "~2.5.0" - }, - "testling": { - "files": "test/*.js", - "browsers": [ - "ie/8..latest", - "chrome/latest", - "firefox/latest", - "opera/12", - "opera/latest", - "safari/5", - "iphone/6", - "android-browser/4" - ] - } -} diff --git a/node_modules/resolve-url/readme.md b/node_modules/resolve-url/readme.md deleted file mode 100644 index edfff7357c..0000000000 --- a/node_modules/resolve-url/readme.md +++ /dev/null @@ -1,83 +0,0 @@ -Overview -======== - -[![browser support](https://ci.testling.com/lydell/resolve-url.png)](https://ci.testling.com/lydell/resolve-url) - -Like Node.js’ [`path.resolve`]/[`url.resolve`] for the browser. - -```js -var resolveUrl = require("resolve-url") - -window.location -// https://example.com/articles/resolving-urls/edit - -resolveUrl("remove") -// https://example.com/articles/resolving-urls/remove - -resolveUrl("/static/scripts/app.js") -// https://example.com/static/scripts/app.js - -// Imagine /static/scripts/app.js contains `//# sourceMappingURL=../source-maps/app.js.map` -resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map") -// https://example.com/static/source-maps/app.js.map - -resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee") -// https://example.com/static/coffee/app.coffee - -resolveUrl("//cdn.example.com/jquery.js") -// https://cdn.example.com/jquery.js - -resolveUrl("http://foo.org/") -// http://foo.org/ -``` - - -Installation -============ - -- `npm install resolve-url` -- `bower install resolve-url` -- `component install lydell/resolve-url` - -Works with CommonJS, AMD and browser globals, through UMD. - - -Usage -===== - -### `resolveUrl(...urls)` ### - -Pass one or more urls. Resolves the last one to an absolute url, using the -previous ones and `window.location`. - -It’s like starting out on `window.location`, and then clicking links with the -urls as `href` attributes in order, from left to right. - -Unlike Node.js’ [`path.resolve`], this function always goes through all of the -arguments, from left to right. `path.resolve` goes from right to left and only -in the worst case goes through them all. Should that matter. - -Actually, the function is _really_ like clicking a lot of links in series: An -actual `` gets its `href` attribute set for each url! This means that the -url resolution of the browser is used, which makes this module really -light-weight. - -Also note that this functions deals with urls, not paths, so in that respect it -has more in common with Node.js’ [`url.resolve`]. But the arguments are more -like [`path.resolve`]. - -[`path.resolve`]: http://nodejs.org/api/path.html#path_path_resolve_from_to -[`url.resolve`]: http://nodejs.org/api/url.html#url_url_resolve_from_to - - -Tests -===== - -Run `npm test`, which lints the code and then gives you a link to open in a -browser of choice (using `testling`). - - -License -======= - -[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/resolve-url/resolve-url.js b/node_modules/resolve-url/resolve-url.js deleted file mode 100644 index 19e8d040ec..0000000000 --- a/node_modules/resolve-url/resolve-url.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -void (function(root, factory) { - if (typeof define === "function" && define.amd) { - define(factory) - } else if (typeof exports === "object") { - module.exports = factory() - } else { - root.resolveUrl = factory() - } -}(this, function() { - - function resolveUrl(/* ...urls */) { - var numUrls = arguments.length - - if (numUrls === 0) { - throw new Error("resolveUrl requires at least one argument; got none.") - } - - var base = document.createElement("base") - base.href = arguments[0] - - if (numUrls === 1) { - return base.href - } - - var head = document.getElementsByTagName("head")[0] - head.insertBefore(base, head.firstChild) - - var a = document.createElement("a") - var resolved - - for (var index = 1; index < numUrls; index++) { - a.href = arguments[index] - resolved = a.href - base.href = resolved - } - - head.removeChild(base) - - return resolved - } - - return resolveUrl - -})); diff --git a/node_modules/resolve-url/test/resolve-url.js b/node_modules/resolve-url/test/resolve-url.js deleted file mode 100644 index 18532edd32..0000000000 --- a/node_modules/resolve-url/test/resolve-url.js +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var test = require("tape") - -var resolveUrl = require("../") - -"use strict" - -test("resolveUrl", function(t) { - - t.plan(7) - - t.equal(typeof resolveUrl, "function", "is a function") - - t.equal( - resolveUrl("https://example.com/"), - "https://example.com/" - ) - - var loc = "https://example.com/articles/resolving-urls/edit" - - t.equal( - resolveUrl(loc, "remove"), - "https://example.com/articles/resolving-urls/remove" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js"), - "https://example.com/static/scripts/app.js" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map"), - "https://example.com/static/source-maps/app.js.map" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee"), - "https://example.com/static/coffee/app.coffee" - ) - - t.equal( - resolveUrl(loc, "//cdn.example.com/jquery.js"), - "https://cdn.example.com/jquery.js" - ) - -}) - -test("edge cases", function(t) { - - t.plan(4) - - t["throws"](resolveUrl, /at least one argument/, "throws with no arguments") - - var accidentallyUndefined - var result - t.doesNotThrow( - function() { result = resolveUrl(accidentallyUndefined) }, - "undefined is still an argument" - ) - t.ok(result.match(/\/undefined$/), "undefined is stringified") - - t.equal( - resolveUrl("http://foo.org/test", undefined, {}, ["a/b"], null), - "http://foo.org/a/null", - "arguments are stringified" - ) - -}) diff --git a/node_modules/urix/.jshintrc b/node_modules/urix/.jshintrc deleted file mode 100644 index 9d1a618361..0000000000 --- a/node_modules/urix/.jshintrc +++ /dev/null @@ -1,42 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": false, - "eqeqeq": true, - "es3": false, - "forin": true, - "immed": false, - "indent": false, - "latedef": "nofunc", - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": true, - "undef": true, - "unused": "vars", - "strict": false, - "trailing": true, - "maxparams": 5, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 100, - - "asi": true, - "expr": true, - "globalstrict": true, - "smarttabs": true, - "sub": true, - - "node": true, - "globals": { - "describe": false, - "it": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false - } -} diff --git a/node_modules/urix/LICENSE b/node_modules/urix/LICENSE deleted file mode 100644 index 0595be3671..0000000000 --- a/node_modules/urix/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/urix/index.js b/node_modules/urix/index.js deleted file mode 100644 index dc6ef2700f..0000000000 --- a/node_modules/urix/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = require("path") - -"use strict" - -function urix(aPath) { - if (path.sep === "\\") { - return aPath - .replace(/\\/g, "/") - .replace(/^[a-z]:\/?/i, "/") - } - return aPath -} - -module.exports = urix diff --git a/node_modules/urix/package.json b/node_modules/urix/package.json deleted file mode 100644 index 992e329594..0000000000 --- a/node_modules/urix/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "urix", - "version": "0.1.0", - "author": "Simon Lydell", - "license": "MIT", - "description": "Makes Windows-style paths more unix and URI friendly.", - "main": "index.js", - "repository": "lydell/urix", - "keywords": [ - "path", - "url", - "uri", - "unix", - "windows", - "backslash", - "slash" - ], - "scripts": { - "test": "jshint index.js test/ && mocha" - }, - "devDependencies": { - "mocha": "^1.17.1", - "jshint": "^2.4.4" - } -} diff --git a/node_modules/urix/readme.md b/node_modules/urix/readme.md deleted file mode 100644 index b258b98635..0000000000 --- a/node_modules/urix/readme.md +++ /dev/null @@ -1,46 +0,0 @@ -[![Build Status](https://travis-ci.org/lydell/urix.png?branch=master)](https://travis-ci.org/lydell/urix) - -Overview -======== - -Makes Windows-style paths more unix and URI friendly. Useful if you work with -paths that eventually will be used in URLs. - -```js -var urix = require("urix") - -// On Windows: -urix("c:\\users\\you\\foo") -// /users/you/foo - -// On unix-like systems: -urix("c:\\users\\you\\foo") -// c:\users\you\foo -``` - - -Installation -============ - -`npm install urix` - -```js -var urix = require("urix") -``` - - -Usage -===== - -### `urix(path)` ### - -On Windows, replaces all backslashes with slashes and uses a slash instead of a -drive letter and a colon for absolute paths. - -On unix-like systems it is a no-op. - - -License -======= - -[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/urix/test/index.js b/node_modules/urix/test/index.js deleted file mode 100644 index 5333f24635..0000000000 --- a/node_modules/urix/test/index.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = require("path") -var assert = require("assert") -var urix = require("../") - -"use stict" - -function test(testPath, expected) { - path.sep = "\\" - assert.equal(urix(testPath), expected) - path.sep = "/" - assert.equal(urix(testPath), testPath) -} - -describe("urix", function() { - - it("is a function", function() { - assert.equal(typeof urix, "function") - }) - - - it("converts backslashes to slashes", function() { - test("a\\b\\c", "a/b/c") - test("\\a\\b\\c", "/a/b/c") - test("a/b\\c", "a/b/c") - test("\\\\a\\\\\\b///c", "//a///b///c") - }) - - - it("changes the drive letter to a slash", function() { - test("c:\\a", "/a") - test("C:\\a", "/a") - test("z:\\a", "/a") - test("c:a", "/a") - test("c:/a", "/a") - test("c:\\\\a", "//a") - test("c://a", "//a") - test("c:\\//a", "///a") - }) - -}) diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 4f5e3ab2f2..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "GobContextGas", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "GobContextGas", - "dependencies": { - "resolve-url": "^0.2.1", - "urix": "^0.1.0" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - } - }, - "dependencies": { - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" - } - } -} diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 94a4e93aab..1edf14540c 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -48,17 +48,17 @@ struct let startstate v = [] let exitstate v = [] - let context fd d = d - let enter ctx r f args = let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (ctx.local) elem in - let ctx' = {ctx with context = (fun () -> new_stack) - ; local = new_stack} in - if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) [ctx.local, new_stack] + + let combine_env ctx lval fexp f args fc au f_ask = + ctx.local end + module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" @@ -76,9 +76,11 @@ end module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" - let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + let pushElem f args ctx = + match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) | Statement stmt -> [stmt] - | _ -> printf "not a stmt\n"; [] + | _ -> [] (* first statement is filtered*) + let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); diff --git a/tests/regression/84-callstring_both/01-simple_rec_sens.c b/tests/regression/84-callstring_both/01-simple_rec_sens.c new file mode 100644 index 0000000000..210ecfb4d8 --- /dev/null +++ b/tests/regression/84-callstring_both/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/84-callstring_both/02-simple_rec_ins.c b/tests/regression/84-callstring_both/02-simple_rec_ins.c new file mode 100644 index 0000000000..7be2bedcf7 --- /dev/null +++ b/tests/regression/84-callstring_both/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/84-callstring_both/03-multiple_rec_sens.c b/tests/regression/84-callstring_both/03-multiple_rec_sens.c new file mode 100644 index 0000000000..0b7977a28f --- /dev/null +++ b/tests/regression/84-callstring_both/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/84-callstring_both/04-multiple_rec_ins.c b/tests/regression/84-callstring_both/04-multiple_rec_ins.c new file mode 100644 index 0000000000..65903ff22d --- /dev/null +++ b/tests/regression/84-callstring_both/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} From 343f83d697406e4f082473c89334b1c377d4676f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 6 Dec 2023 14:40:17 +0100 Subject: [PATCH 031/128] 2 lists for stack representation in callstring --- src/analyses/callstringAnalysis.ml | 58 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 1edf14540c..da5127a2f6 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -8,8 +8,8 @@ module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> (t list * t list) -> (t list * t list) -> unit (* a helper function to print the callstack *) end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context @@ -21,22 +21,20 @@ struct (* simulates a call stack of depth k*) module CallStack = struct - include Printable.Liszt (CT) + include Printable.Prod (Printable.Liszt (CT)) (Printable.Liszt (CT)) let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) + let length (stack_first, stack_last) = List.length stack_first + List.length stack_last let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = depth - List.length elem in - if remaining_space >= 0 - then - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem - else - List.rev(take depth (List.rev elem)) + match elem with + | None -> stack + | Some e -> + match (length stack >= depth), stack with + | _, ([], []) -> [e], [] + | false, ([], last) -> List.rev last, [e] + | false, (stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] + | true, ([], last) -> List.tl(List.rev(last)), [e] + | true, (s::stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] end module D = Lattice.Fake(CallStack) @@ -45,12 +43,12 @@ struct module G = Lattice.Unit let name () = "callstring_"^ CT.stackTypeName - let startstate v = [] - let exitstate v = [] + let startstate v = ([],[]) + let exitstate v = ([],[]) let enter ctx r f args = - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (ctx.local) elem in + let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack: CallStack.t = CallStack.push ctx.local elem in if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) [ctx.local, new_stack] @@ -62,14 +60,16 @@ end module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" - let pushElem f args ctx = [f] + let pushElem f args ctx = Some f - let printStack f expL listA listB = + let printStack f expL (listA1, listA2) (listB1, listB2) = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listA2); printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listB2); printf "\n\n" end @@ -78,16 +78,18 @@ module Stmt:Callstack_Type = struct let stackTypeName = "stmt" let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) - | Statement stmt -> [stmt] - | _ -> [] (* first statement is filtered*) + | Statement stmt -> Some stmt + | _ -> None (* first statement is filtered*) - let printStack f expL listA listB = + let printStack f expL (listA1, listA2) (listB1, listB2) = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listA2); printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listB2); printf "\n\n" end From 0ad54b5e422985a31a1e433fac9b6a6301c8a095 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Dec 2023 11:21:58 +0100 Subject: [PATCH 032/128] added location for callstack type, added queue impl in printable, added sv comp files, added tests for loc --- conf/svcomp80-context_gas.json | 98 +++++++++++++++++ conf/svcomp82-callstringFundec.json | 99 +++++++++++++++++ conf/svcomp83-callstringLoc.json | 99 +++++++++++++++++ conf/svcomp84-callstringBoth.json | 100 ++++++++++++++++++ src/analyses/callstringAnalysis.ml | 25 ++++- src/common/domains/printable.ml | 35 ++++++ .../85-callstring_Loc/01-simple_rec_sens.c | 22 ++++ .../85-callstring_Loc/02-simple_rec_ins.c | 22 ++++ .../85-callstring_Loc/03-multiple_rec_sens.c | 59 +++++++++++ .../85-callstring_Loc/04-multiple_rec_ins.c | 59 +++++++++++ .../05-function_chain_sens.c | 54 ++++++++++ .../85-callstring_Loc/06-function_chain_ins.c | 54 ++++++++++ .../85-callstring_Loc/07-call_in_call.c | 54 ++++++++++ .../08-circle_call_and_big_loop.c | 46 ++++++++ 14 files changed, 824 insertions(+), 2 deletions(-) create mode 100644 conf/svcomp80-context_gas.json create mode 100644 conf/svcomp82-callstringFundec.json create mode 100644 conf/svcomp83-callstringLoc.json create mode 100644 conf/svcomp84-callstringBoth.json create mode 100644 tests/regression/85-callstring_Loc/01-simple_rec_sens.c create mode 100644 tests/regression/85-callstring_Loc/02-simple_rec_ins.c create mode 100644 tests/regression/85-callstring_Loc/03-multiple_rec_sens.c create mode 100644 tests/regression/85-callstring_Loc/04-multiple_rec_ins.c create mode 100644 tests/regression/85-callstring_Loc/05-function_chain_sens.c create mode 100644 tests/regression/85-callstring_Loc/06-function_chain_ins.c create mode 100644 tests/regression/85-callstring_Loc/07-call_in_call.c create mode 100644 tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c diff --git a/conf/svcomp80-context_gas.json b/conf/svcomp80-context_gas.json new file mode 100644 index 0000000000..9647039e25 --- /dev/null +++ b/conf/svcomp80-context_gas.json @@ -0,0 +1,98 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": true, + "ctx_gas_value": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp82-callstringFundec.json b/conf/svcomp82-callstringFundec.json new file mode 100644 index 0000000000..c34af435dc --- /dev/null +++ b/conf/svcomp82-callstringFundec.json @@ -0,0 +1,99 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_fundec" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp83-callstringLoc.json b/conf/svcomp83-callstringLoc.json new file mode 100644 index 0000000000..d13afb3a13 --- /dev/null +++ b/conf/svcomp83-callstringLoc.json @@ -0,0 +1,99 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_loc" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp84-callstringBoth.json b/conf/svcomp84-callstringBoth.json new file mode 100644 index 0000000000..5ea84689db --- /dev/null +++ b/conf/svcomp84-callstringBoth.json @@ -0,0 +1,100 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_fundec", + "callstring_loc" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index da5127a2f6..525aa31339 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -26,7 +26,7 @@ struct let length (stack_first, stack_last) = List.length stack_first + List.length stack_last let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - match elem with + match elem with | None -> stack | Some e -> match (length stack >= depth), stack with @@ -93,9 +93,30 @@ module Stmt:Callstack_Type = struct printf "\n\n" end + +module Location:Callstack_Type = struct + include CilType.Location + let stackTypeName = "loc" + let pushElem f args ctx = + let q = Queue.create () in + Queue.push 1 q; + Some !Tracing.current_loc + + let printStack f expL (listA1, listA2) (listB1, listB2) = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listA2); + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listB2); + printf "\n\n" +end + (* Lifters for the Callstring approach with different Callstack element types*) let _ = MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) - MCP.register_analysis (module Spec (Stmt) : MCPSpec) (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index 68ce3b74d3..697e3935f7 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -506,6 +506,41 @@ module Prod4 (Base1: S) (Base2: S) (Base3: S) (Base4: S) = struct let arbitrary () = QCheck.quad (Base1.arbitrary ()) (Base2.arbitrary ()) (Base3.arbitrary ()) (Base4.arbitrary ()) end + +module Queue (Base: S) = +struct + type t = Base.t Queue.t + include Std + + let queue_map f q = + let mapped_queue = Queue.create () in + Queue.iter (fun x -> Queue.push (f x) mapped_queue) q; + mapped_queue + + let show x = + let elem = Queue.fold (fun acc elem -> elem :: acc) [] x |> List.rev in + "[" ^ (String.concat ", " elem) ^ "]" + + let pretty () x = text (show x) + let name () = Base.name () ^ "queue" + (* TODO more efficient impl*) + + let relift x = queue_map Base.relift x + + let printXml f xs = + let xs_copy = Queue.copy xs in + let rec loop n q = + if Queue.is_empty q then () + else + let x = Queue.pop q in + BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; + loop (n+1) (xs_copy) + in + BatPrintf.fprintf f "\n\n"; + loop 0 xs_copy; + BatPrintf.fprintf f "\n\n" +end + module Liszt (Base: S) = struct type t = Base.t list [@@deriving eq, ord, hash, to_yojson] diff --git a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c new file mode 100644 index 0000000000..d0639cae6a --- /dev/null +++ b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c new file mode 100644 index 0000000000..791742154d --- /dev/null +++ b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c new file mode 100644 index 0000000000..1ef2a12f89 --- /dev/null +++ b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c new file mode 100644 index 0000000000..b53aa47b32 --- /dev/null +++ b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/05-function_chain_sens.c b/tests/regression/85-callstring_Loc/05-function_chain_sens.c new file mode 100644 index 0000000000..18e6605dd3 --- /dev/null +++ b/tests/regression/85-callstring_Loc/05-function_chain_sens.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 12; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); +} diff --git a/tests/regression/85-callstring_Loc/06-function_chain_ins.c b/tests/regression/85-callstring_Loc/06-function_chain_ins.c new file mode 100644 index 0000000000..4ce249d956 --- /dev/null +++ b/tests/regression/85-callstring_Loc/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 13; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/07-call_in_call.c b/tests/regression/85-callstring_Loc/07-call_in_call.c new file mode 100644 index 0000000000..5ddb98235e --- /dev/null +++ b/tests/regression/85-callstring_Loc/07-call_in_call.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c new file mode 100644 index 0000000000..b730dfd3f8 --- /dev/null +++ b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} From 74610ab121703d52a066807379fc2126f03e998a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Dec 2023 14:36:18 +0100 Subject: [PATCH 033/128] implemented Queue completely, added new callstringAna for usage of queue (either the queue implementation or the 2 list implementation will stay) --- src/analyses/callstringAnalysis.ml | 4 +- src/analyses/callstringAnalysisQueue.ml | 118 ++++++++++++++++++++++++ src/common/domains/printable.ml | 25 ++++- 3 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 src/analyses/callstringAnalysisQueue.ml diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 525aa31339..d622d14c51 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -117,6 +117,4 @@ end let _ = MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) - MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) - - + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) \ No newline at end of file diff --git a/src/analyses/callstringAnalysisQueue.ml b/src/analyses/callstringAnalysisQueue.ml new file mode 100644 index 0000000000..45cc3f04ec --- /dev/null +++ b/src/analyses/callstringAnalysisQueue.ml @@ -0,0 +1,118 @@ +open Analyses +open Printf +open GoblintCil +open GobConfig + +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t Queue.t -> t Queue.t -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module Spec (CT:Callstack_Type) : MCPSpec = +struct + include Analyses.IdentitySpec + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Queue (CT) + let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + match elem with + | None -> stack + | Some e -> + Queue.push e stack; (* pushes new element to stack*) + (* remove elements from stack, till the depth k is guaranteed*) + let excess_length = max 0 (Queue.length stack - depth) in + for _ = 1 to excess_length do + ignore (Queue.pop stack) + done; + stack + end + + module D = Lattice.Fake(CallStack) + module C = CallStack + module V = EmptyV + module G = Lattice.Unit + module Q = Printable.Queue (Printable.Strings) + + let name () = "callstring_"^ CT.stackTypeName + let startstate v = Queue.create () + let exitstate v = Queue.create () + + let enter ctx r f args = + let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let old_stack: CallStack.t = Queue.copy ctx.local in + let new_stack: CallStack.t = CallStack.push old_stack elem in + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) + [ctx.local, new_stack] + + let combine_env ctx lval fexp f args fc au f_ask = + ctx.local +end + + +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "fundec" + let pushElem f args ctx = Some f + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" +end + +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "stmt" + let pushElem f args ctx = + match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> Some stmt + | _ -> None (* first statement is filtered*) + + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + + +module Location:Callstack_Type = struct + include CilType.Location + let stackTypeName = "loc" + let pushElem f args ctx = + let q = Queue.create () in + Queue.push 1 q; + Some !Tracing.current_loc + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +let _ = + MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) + + diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index 697e3935f7..5467e66d79 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -506,19 +506,18 @@ module Prod4 (Base1: S) (Base2: S) (Base3: S) (Base4: S) = struct let arbitrary () = QCheck.quad (Base1.arbitrary ()) (Base2.arbitrary ()) (Base3.arbitrary ()) (Base4.arbitrary ()) end - module Queue (Base: S) = struct type t = Base.t Queue.t include Std - + let queue_map f q = let mapped_queue = Queue.create () in Queue.iter (fun x -> Queue.push (f x) mapped_queue) q; mapped_queue let show x = - let elem = Queue.fold (fun acc elem -> elem :: acc) [] x |> List.rev in + let elem = Queue.fold (fun acc elem -> Base.show elem :: acc) [] x |> List.rev in "[" ^ (String.concat ", " elem) ^ "]" let pretty () x = text (show x) @@ -539,6 +538,26 @@ struct BatPrintf.fprintf f "\n\n"; loop 0 xs_copy; BatPrintf.fprintf f "\n\n" + + let rec equal_helper a b = + if Queue.is_empty a then true + else ( + let a_v = Queue.pop a in + let b_v = Queue.pop b in + if Base.equal a_v b_v + then equal_helper a b + else false) + + let equal a b = + if Queue.length a <> Queue.length b then false + else + let a_copy = Queue.copy a in + let b_copy = Queue.copy b in + equal_helper a_copy b_copy + + let to_yojson x = `String (show x) + let hash = Hashtbl.hash + let compare = Stdlib.compare end module Liszt (Base: S) = From 0a9986323a415e2bbde3d4aff3d936678a0041be Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 19 Oct 2023 10:59:34 +0200 Subject: [PATCH 034/128] added a new lifter in constraints, converted C to an option and tried to update transfer functions (may still need some updates) --- .devcontainer/devcontainer.json | 3 +- src/framework/constraints.ml | 63 ++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2bf28b3c6f..af25a29e3f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,7 +14,8 @@ "extensions": [ "ocamllabs.ocaml-platform", - "hackwaly.ocamlearlybird" + "hackwaly.ocamlearlybird", + "zepalmer.ocaml-indentation" ], "settings": {}, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 77d3a38186..1d25fce3e6 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -468,7 +468,7 @@ struct with Deadcode -> b let sync ctx reason = lift_fun ctx D.lift S.sync ((|>) reason) `Bot - + let enter ctx r f args = let liftmap = List.map (fun (x,y) -> D.lift x, D.lift y) in lift_fun ctx liftmap S.enter ((|>) args % (|>) f % (|>) r) [] @@ -496,6 +496,67 @@ struct let event (ctx:(D.t,G.t,C.t,V.t) ctx) (e:Events.t) (octx:(D.t,G.t,C.t,V.t) ctx):D.t = lift_fun ctx D.lift S.event ((|>) (conv octx) % (|>) e) `Bot end +(** Lifts a [Spec] with the context gas variable. TODO *) +module ContextGasLifter (S:Spec) + : Spec with module D = S.D + and module G = S.G += +struct + include S + module D = S.D + module G = S.G + module C = + struct + include Printable.Option (S.C) (struct let name = "context gas" end) + end + module V = S.V + module P = S.P + + let name () = S.name ()^" with context gas" + + let context fd d = None (* TODO*) + + let unlift c = + match c with + | Some x -> x + | None -> ctx_failwith "context gas" (*TODO*) + + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = + {ctx with context = (fun () -> unlift (ctx.context ())) } + + let convOpt c = + match c with + | Some x -> Some (unlift x) + | None -> None + + (*let lift_fun ctx g h b = + try h (g (conv ctx)) + with Ctx_failure _ -> b*) + + let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () + let query ctx (type a) (q: a Queries.t): a Queries.result = + try S.query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q + let assign ctx lval expr = try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () + let vdecl ctx v = try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () + let body ctx fundec = try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () + let branch ctx e tv = try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () + let return ctx r f = try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () + let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () + let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () + let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () + let enter ctx r f args = try S.enter (conv ctx) r f args with Ctx_failure _ -> [] + let combine_env ctx r fe f args fc es f_ask = + try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () + let combine_assign ctx r fe f args fc es f_ask = + try S.combine_assign (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () + let paths_as_set ctx = try S.paths_as_set (conv ctx) with Ctx_failure _ -> [] + let threadenter ctx lval f args = try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] + let threadspawn ctx lval f args fctx = try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () + let event ctx e octx = try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + +end + module type Increment = sig val increment: increment_data option From 874e4d683e56ac92d6b3473246f84c09ce3be010 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 19 Oct 2023 14:22:14 +0200 Subject: [PATCH 035/128] added lifter to control, added context gas in lifter, with this change 13 tests are failing --- src/framework/constraints.ml | 12 ++++++++---- src/framework/control.ml | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1d25fce3e6..d99f9f358e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -508,22 +508,22 @@ struct module C = struct include Printable.Option (S.C) (struct let name = "context gas" end) + let context_gas = ref 100 end module V = S.V module P = S.P let name () = S.name ()^" with context gas" - let context fd d = None (* TODO*) + let context fd d = if !C.context_gas == 0 then None else Some (S.context fd d) (* TODO*) let unlift c = match c with | Some x -> x | None -> ctx_failwith "context gas" (*TODO*) - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - {ctx with context = (fun () -> unlift (ctx.context ())) } + {ctx with context = (fun () -> unlift (ctx.context ())) } (*TODO eleganter?*) let convOpt c = match c with @@ -533,6 +533,11 @@ struct (*let lift_fun ctx g h b = try h (g (conv ctx)) with Ctx_failure _ -> b*) + + let enter ctx r f args = + try C.context_gas := !C.context_gas - 1; + S.enter (conv ctx) r f args + with Ctx_failure _ -> [] let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () let query ctx (type a) (q: a Queries.t): a Queries.result = @@ -545,7 +550,6 @@ struct let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - let enter ctx r f args = try S.enter (conv ctx) r f args with Ctx_failure _ -> [] let combine_env ctx r fe f args fc es f_ask = try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () let combine_assign ctx r fe f args fc es f_ask = diff --git a/src/framework/control.ml b/src/framework/control.ml index 00a6034e27..5aeb20007f 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -29,6 +29,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (not arg_enabled) (module PathSensitive2) |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) |> lift true (module DeadCodeLifter) + |> lift true (module ContextGasLifter) |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) From 3e395efe8b64e1655231c69552d393d944c4fb84 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 22 Oct 2023 18:17:15 +0200 Subject: [PATCH 036/128] changed constraints, added test case, not working if context gas = 0 --- src/framework/constraints.ml | 174 ++++++++++++++---- src/framework/control.ml | 6 +- .../01-simple-recursion-depth50.c | 17 ++ 3 files changed, 154 insertions(+), 43 deletions(-) create mode 100644 tests/regression/80-context_gas/01-simple-recursion-depth50.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d99f9f358e..a9c76e3a24 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -6,6 +6,7 @@ open GoblintCil open MyCFG open Analyses open GobConfig +include Printf module M = Messages @@ -468,7 +469,7 @@ struct with Deadcode -> b let sync ctx reason = lift_fun ctx D.lift S.sync ((|>) reason) `Bot - + let enter ctx r f args = let liftmap = List.map (fun (x,y) -> D.lift x, D.lift y) in lift_fun ctx liftmap S.enter ((|>) args % (|>) f % (|>) r) [] @@ -506,58 +507,151 @@ struct module D = S.D module G = S.G module C = - struct - include Printable.Option (S.C) (struct let name = "context gas" end) - let context_gas = ref 100 - end + struct + include Printable.Option (S.C) (struct let name = "context gas" end) + let context_gas = ref 10 + end module V = S.V module P = S.P let name () = S.name ()^" with context gas" - let context fd d = if !C.context_gas == 0 then None else Some (S.context fd d) (* TODO*) + let context fd d = (*printf "context";*) + if !C.context_gas == 0 then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) let unlift c = match c with - | Some x -> x - | None -> ctx_failwith "context gas" (*TODO*) + | Some x -> x + | None -> ctx_failwith "context gas" (*TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - {ctx with context = (fun () -> unlift (ctx.context ())) } (*TODO eleganter?*) - - let convOpt c = + (*if C.context_gas == 0 + then + {ctx with context = (fun () -> ) } + else*) + {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + + (*let convOpt c = match c with - | Some x -> Some (unlift x) - | None -> None + | Some x -> Some (unlift x) + | None -> None*) (*let lift_fun ctx g h b = try h (g (conv ctx)) with Ctx_failure _ -> b*) - + + let rec showExprList args = + match args with + | [] -> " " + | a::t -> (CilType.Exp.show a) ^ (showExprList t) + let enter ctx r f args = - try C.context_gas := !C.context_gas - 1; - S.enter (conv ctx) r f args - with Ctx_failure _ -> [] + (*printf "enter";*) + if !C.context_gas <> 0 then + try ( + if not !AnalysisState.postsolving + then + (C.context_gas := !C.context_gas - 1; + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)) + else printf " "; + S.enter (conv ctx) r f args ) + with Ctx_failure _ -> [] + else [] + + let sync ctx reason = + (*printf "sync";*) + if !C.context_gas <> 0 then + try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let query ctx (type a) (q: a Queries.t): a Queries.result = + (*printf "query";*) + if !C.context_gas <> 0 then + try query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q + else Queries.Result.bot q + + let assign ctx lval expr = + (*printf "assign";*) + if !C.context_gas <> 0 then + try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let vdecl ctx v = + (*printf "vdecl";*) + if !C.context_gas <> 0 then + try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () + else S.D.bot () + let body ctx fundec = + (*printf "body";*) + if !C.context_gas <> 0 then + try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let branch ctx e tv = + (*printf "branch";*) + if !C.context_gas <> 0 then + try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let return ctx r f = + (*printf "return";*) + if !C.context_gas <> 0 then + try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let asm ctx = + (*printf "asm";*) + if !C.context_gas <> 0 then + try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let skip ctx = + (*printf "skip";*) + if !C.context_gas <> 0 then + try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let special ctx r f args = + (*printf "special";*) + if !C.context_gas <> 0 then + try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let combine_env ctx r fe f args fc es f_ask = + (*printf "combine_env";*) + if !C.context_gas <> 0 then + try S.combine_env (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () + else S.D.bot () - let sync ctx reason = try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () - let query ctx (type a) (q: a Queries.t): a Queries.result = - try S.query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q - let assign ctx lval expr = try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () - let vdecl ctx v = try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () - let body ctx fundec = try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () - let branch ctx e tv = try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () - let return ctx r f = try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () - let asm ctx = try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () - let skip ctx = try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () - let special ctx r f args = try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - let combine_env ctx r fe f args fc es f_ask = - try S.combine_env (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () let combine_assign ctx r fe f args fc es f_ask = - try S.combine_assign (conv ctx) r fe f args (convOpt fc) es f_ask with Ctx_failure _ -> S.D.bot () - let paths_as_set ctx = try S.paths_as_set (conv ctx) with Ctx_failure _ -> [] - let threadenter ctx lval f args = try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] - let threadspawn ctx lval f args fctx = try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () - let event ctx e octx = try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + (*printf "combine_assign";*) + if !C.context_gas <> 0 then + try S.combine_assign (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let paths_as_set ctx = + (*printf "paths_as_set";*) + if !C.context_gas <> 0 then + try S.paths_as_set (conv ctx) with Ctx_failure _ -> [S.D.bot ()] + else [S.D.bot ()] + + let threadenter ctx lval f args = + (*printf "threadenter";*) + if !C.context_gas <> 0 then + try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] + else [] + + let threadspawn ctx lval f args fctx = + (*printf "threadspawn";*) + if !C.context_gas <> 0 then + try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () + + let event ctx e octx = + (*printf "event";*) + if !C.context_gas <> 0 then + try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () + else S.D.bot () end @@ -1197,7 +1291,7 @@ struct | `Lifted2 d -> LH.replace l' x d (* | `Bot -> () *) (* Since Verify2 is broken and only checks existing keys, add it with local bottom value. - This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) + This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) | `Bot -> LH.replace l' x (S.D.bot ()) | `Top -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has top value" | `Lifted1 _ -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has global value" @@ -1984,10 +2078,10 @@ struct in PP.iter f h1; (* let k1 = Set.of_enum @@ PP.keys h1 in - let k2 = Set.of_enum @@ PP.keys h2 in - let o1 = Set.cardinal @@ Set.diff k1 k2 in - let o2 = Set.cardinal @@ Set.diff k2 k1 in - Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) + let k2 = Set.of_enum @@ PP.keys h2 in + let o1 = Set.cardinal @@ Set.diff k1 k2 in + let o2 = Set.cardinal @@ Set.diff k2 k1 in + Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) Printf.printf "locals: \tequal = %d\tleft = %d\tright = %d\tincomparable = %d\n" !eq !le !gr !uk let compare_locals_ctx h1 h2 = diff --git a/src/framework/control.ml b/src/framework/control.ml index 5aeb20007f..0bfa09e518 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,7 +20,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) + (module MCP.MCP2 : Spec) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) @@ -28,8 +28,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift arg_enabled (module WitnessConstraints.PathSensitive3) |> lift (not arg_enabled) (module PathSensitive2) |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift true (module ContextGasLifter) + |> lift true (module DeadCodeLifter) |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) @@ -39,6 +38,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + |> lift true (module ContextGasLifter) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple-recursion-depth50.c new file mode 100644 index 0000000000..866492a34d --- /dev/null +++ b/tests/regression/80-context_gas/01-simple-recursion-depth50.c @@ -0,0 +1,17 @@ +// PARAM: --enable ana.int.interval +#include + +int global; + +int main(void) +{ + f(10); +} + +int f(int i) +{ + if (i > 0){ + i--; + f(i); + } +} From b917ec26973a3511c3fbf52f7f8c9d4fcde78b1e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 23 Oct 2023 12:03:01 +0200 Subject: [PATCH 037/128] just checking if the tests in github actions are now working :)), nothing major new happend --- src/framework/constraints.ml | 14 +----- src/framework/control.ml | 82 ++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 53 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a9c76e3a24..ee2baf2c8d 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -525,21 +525,11 @@ struct | None -> ctx_failwith "context gas" (*TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - (*if C.context_gas == 0 - then - {ctx with context = (fun () -> ) } + (*if !C.context_gas == 0 + then {ctx with context = (fun () -> )} else*) {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) - (*let convOpt c = - match c with - | Some x -> Some (unlift x) - | None -> None*) - - (*let lift_fun ctx g h b = - try h (g (conv ctx)) - with Ctx_failure _ -> b*) - let rec showExprList args = match args with | [] -> " " diff --git a/src/framework/control.ml b/src/framework/control.ml index 0bfa09e518..79195f7c81 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -34,7 +34,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) @@ -322,10 +322,10 @@ struct | MyCFG.Assign (lval,exp) -> if M.tracing then M.trace "global_inits" "Assign %a = %a\n" d_lval lval d_exp exp; (match lval, exp with - | (Var v,o), (AddrOf (Var f,NoOffset)) - when v.vstorage <> Static && isFunctionType f.vtype -> - (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) - | _ -> () + | (Var v,o), (AddrOf (Var f,NoOffset)) + when v.vstorage <> Static && isFunctionType f.vtype -> + (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) + | _ -> () ); let res = Spec.assign {ctx with local = st} lval exp in (* Needed for privatizations (e.g. None) that do not side immediately *) @@ -549,9 +549,9 @@ struct GobSys.mkdir_or_exists save_run; GobConfig.write_file config; let module Meta = struct - type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] - let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } - end + type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] + let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } + end in (* Yojson.Safe.to_file meta Meta.json; *) Yojson.Safe.pretty_to_channel (Stdlib.open_out (Fpath.to_string meta)) Meta.json; (* the above is compact, this is pretty-printed *) @@ -603,10 +603,10 @@ struct in let print_and_calculate_uncalled = function | GFun (fn, loc) when is_bad_uncalled fn.svar loc-> - let cnt = Cilfacade.countLoc fn in - uncalled_dead := !uncalled_dead + cnt; - if get_bool "ana.dead-code.functions" then - M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) + let cnt = Cilfacade.countLoc fn in + uncalled_dead := !uncalled_dead + cnt; + if get_bool "ana.dead-code.functions" then + M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) | _ -> () in List.iter print_and_calculate_uncalled file.globals; @@ -638,35 +638,35 @@ struct NodeH.modify_opt node join by_node; ); by_loc, by_node - in - - let ask ?(node = MyCFG.dummy_node) loc = - let f (type a) (q : a Queries.t) : a = - match Hashtbl.find_option joined_by_loc loc with - | None -> Queries.Result.bot q - | Some local -> Query.ask_local_node gh node local q - in - ({ f } : Queries.ask) - in - - (* A node is dead when its abstract value is bottom in all contexts; - it holds that: bottom in all contexts iff. bottom in the join of all contexts. - Therefore, we just answer whether the (stored) join is bottom. *) - let must_be_dead node = - NodeH.find_option joined_by_node node - (* nodes that didn't make it into the result are definitely dead (hence for_all) *) - |> GobOption.for_all Spec.D.is_bot - in - - let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in - - let skipped_statements from_node edge to_node = - CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] - in - - Transform.run_transformations file active_transformations - { ask ; must_be_dead ; must_be_uncalled ; - cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; + in + + let ask ?(node = MyCFG.dummy_node) loc = + let f (type a) (q : a Queries.t) : a = + match Hashtbl.find_option joined_by_loc loc with + | None -> Queries.Result.bot q + | Some local -> Query.ask_local_node gh node local q + in + ({ f } : Queries.ask) + in + + (* A node is dead when its abstract value is bottom in all contexts; + it holds that: bottom in all contexts iff. bottom in the join of all contexts. + Therefore, we just answer whether the (stored) join is bottom. *) + let must_be_dead node = + NodeH.find_option joined_by_node node + (* nodes that didn't make it into the result are definitely dead (hence for_all) *) + |> GobOption.for_all Spec.D.is_bot + in + + let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in + + let skipped_statements from_node edge to_node = + CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] + in + + Transform.run_transformations file active_transformations + { ask ; must_be_dead ; must_be_uncalled ; + cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; ); lh, gh From d6e0940dbeb1ac106866800d7ae431c128275047 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 1 Nov 2023 16:59:50 +0100 Subject: [PATCH 038/128] added two testcases; fixed a copy paste error in query; deleted debugging prints; made it compact and nice --- src/framework/constraints.ml | 156 ++++-------------- .../01-simple-recursion-depth50.c | 20 ++- .../80-context_gas/02-two-recursions.c | 40 +++++ .../03-special-values-handeling.c | 22 +++ 4 files changed, 111 insertions(+), 127 deletions(-) create mode 100644 tests/regression/80-context_gas/02-two-recursions.c create mode 100644 tests/regression/80-context_gas/03-special-values-handeling.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ee2baf2c8d..2aaf8c1404 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -508,140 +508,50 @@ struct module G = S.G module C = struct - include Printable.Option (S.C) (struct let name = "context gas" end) + include Printable.Option (S.C) (struct let name = "contextGas" end) let context_gas = ref 10 end module V = S.V module P = S.P - let name () = S.name ()^" with context gas" - - let context fd d = (*printf "context";*) - if !C.context_gas == 0 then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) - - let unlift c = - match c with - | Some x -> x - | None -> ctx_failwith "context gas" (*TODO*) - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = - (*if !C.context_gas == 0 - then {ctx with context = (fun () -> )} - else*) - {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) - - let rec showExprList args = + let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " | a::t -> (CilType.Exp.show a) ^ (showExprList t) + let name () = S.name ()^" with context gas" + + let context fd d = + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) + then {ctx with context = (fun () -> ctx_failwith "contextGas") } + else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + let enter ctx r f args = - (*printf "enter";*) - if !C.context_gas <> 0 then - try ( - if not !AnalysisState.postsolving - then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)) - else printf " "; - S.enter (conv ctx) r f args ) - with Ctx_failure _ -> [] - else [] - - let sync ctx reason = - (*printf "sync";*) - if !C.context_gas <> 0 then - try S.sync (conv ctx) reason with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let query ctx (type a) (q: a Queries.t): a Queries.result = - (*printf "query";*) - if !C.context_gas <> 0 then - try query (conv ctx) q with Ctx_failure _ -> Queries.Result.bot q - else Queries.Result.bot q - - let assign ctx lval expr = - (*printf "assign";*) - if !C.context_gas <> 0 then - try S.assign (conv ctx) lval expr with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let vdecl ctx v = - (*printf "vdecl";*) - if !C.context_gas <> 0 then - try S.vdecl (conv ctx) v with Ctx_failure _ -> S.D.bot () - else S.D.bot () - let body ctx fundec = - (*printf "body";*) - if !C.context_gas <> 0 then - try S.body (conv ctx) fundec with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let branch ctx e tv = - (*printf "branch";*) - if !C.context_gas <> 0 then - try S.branch (conv ctx) e tv with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let return ctx r f = - (*printf "return";*) - if !C.context_gas <> 0 then - try S.return (conv ctx) r f with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let asm ctx = - (*printf "asm";*) - if !C.context_gas <> 0 then - try S.asm (conv ctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let skip ctx = - (*printf "skip";*) - if !C.context_gas <> 0 then - try S.skip (conv ctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let special ctx r f args = - (*printf "special";*) - if !C.context_gas <> 0 then - try S.special (conv ctx) r f args with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let combine_env ctx r fe f args fc es f_ask = - (*printf "combine_env";*) - if !C.context_gas <> 0 then - try S.combine_env (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () - else S.D.bot () + if (not !AnalysisState.postsolving) && (!C.context_gas > 0) + then + (C.context_gas := !C.context_gas - 1; + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + S.enter (conv ctx) r f args - let combine_assign ctx r fe f args fc es f_ask = - (*printf "combine_assign";*) - if !C.context_gas <> 0 then - try S.combine_assign (conv ctx) r fe f args (Option.map unlift fc) es f_ask with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let paths_as_set ctx = - (*printf "paths_as_set";*) - if !C.context_gas <> 0 then - try S.paths_as_set (conv ctx) with Ctx_failure _ -> [S.D.bot ()] - else [S.D.bot ()] - - let threadenter ctx lval f args = - (*printf "threadenter";*) - if !C.context_gas <> 0 then - try S.threadenter (conv ctx) lval f args with Ctx_failure _ -> [] - else [] - - let threadspawn ctx lval f args fctx = - (*printf "threadspawn";*) - if !C.context_gas <> 0 then - try S.threadspawn (conv ctx) lval f args (conv fctx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () - - let event ctx e octx = - (*printf "event";*) - if !C.context_gas <> 0 then - try S.event (conv ctx) e (conv octx) with Ctx_failure _ -> S.D.bot () - else S.D.bot () + let sync ctx reason = S.sync (conv ctx) reason + let query ctx q = S.query (conv ctx) q + let assign ctx lval expr = S.assign (conv ctx) lval expr + let vdecl ctx v = S.vdecl (conv ctx) v + let body ctx fundec = S.body (conv ctx) fundec + let branch ctx e tv = S.branch (conv ctx) e tv + let return ctx r f = S.return (conv ctx) r f + let asm ctx = S.asm (conv ctx) + let skip ctx = S.skip (conv ctx) + let special ctx r f args = S.special (conv ctx) r f args + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let paths_as_set ctx = S.paths_as_set (conv ctx) + let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) (*TODO*) + let event ctx e octx = S.event (conv ctx) e (conv octx) end diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple-recursion-depth50.c index 866492a34d..0b2fe05dc2 100644 --- a/tests/regression/80-context_gas/01-simple-recursion-depth50.c +++ b/tests/regression/80-context_gas/01-simple-recursion-depth50.c @@ -1,17 +1,29 @@ -// PARAM: --enable ana.int.interval +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include #include -int global; - +int a = 0; int main(void) { - f(10); + f(50); + + __goblint_check (a<20); + __goblint_check (a<15); + __goblint_check (a<10); + __goblint_check (a<5); + __goblint_check (a==0); } int f(int i) { + + if (i > 0){ i--; + a = i; f(i); } + } + + diff --git a/tests/regression/80-context_gas/02-two-recursions.c b/tests/regression/80-context_gas/02-two-recursions.c new file mode 100644 index 0000000000..03166dee31 --- /dev/null +++ b/tests/regression/80-context_gas/02-two-recursions.c @@ -0,0 +1,40 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include +#include + +int main(void) +{ + int res1 = f(10); + int res2 = g(10); + int result = res1 + res2; + __goblint_check (result == 4); // context sensitive + __goblint_check (result <= 6); // context insensitive +} + +// gets either even or odd i values +int f(int i) +{ + if (i == 0){ + return 1; + } + if (i > 0){ + i--; + g(i); + } + return 2; +} + +// gets either even or odd i values +int g(int i) +{ + if (i == 0){ + return 3; + } + if (i > 0){ + i--; + f(i); + } + return 4; +} + + diff --git a/tests/regression/80-context_gas/03-special-values-handeling.c b/tests/regression/80-context_gas/03-special-values-handeling.c new file mode 100644 index 0000000000..0599b40d28 --- /dev/null +++ b/tests/regression/80-context_gas/03-special-values-handeling.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include +#include + +int main(void) +{ + int res = f(10); + __goblint_check (res==100); +} + +// gets either even or odd i values +int f(int i) +{ + if (i == 0){ + return 100; + } + if (i > 0){ + i--; + f(i); + } + return 0; +} From bfb507d6ee13e9795551f878d953c49d033ab236 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 08:50:18 +0100 Subject: [PATCH 039/128] removed prints for clean output --- src/framework/constraints.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2aaf8c1404..795976ce41 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -522,7 +522,7 @@ struct let name () = S.name ()^" with context gas" let context fd d = - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then ((*printf "gas=0\n";*) None) else Some (S.context fd d) (* TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) @@ -532,8 +532,8 @@ struct let enter ctx r f args = if (not !AnalysisState.postsolving) && (!C.context_gas > 0) then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + (C.context_gas := !C.context_gas - 1; + (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)*)); S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason From 9958bf5be90e22d5ffa5ffe0743b610682847c99 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 11:01:16 +0100 Subject: [PATCH 040/128] status after the 2. meeting with supervisor --- src/framework/constraints.ml | 8 ++++---- ...le-recursion-depth50.c => 01-simple_recursion.c} | 13 +++---------- .../{02-two-recursions.c => 02-two_recursions.c} | 0 ...es-handeling.c => 03-special_values_handeling.c} | 0 tests/regression/80-context_gas/04-two_param.c | 11 +++++++++++ 5 files changed, 18 insertions(+), 14 deletions(-) rename tests/regression/80-context_gas/{01-simple-recursion-depth50.c => 01-simple_recursion.c} (58%) rename tests/regression/80-context_gas/{02-two-recursions.c => 02-two_recursions.c} (100%) rename tests/regression/80-context_gas/{03-special-values-handeling.c => 03-special_values_handeling.c} (100%) create mode 100644 tests/regression/80-context_gas/04-two_param.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 795976ce41..3d409415f8 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -522,18 +522,18 @@ struct let name () = S.name ()^" with context gas" let context fd d = - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) then ((*printf "gas=0\n";*) None) else Some (S.context fd d) (* TODO*) + if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (not !AnalysisState.postsolving) && (!C.context_gas <= 0) + if (!C.context_gas <= 0) then {ctx with context = (fun () -> ctx_failwith "contextGas") } else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) let enter ctx r f args = - if (not !AnalysisState.postsolving) && (!C.context_gas > 0) + if (!C.context_gas > 0) then (C.context_gas := !C.context_gas - 1; - (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)*)); + printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason diff --git a/tests/regression/80-context_gas/01-simple-recursion-depth50.c b/tests/regression/80-context_gas/01-simple_recursion.c similarity index 58% rename from tests/regression/80-context_gas/01-simple-recursion-depth50.c rename to tests/regression/80-context_gas/01-simple_recursion.c index 0b2fe05dc2..044ea12dd8 100644 --- a/tests/regression/80-context_gas/01-simple-recursion-depth50.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -2,28 +2,21 @@ #include #include -int a = 0; +int a = 5; int main(void) { - f(50); + f(5); - __goblint_check (a<20); - __goblint_check (a<15); - __goblint_check (a<10); - __goblint_check (a<5); - __goblint_check (a==0); + __goblint_check (a==0); // FAIL } int f(int i) { - - if (i > 0){ i--; a = i; f(i); } - } diff --git a/tests/regression/80-context_gas/02-two-recursions.c b/tests/regression/80-context_gas/02-two_recursions.c similarity index 100% rename from tests/regression/80-context_gas/02-two-recursions.c rename to tests/regression/80-context_gas/02-two_recursions.c diff --git a/tests/regression/80-context_gas/03-special-values-handeling.c b/tests/regression/80-context_gas/03-special_values_handeling.c similarity index 100% rename from tests/regression/80-context_gas/03-special-values-handeling.c rename to tests/regression/80-context_gas/03-special_values_handeling.c diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c new file mode 100644 index 0000000000..890e8faf62 --- /dev/null +++ b/tests/regression/80-context_gas/04-two_param.c @@ -0,0 +1,11 @@ +int main () { + f(50,50); +} + +int f (int x, int y){ + if (x == 0){ + __goblint_check (y == 0); + return 0; + } + f (--x, --y); +} \ No newline at end of file From d9211e163ff0af49f1f60e4b835203e94e8f95c6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 2 Nov 2023 18:52:35 +0100 Subject: [PATCH 041/128] changed module C, no compiler errors, but implementations are not complete yet --- src/framework/constraints.ml | 46 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 3d409415f8..9d1a637dc4 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -506,34 +506,54 @@ struct include S module D = S.D module G = S.G + + module PrintableInt = (*TODO*) + struct + type t = int [@@deriving eq, ord, hash] + + include Printable.Std + + let name () = "Integer" + let show x = string_of_int x + let pretty () x = Pretty.dprintf "Integer: %i" x + let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) + let to_yojson x = `String (string_of_int x) + + let arbitrary () = QCheck.int_range 0 (10000 - 1) + let relift x = x + end + module C = struct - include Printable.Option (S.C) (struct let name = "contextGas" end) - let context_gas = ref 10 + include Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) end module V = S.V module P = S.P - let rec showExprList args = (*TODO: delete, just here for printing*) + + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) let name () = S.name ()^" with context gas" let context fd d = - if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*) + (*if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*)*) + ((Some (S.context fd d)), 2 ) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (!C.context_gas <= 0) + (*if (!C.context_gas <= 0) then {ctx with context = (fun () -> ctx_failwith "contextGas") } - else {ctx with context = (fun () -> Option.get (ctx.context ())) } (*TODO Raises Invalid_argument if o is None.?*) + else*) + {ctx with context = (fun () -> Option.get ( fst (ctx.context ()))) } (*TODO Raises Invalid_argument if o is None.?*) let enter ctx r f args = - if (!C.context_gas > 0) - then + (*if (!C.context_gas > 0) + then (C.context_gas := !C.context_gas - 1; printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); + S.enter (conv ctx) r f args*) S.enter (conv ctx) r f args let sync ctx reason = S.sync (conv ctx) reason @@ -546,11 +566,11 @@ struct let asm ctx = S.asm (conv ctx) let skip ctx = S.skip (conv ctx) let special ctx r f args = S.special (conv ctx) r f args - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) es f_ask + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask let paths_as_set ctx = S.paths_as_set (conv ctx) - let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) (*TODO*) + let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) let event ctx e octx = S.event (conv ctx) e (conv octx) end From 938a62324a7c578357ee36a16724aa64b5dd9a8d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 10:51:26 +0100 Subject: [PATCH 042/128] converted D to a Product with an Int, same for C, changed the transfer functions; code is running for simple example, improvement for the int modules need still to be done --- src/framework/constraints.ml | 134 ++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 43 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 9d1a637dc4..89ee7207e3 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -499,13 +499,10 @@ end (** Lifts a [Spec] with the context gas variable. TODO *) module ContextGasLifter (S:Spec) - : Spec with module D = S.D - and module G = S.G + : Spec with module G = S.G = struct include S - module D = S.D - module G = S.G module PrintableInt = (*TODO*) struct @@ -518,60 +515,111 @@ struct let pretty () x = Pretty.dprintf "Integer: %i" x let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) let to_yojson x = `String (string_of_int x) - - let arbitrary () = QCheck.int_range 0 (10000 - 1) let relift x = x end - module C = - struct - include Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) - end - module V = S.V - module P = S.P + module LatticeInt = (*TODO*) + struct + include PrintableInt + + let leq x y = x <= y + let join x y = max x y + let widen = join + let meet x y = min x y + let narrow = meet + let top () = 10000 + let is_top a = match a with + | 10000 -> true + | _ -> false + let bot () = 0 + let is_bot a = match a with + | 0 -> true + | _ -> false + + let pretty_diff () ((x:t),(y:t)): Pretty.doc = + Pretty.dprintf "%a not leq %a" pretty x pretty y + + end + + module D = Lattice.Prod (S.D) (LatticeInt) + module G = S.G + + module C = Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) + module V = S.V + module P = + struct + include S.P + let of_elt (x, _) = of_elt x + end (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) - let name () = S.name ()^" with context gas" - - let context fd d = - (*if (!C.context_gas <= 0) then (printf "gas=0\n"; None) else Some (S.context fd d) (* TODO*)*) - ((Some (S.context fd d)), 2 ) + let context_gas_start = 20 - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - (*if (!C.context_gas <= 0) - then {ctx with context = (fun () -> ctx_failwith "contextGas") } - else*) - {ctx with context = (fun () -> Option.get ( fst (ctx.context ()))) } (*TODO Raises Invalid_argument if o is None.?*) + let name () = S.name ()^" with context gas" + let startstate v = S.startstate v, context_gas_start + let exitstate v = S.exitstate v, 0 (* TODO*) + let morphstate v (d,i) = S.morphstate v d, i (* TODO*) + + let context_gas_value ctx = + snd ctx.local + + let context fd (d,i) = + if (i <= 0) then (printf "gas=0\n"; (None, 0)) else ((Some (S.context fd d)), i) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* TODO*) + if (context_gas_value ctx <= 0) + then { + ctx with context = (fun () -> ctx_failwith "contextGas") + ; local = fst ctx.local + ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) (*TODO*) + } else { + ctx with context = (fun () -> Option.get (fst (ctx.context ()))) + ; local = fst ctx.local + ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) + } (*TODO Raises Invalid_argument if o is None.?*) + + let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = (* TODO*) + (*printf "context_gas_value = %i \n" (context_gas_value ctx);*) + if (context_gas_value ctx <= 1) (* because 1 is decreased to 0, which is already conntext insensitive*) + then { + ctx with context = (fun () -> (None, 0) ) + ; local = (fst ctx.local, 0) + } else { + ctx with context = (fun () -> (fst (ctx.context ()) , context_gas_value ctx - 1)) + ; local = (fst ctx.local, context_gas_value ctx - 1) + } let enter ctx r f args = - (*if (!C.context_gas > 0) - then - (C.context_gas := !C.context_gas - 1; - printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args)); - S.enter (conv ctx) r f args*) - S.enter (conv ctx) r f args + let ctx_dec = dec_context_gas ctx in + (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args));*) + printf "enterContextGas %i in %s with \n" (context_gas_value ctx_dec) (CilType.Fundec.show f) ; + let ctx_conv = conv ctx_dec in + let liftmap_tup = List.map (fun (x,y) -> (x, context_gas_value ctx_dec), (y, context_gas_value ctx_dec)) in + liftmap_tup (S.enter ctx_conv r f args) + + let liftmap f ctx = List.map (fun (x) -> (x, context_gas_value ctx)) f - let sync ctx reason = S.sync (conv ctx) reason + let sync ctx reason = S.sync (conv ctx) reason, context_gas_value ctx let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr - let vdecl ctx v = S.vdecl (conv ctx) v - let body ctx fundec = S.body (conv ctx) fundec - let branch ctx e tv = S.branch (conv ctx) e tv - let return ctx r f = S.return (conv ctx) r f - let asm ctx = S.asm (conv ctx) - let skip ctx = S.skip (conv ctx) - let special ctx r f args = S.special (conv ctx) r f args - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) es f_ask - let paths_as_set ctx = S.paths_as_set (conv ctx) - let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) + let assign ctx lval expr = S.assign (conv ctx) lval expr, context_gas_value ctx + let vdecl ctx v = S.vdecl (conv ctx) v, context_gas_value ctx + let body ctx fundec = S.body (conv ctx) fundec, context_gas_value ctx + let branch ctx e tv = S.branch (conv ctx) e tv, context_gas_value ctx + let return ctx r f = S.return (conv ctx) r f, context_gas_value ctx + let asm ctx = S.asm (conv ctx), context_gas_value ctx + let skip ctx = S.skip (conv ctx), context_gas_value ctx + let special ctx r f args = S.special (conv ctx) r f args, context_gas_value ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx + let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), context_gas_value ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), context_gas_value ctx end From 53bc11d47c94233cdbcfd01b360ead45837831c5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 17:22:50 +0100 Subject: [PATCH 043/128] moved int Printable and lattice to the corresponding file; added and improved testcases --- src/common/domains/printable.ml | 15 ++ src/domain/lattice.ml | 21 +++ src/framework/constraints.ml | 144 +++++++----------- .../80-context_gas/00-hardcoded_recursion.c | 41 +++++ .../80-context_gas/01-simple_recursion.c | 25 +-- .../80-context_gas/02-two_recursions.c | 49 +++--- .../03-special_values_handeling.c | 22 --- .../80-context_gas/03_three_recursions.c | 56 +++++++ .../regression/80-context_gas/04-two_param.c | 20 ++- .../80-context_gas/05-same_functions.c | 27 ++++ 10 files changed, 262 insertions(+), 158 deletions(-) create mode 100644 tests/regression/80-context_gas/00-hardcoded_recursion.c delete mode 100644 tests/regression/80-context_gas/03-special_values_handeling.c create mode 100644 tests/regression/80-context_gas/03_three_recursions.c create mode 100644 tests/regression/80-context_gas/05-same_functions.c diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index cc01718ee8..ebd458ce30 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -721,3 +721,18 @@ struct let to_yojson x = x (* override SimplePretty *) end + +(* Integer of type Printable*) +module PInt = +struct + type t = int [@@deriving eq, ord, hash] + + include Std + + let name () = "Integer" + let show x = string_of_int x + let pretty () x = Pretty.dprintf "Integer: %i" x + let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) + let to_yojson x = `String (string_of_int x) + let relift x = x +end diff --git a/src/domain/lattice.ml b/src/domain/lattice.ml index 9ea3f74635..cb586703cb 100644 --- a/src/domain/lattice.ml +++ b/src/domain/lattice.ml @@ -645,3 +645,24 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y end + +(* Integer of type Lattice*) +module LInt = +struct + include Printable.PInt + + let leq x y = x <= y + let join x y = max x y + let widen = join + let meet x y = min x y + let narrow = meet + + let top () = max_int + let is_top a = a >= top () + let bot () = 0 + let is_bot a = a <= bot () + + let pretty_diff () ((x:t),(y:t)): Pretty.doc = + Pretty.dprintf "%a not leq %a" pretty x pretty y + +end \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 89ee7207e3..2cad703ef7 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -497,55 +497,21 @@ struct let event (ctx:(D.t,G.t,C.t,V.t) ctx) (e:Events.t) (octx:(D.t,G.t,C.t,V.t) ctx):D.t = lift_fun ctx D.lift S.event ((|>) (conv octx) % (|>) e) `Bot end +module CGName = struct let name = "contextGas" end + (** Lifts a [Spec] with the context gas variable. TODO *) module ContextGasLifter (S:Spec) - : Spec with module G = S.G + : Spec with module D = Lattice.Prod (S.D) (Lattice.LInt) + and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + and module G = S.G = struct include S - module PrintableInt = (*TODO*) - struct - type t = int [@@deriving eq, ord, hash] - - include Printable.Std - - let name () = "Integer" - let show x = string_of_int x - let pretty () x = Pretty.dprintf "Integer: %i" x - let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) - let to_yojson x = `String (string_of_int x) - let relift x = x - end - - module LatticeInt = (*TODO*) - struct - include PrintableInt - - let leq x y = x <= y - let join x y = max x y - let widen = join - let meet x y = min x y - - let narrow = meet - let top () = 10000 - let is_top a = match a with - | 10000 -> true - | _ -> false - let bot () = 0 - let is_bot a = match a with - | 0 -> true - | _ -> false - - let pretty_diff () ((x:t),(y:t)): Pretty.doc = - Pretty.dprintf "%a not leq %a" pretty x pretty y - - end - - module D = Lattice.Prod (S.D) (LatticeInt) + module D = Lattice.Prod (S.D) (Lattice.LInt) module G = S.G - module C = Printable.Prod (Printable.Option (S.C) (struct let name = "contextGas" end)) (PrintableInt) + module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) module V = S.V module P = struct @@ -553,73 +519,65 @@ struct let of_elt (x, _) = of_elt x end - (*let rec showExprList args = (*TODO: delete, just here for printing*) - match args with - | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t)*) + let cg_init_val = 10 (* initial value of context gas*) - let context_gas_start = 20 + (* returns context gas value of the given ctx*) + let cg_val ctx = + snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) let name () = S.name ()^" with context gas" - let startstate v = S.startstate v, context_gas_start + let startstate v = S.startstate v, cg_init_val let exitstate v = S.exitstate v, 0 (* TODO*) let morphstate v (d,i) = S.morphstate v d, i (* TODO*) - let context_gas_value ctx = - snd ctx.local - let context fd (d,i) = - if (i <= 0) then (printf "gas=0\n"; (None, 0)) else ((Some (S.context fd d)), i) - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* TODO*) - if (context_gas_value ctx <= 0) - then { - ctx with context = (fun () -> ctx_failwith "contextGas") - ; local = fst ctx.local - ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) (*TODO*) - } else { - ctx with context = (fun () -> Option.get (fst (ctx.context ()))) - ; local = fst ctx.local - ; split = (fun d es -> ctx.split (d, context_gas_value ctx) es ) - } (*TODO Raises Invalid_argument if o is None.?*) - - let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = (* TODO*) - (*printf "context_gas_value = %i \n" (context_gas_value ctx);*) - if (context_gas_value ctx <= 1) (* because 1 is decreased to 0, which is already conntext insensitive*) - then { - ctx with context = (fun () -> (None, 0) ) - ; local = (fst ctx.local, 0) - } else { - ctx with context = (fun () -> (fst (ctx.context ()) , context_gas_value ctx - 1)) - ; local = (fst ctx.local, context_gas_value ctx - 1) - } + if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = + (* D.t -> S.D.t *) + let ctx' = {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, cg_val ctx) es )} in + (* C.t -> S.C.t *) + if (cg_val ctx <= 0) + then {ctx' with context = (fun () -> ctx_failwith "contextGas")} + else {ctx' with context = (fun () -> Option.get (fst (ctx'.context ())))} + + let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = + if (cg_val ctx <= 1) + then {ctx with context = (fun () -> (None, 0) ) (* context insensitive *) + ; local = (fst ctx.local, 0)} + else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) + ; local = (fst ctx.local, cg_val ctx - 1)} + + let rec showExprList args = (*TODO: delete, just here for printing*) + match args with + | [] -> " " + | a::t -> (CilType.Exp.show a) ^ (showExprList t) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*printf "enterContextGas %i in %s with %s \n" !C.context_gas (CilType.Fundec.show f) (showExprList args));*) - printf "enterContextGas %i in %s with \n" (context_gas_value ctx_dec) (CilType.Fundec.show f) ; - let ctx_conv = conv ctx_dec in - let liftmap_tup = List.map (fun (x,y) -> (x, context_gas_value ctx_dec), (y, context_gas_value ctx_dec)) in - liftmap_tup (S.enter ctx_conv r f args) + if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx_dec), (y, cg_val ctx_dec)) in + liftmap_tup (S.enter (conv ctx_dec) r f args) - let liftmap f ctx = List.map (fun (x) -> (x, context_gas_value ctx)) f + let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f - let sync ctx reason = S.sync (conv ctx) reason, context_gas_value ctx + let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr, context_gas_value ctx - let vdecl ctx v = S.vdecl (conv ctx) v, context_gas_value ctx - let body ctx fundec = S.body (conv ctx) fundec, context_gas_value ctx - let branch ctx e tv = S.branch (conv ctx) e tv, context_gas_value ctx - let return ctx r f = S.return (conv ctx) r f, context_gas_value ctx - let asm ctx = S.asm (conv ctx), context_gas_value ctx - let skip ctx = S.skip (conv ctx), context_gas_value ctx - let special ctx r f args = S.special (conv ctx) r f args, context_gas_value ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, context_gas_value ctx + let assign ctx lval expr = S.assign (conv ctx) lval expr, cg_val ctx + let vdecl ctx v = S.vdecl (conv ctx) v, cg_val ctx + let body ctx fundec = S.body (conv ctx) fundec, cg_val ctx + let branch ctx e tv = S.branch (conv ctx) e tv, cg_val ctx + let return ctx r f = S.return (conv ctx) r f, cg_val ctx + let asm ctx = S.asm (conv ctx), cg_val ctx + let skip ctx = S.skip (conv ctx), cg_val ctx + let special ctx r f args = S.special (conv ctx) r f args, cg_val ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), context_gas_value ctx - let event ctx e octx = S.event (conv ctx) e (conv octx), context_gas_value ctx + let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), cg_val ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas/00-hardcoded_recursion.c new file mode 100644 index 0000000000..a512bfb491 --- /dev/null +++ b/tests/regression/80-context_gas/00-hardcoded_recursion.c @@ -0,0 +1,41 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int a = 20; + +int f(int i) +{ + if (i == 5) + { + a = 4; + f(4); + } + if (i == 4) + { + a = 3; + f(3); + } + if (i == 3) + { + a = 2; + f(2); + } + if (i == 2) + { + a = 1; + f(1); + } + if (i == 1) + { + a = 0; + f(0); + } +} + +int main(void) +{ + f(5); + + // if the analysis runs fully context sensitive, "a" should be equal 0 + __goblint_check(a == 0); +} diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas/01-simple_recursion.c index 044ea12dd8..1c5460b960 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -1,22 +1,23 @@ // PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include +#include -int a = 5; -int main(void) -{ - f(5); - - __goblint_check (a==0); // FAIL -} +int num_iterat = 5; +int a = 20; int f(int i) { - if (i > 0){ - i--; - a = i; + if (i > 0) + { + a = --i; f(i); } + return 0; } +int main(void) +{ + f(num_iterat); + // if the analysis runs fully context sensitive, "a" should be equal 0 + __goblint_check(a == 0); +} diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index 03166dee31..c331977770 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,40 +1,41 @@ // PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include +#include -int main(void) -{ - int res1 = f(10); - int res2 = g(10); - int result = res1 + res2; - __goblint_check (result == 4); // context sensitive - __goblint_check (result <= 6); // context insensitive -} +int num_iterat = 10; -// gets either even or odd i values int f(int i) { - if (i == 0){ - return 1; + int res = 0; + if (i == 0) + { + res = 1; } - if (i > 0){ - i--; - g(i); + if (i > 0) + { + res = f(--i); } - return 2; + return res; } -// gets either even or odd i values int g(int i) { - if (i == 0){ - return 3; + int res = 0; + if (i == 0) + { + res = 1; } - if (i > 0){ - i--; - f(i); + if (i > 0) + { + res = g(--i); } - return 4; + return res; } +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int result = res1 + res2; + __goblint_check(result == 2); // context sensitive +} diff --git a/tests/regression/80-context_gas/03-special_values_handeling.c b/tests/regression/80-context_gas/03-special_values_handeling.c deleted file mode 100644 index 0599b40d28..0000000000 --- a/tests/regression/80-context_gas/03-special_values_handeling.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums -#include -#include - -int main(void) -{ - int res = f(10); - __goblint_check (res==100); -} - -// gets either even or odd i values -int f(int i) -{ - if (i == 0){ - return 100; - } - if (i > 0){ - i--; - f(i); - } - return 0; -} diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas/03_three_recursions.c new file mode 100644 index 0000000000..10ebc4ad18 --- /dev/null +++ b/tests/regression/80-context_gas/03_three_recursions.c @@ -0,0 +1,56 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int num_iterat = 5; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int result = res1 + res2 + res3; + + __goblint_check(result == 3); // context sensitive +} diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index 890e8faf62..9f47bc80b5 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,11 +1,17 @@ -int main () { - f(50,50); -} -int f (int x, int y){ - if (x == 0){ - __goblint_check (y == 0); +int num_iterat = 5; + +int f(int x, int y) +{ + if (x == 0) + { + __goblint_check(y == 0); return 0; } - f (--x, --y); + f(--x, --y); +} + +int main() +{ + f(num_iterat, num_iterat); } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c new file mode 100644 index 0000000000..5ccb402f63 --- /dev/null +++ b/tests/regression/80-context_gas/05-same_functions.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +#include + +int num_iterat = 5; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = f(num_iterat); + int result = res1 + res2; + + __goblint_check(result == 2); // context sensitive +} \ No newline at end of file From cb557c9b9001b8a6f5e124327cde26cfd25d9801 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 7 Nov 2023 17:34:09 +0100 Subject: [PATCH 044/128] adapted to changes from Master: added multiple --- src/framework/constraints.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2cad703ef7..57519bcb9e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -575,8 +575,8 @@ struct let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx - let threadenter ctx lval f args = liftmap (S.threadenter (conv ctx) lval f args) ctx (*TODO: it's possible to decrease the counter also here*) - let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx), cg_val ctx + let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's possible to decrease the counter also here*) + let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end From 7818511374a4114308c0dc12c843f44910a06d91 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 9 Nov 2023 12:29:20 +0100 Subject: [PATCH 045/128] fixed small error at enter transfer function; now decrement should work properly; only issue:1 decrement too much --- src/framework/constraints.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 57519bcb9e..756e212715 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -549,15 +549,16 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - let rec showExprList args = (*TODO: delete, just here for printing*) + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = + (*printf "enter\n";*) let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx_dec), (y, cg_val ctx_dec)) in + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f From a51a8436bb470eed481da0f0c9af6587eef56a95 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 10 Nov 2023 14:12:39 +0100 Subject: [PATCH 046/128] Longjump enabled, working --- src/framework/constraints.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 756e212715..323f081796 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -555,9 +555,8 @@ struct | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = - (*printf "enter\n";*) let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) From c035e3a33e2b23e614411441584d16ce86ca8905 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 13 Nov 2023 09:35:20 +0100 Subject: [PATCH 047/128] moved contextGasLifter upwards, hopefully fixes some of the regression tests --- src/framework/control.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index 79195f7c81..06b481659b 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,7 +20,8 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) + (module MCP.MCP2 : Spec) + |> lift true (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) @@ -37,8 +38,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - |> lift true (module ContextGasLifter) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From e83fa36a3fb0fab2ca098ef60e8852ff148f5bc9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 14 Nov 2023 15:10:54 +0100 Subject: [PATCH 048/128] made context lifter optional; added option to test cases --- src/config/options.schema.json | 7 +++ src/framework/control.ml | 2 +- .../80-context_gas/00-hardcoded_recursion.c | 9 +++- .../80-context_gas/01-simple_recursion.c | 2 +- .../80-context_gas/02-two_recursions.c | 2 +- .../80-context_gas/03_three_recursions.c | 2 +- .../regression/80-context_gas/04-two_param.c | 4 +- .../80-context_gas/05-same_functions.c | 2 +- .../80-context_gas/06-function_chain.c | 54 +++++++++++++++++++ 9 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 tests/regression/80-context_gas/06-function_chain.c diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 4d9546a9ca..cf7f886529 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -498,6 +498,13 @@ "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true + }, + "ctx_gas": { + "title": "ana.opt.ctx_gas", + "description": + "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/src/framework/control.ml b/src/framework/control.ml index 06b481659b..7838fd850a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,7 +21,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift true (module ContextGasLifter) + |> lift (get_bool "ana.opt.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas/00-hardcoded_recursion.c index a512bfb491..ec601d898b 100644 --- a/tests/regression/80-context_gas/00-hardcoded_recursion.c +++ b/tests/regression/80-context_gas/00-hardcoded_recursion.c @@ -1,6 +1,7 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include +int num_iterat = 5; int a = 20; int f(int i) @@ -30,11 +31,15 @@ int f(int i) a = 0; f(0); } + if (i == 0) + { + return 0; + } } int main(void) { - f(5); + f(num_iterat); // if the analysis runs fully context sensitive, "a" should be equal 0 __goblint_check(a == 0); diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas/01-simple_recursion.c index 1c5460b960..64da74b757 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas/01-simple_recursion.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index c331977770..7a10e89a83 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 10; diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas/03_three_recursions.c index 10ebc4ad18..1782887b61 100644 --- a/tests/regression/80-context_gas/03_three_recursions.c +++ b/tests/regression/80-context_gas/03_three_recursions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index 9f47bc80b5..c52df78198 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,5 +1,5 @@ - -int num_iterat = 5; +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +int num_iterat = 10; int f(int x, int y) { diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c index 5ccb402f63..bcffc498a9 100644 --- a/tests/regression/80-context_gas/05-same_functions.c +++ b/tests/regression/80-context_gas/05-same_functions.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.int.def_exc --enable ana.int.enums +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include int num_iterat = 5; diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas/06-function_chain.c new file mode 100644 index 0000000000..c88835fb14 --- /dev/null +++ b/tests/regression/80-context_gas/06-function_chain.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 10; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); // context sensitive +} From 49c5a5703a9c6b53d655232f3a3b52893a132876 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 14 Nov 2023 15:51:39 +0100 Subject: [PATCH 049/128] adapted the hardcoded path in test-gobview to match with this repository (this should make the gobview test work); changed the testcase recursion depth (this should make the regression tests work) --- scripts/test-gobview.py | 4 ++-- tests/regression/80-context_gas/02-two_recursions.c | 2 +- tests/regression/80-context_gas/04-two_param.c | 2 +- tests/regression/80-context_gas/06-function_chain.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/test-gobview.py b/scripts/test-gobview.py index 1ac8f6a76c..cac3ab824c 100644 --- a/scripts/test-gobview.py +++ b/scripts/test-gobview.py @@ -26,8 +26,8 @@ def serve(): global p goblint_http_path = '_build/default/gobview/goblint-http-server/goblint_http.exe' p = subprocess.Popen(['./' + goblint_http_path, - '-with-goblint', '../analyzer/goblint', - '-goblint', '--set', 'files[+]', '"../analyzer/tests/regression/00-sanity/01-assert.c"']) + '-with-goblint', '../GobContextGas/goblint', + '-goblint', '--set', 'files[+]', '"../GobContextGas/tests/regression/00-sanity/01-assert.c"']) print("serving at port", PORT) thread = Thread(target=serve, args=()) diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c index 7a10e89a83..4046162c82 100644 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ b/tests/regression/80-context_gas/02-two_recursions.c @@ -1,7 +1,7 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include -int num_iterat = 10; +int num_iterat = 5; int f(int i) { diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas/04-two_param.c index c52df78198..71ddf42758 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas/04-two_param.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -int num_iterat = 10; +int num_iterat = 5; int f(int x, int y) { diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas/06-function_chain.c index c88835fb14..d897d422bb 100644 --- a/tests/regression/80-context_gas/06-function_chain.c +++ b/tests/regression/80-context_gas/06-function_chain.c @@ -1,7 +1,7 @@ // PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set #include -int num_iterat = 10; +int num_iterat = 5; int h(int i) { From 145f577a558ad5a159ec1cf1454dffd7a2c493ff Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 17 Nov 2023 16:25:11 +0100 Subject: [PATCH 050/128] used Chain for ctxGasLifter (deleted Int module in Printable and Lattice), ana.opt.ctx_gas -> ana.context.ctx_gas; made html output of context gas prettier (by overwriting Prod), added and adapted testcases --- src/common/domains/printable.ml | 17 +----- src/config/options.schema.json | 14 ++--- src/domain/lattice.ml | 23 +------- src/framework/constraints.ml | 38 ++++++++---- src/framework/control.ml | 2 +- .../80-context_gas/02-two_recursions.c | 41 ------------- .../80-context_gas/05-same_functions.c | 27 --------- .../01-basic_multiple_param_simple.c} | 3 +- .../02-boundary_check_simple_rec.c} | 7 +-- .../03-boundary_check_multiple_rec.c} | 11 ++-- .../04-hardcoded_recursion.c} | 5 +- .../05-function_chain.c} | 5 +- .../80-context_gas_sens/06-call_in_loop.c | 31 ++++++++++ .../80-context_gas_sens/07-call_in_loop_adv.c | 29 +++++++++ .../08-circle_call_and_loops.c | 48 +++++++++++++++ .../01-multiple_param_simple.c | 18 ++++++ .../02-boundary_check_simple_rec.c | 22 +++++++ .../03-boundary_check_multiple_rec.c | 59 +++++++++++++++++++ .../81-context_gas_insens/04-function_chain.c | 54 +++++++++++++++++ .../81-context_gas_insens/05-ackermann.c | 27 +++++++++ .../81-context_gas_insens/06-call_in_loop.c | 27 +++++++++ .../07-circle_call_and_loops.c | 48 +++++++++++++++ .../81-context_gas_insens/08-loop_unrolling.c | 39 ++++++++++++ 23 files changed, 455 insertions(+), 140 deletions(-) delete mode 100644 tests/regression/80-context_gas/02-two_recursions.c delete mode 100644 tests/regression/80-context_gas/05-same_functions.c rename tests/regression/{80-context_gas/04-two_param.c => 80-context_gas_sens/01-basic_multiple_param_simple.c} (68%) rename tests/regression/{80-context_gas/01-simple_recursion.c => 80-context_gas_sens/02-boundary_check_simple_rec.c} (51%) rename tests/regression/{80-context_gas/03_three_recursions.c => 80-context_gas_sens/03-boundary_check_multiple_rec.c} (60%) rename tests/regression/{80-context_gas/00-hardcoded_recursion.c => 80-context_gas_sens/04-hardcoded_recursion.c} (72%) rename tests/regression/{80-context_gas/06-function_chain.c => 80-context_gas_sens/05-function_chain.c} (76%) create mode 100644 tests/regression/80-context_gas_sens/06-call_in_loop.c create mode 100644 tests/regression/80-context_gas_sens/07-call_in_loop_adv.c create mode 100644 tests/regression/80-context_gas_sens/08-circle_call_and_loops.c create mode 100644 tests/regression/81-context_gas_insens/01-multiple_param_simple.c create mode 100644 tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c create mode 100644 tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c create mode 100644 tests/regression/81-context_gas_insens/04-function_chain.c create mode 100644 tests/regression/81-context_gas_insens/05-ackermann.c create mode 100644 tests/regression/81-context_gas_insens/06-call_in_loop.c create mode 100644 tests/regression/81-context_gas_insens/07-circle_call_and_loops.c create mode 100644 tests/regression/81-context_gas_insens/08-loop_unrolling.c diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index ebd458ce30..d3530f40de 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -720,19 +720,4 @@ struct ) let to_yojson x = x (* override SimplePretty *) -end - -(* Integer of type Printable*) -module PInt = -struct - type t = int [@@deriving eq, ord, hash] - - include Std - - let name () = "Integer" - let show x = string_of_int x - let pretty () x = Pretty.dprintf "Integer: %i" x - let printXml f x = BatPrintf.fprintf f "\n\n%s\n\n\n" (string_of_int x) - let to_yojson x = `String (string_of_int x) - let relift x = x -end +end \ No newline at end of file diff --git a/src/config/options.schema.json b/src/config/options.schema.json index cf7f886529..bcb7745eb3 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -498,13 +498,6 @@ "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true - }, - "ctx_gas": { - "title": "ana.opt.ctx_gas", - "description": - "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", - "type": "boolean", - "default": false } }, "additionalProperties": false @@ -964,6 +957,13 @@ "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", "type": "boolean", "default": false + }, + "ctx_gas": { + "title": "ana.context.ctx_gas", + "description": + "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/src/domain/lattice.ml b/src/domain/lattice.ml index cb586703cb..fa7b56eab5 100644 --- a/src/domain/lattice.ml +++ b/src/domain/lattice.ml @@ -644,25 +644,4 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y -end - -(* Integer of type Lattice*) -module LInt = -struct - include Printable.PInt - - let leq x y = x <= y - let join x y = max x y - let widen = join - let meet x y = min x y - let narrow = meet - - let top () = max_int - let is_top a = a >= top () - let bot () = 0 - let is_bot a = a <= bot () - - let pretty_diff () ((x:t),(y:t)): Pretty.doc = - Pretty.dprintf "%a not leq %a" pretty x pretty y - -end \ No newline at end of file +end \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 323f081796..3009d6924c 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -498,20 +498,32 @@ struct end module CGName = struct let name = "contextGas" end +module IntConf = + struct + let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) + let names x = Format.asprintf "%d" x + end -(** Lifts a [Spec] with the context gas variable. TODO *) +(** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. + If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) module ContextGasLifter (S:Spec) - : Spec with module D = Lattice.Prod (S.D) (Lattice.LInt) - and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) + and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.Chain (IntConf)) and module G = S.G = struct include S - module D = Lattice.Prod (S.D) (Lattice.LInt) - module G = S.G + module Context_Gas_Prod (Base1: Printable.S) (Base2: Printable.S) = + struct + include Printable.Prod (Base1) (Base2) + let printXml f (x,y) = + BatPrintf.fprintf f "\n\n\n%s\n\n%a\nContext Gas Value\n\n%a\n\n" (XmlUtil.escape (Base1.name ())) Base1.printXml x Base2.printXml y + end - module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.PInt) + module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) + module G = S.G + module C = Context_Gas_Prod (Printable.Option (S.C) (CGName)) (Lattice.Chain (IntConf)) module V = S.V module P = struct @@ -527,8 +539,8 @@ struct let name () = S.name ()^" with context gas" let startstate v = S.startstate v, cg_init_val - let exitstate v = S.exitstate v, 0 (* TODO*) - let morphstate v (d,i) = S.morphstate v d, i (* TODO*) + let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) + let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) @@ -536,10 +548,10 @@ struct let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = (* D.t -> S.D.t *) let ctx' = {ctx with local = fst ctx.local - ; split = (fun d es -> ctx.split (d, cg_val ctx) es )} in + ; split = (fun d es -> ctx.split (d, cg_val ctx) es)} in (* C.t -> S.C.t *) if (cg_val ctx <= 0) - then {ctx' with context = (fun () -> ctx_failwith "contextGas")} + then {ctx' with context = (fun () -> ctx_failwith "no context (contextGas = 0)")} else {ctx' with context = (fun () -> Option.get (fst (ctx'.context ())))} let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = @@ -549,14 +561,14 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - (*let rec showExprList args = (*TODO: delete, just here for printing*) + let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); *) + if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) diff --git a/src/framework/control.ml b/src/framework/control.ml index 7838fd850a..d5b45cdf9f 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,7 +21,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.opt.ctx_gas") (module ContextGasLifter) + |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) diff --git a/tests/regression/80-context_gas/02-two_recursions.c b/tests/regression/80-context_gas/02-two_recursions.c deleted file mode 100644 index 4046162c82..0000000000 --- a/tests/regression/80-context_gas/02-two_recursions.c +++ /dev/null @@ -1,41 +0,0 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -#include - -int num_iterat = 5; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int result = res1 + res2; - - __goblint_check(result == 2); // context sensitive -} diff --git a/tests/regression/80-context_gas/05-same_functions.c b/tests/regression/80-context_gas/05-same_functions.c deleted file mode 100644 index bcffc498a9..0000000000 --- a/tests/regression/80-context_gas/05-same_functions.c +++ /dev/null @@ -1,27 +0,0 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set -#include - -int num_iterat = 5; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = f(num_iterat); - int result = res1 + res2; - - __goblint_check(result == 2); // context sensitive -} \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-two_param.c b/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c similarity index 68% rename from tests/regression/80-context_gas/04-two_param.c rename to tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c index 71ddf42758..d1715eaced 100644 --- a/tests/regression/80-context_gas/04-two_param.c +++ b/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c @@ -1,4 +1,5 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example int num_iterat = 5; int f(int x, int y) diff --git a/tests/regression/80-context_gas/01-simple_recursion.c b/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c similarity index 51% rename from tests/regression/80-context_gas/01-simple_recursion.c rename to tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c index 64da74b757..0856eea230 100644 --- a/tests/regression/80-context_gas/01-simple_recursion.c +++ b/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example + boundary check for simple recursion #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int a = 20; int f(int i) @@ -17,7 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - - // if the analysis runs fully context sensitive, "a" should be equal 0 __goblint_check(a == 0); } diff --git a/tests/regression/80-context_gas/03_three_recursions.c b/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c similarity index 60% rename from tests/regression/80-context_gas/03_three_recursions.c rename to tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c index 1782887b61..558b7e436f 100644 --- a/tests/regression/80-context_gas/03_three_recursions.c +++ b/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly + boundary check for multiple recursions #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int f(int i) { @@ -50,7 +51,9 @@ int main(void) int res1 = f(num_iterat); int res2 = g(num_iterat); int res3 = h(num_iterat); - int result = res1 + res2 + res3; + int res4 = h(num_iterat); + int res5 = h(num_iterat); + int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 3); // context sensitive + __goblint_check(result == 5); } diff --git a/tests/regression/80-context_gas/00-hardcoded_recursion.c b/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c similarity index 72% rename from tests/regression/80-context_gas/00-hardcoded_recursion.c rename to tests/regression/80-context_gas_sens/04-hardcoded_recursion.c index ec601d898b..d1ac462870 100644 --- a/tests/regression/80-context_gas/00-hardcoded_recursion.c +++ b/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if the context gas is reduced too much, due to the (not needed) function calls f(4) and f(3) #include -int num_iterat = 5; +int num_iterat = 2; int a = 20; int f(int i) diff --git a/tests/regression/80-context_gas/06-function_chain.c b/tests/regression/80-context_gas_sens/05-function_chain.c similarity index 76% rename from tests/regression/80-context_gas/06-function_chain.c rename to tests/regression/80-context_gas_sens/05-function_chain.c index d897d422bb..99b4f0a89d 100644 --- a/tests/regression/80-context_gas/06-function_chain.c +++ b/tests/regression/80-context_gas_sens/05-function_chain.c @@ -1,7 +1,8 @@ -// PARAM: --enable ana.opt.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if Chain-Calls are handled properly #include -int num_iterat = 5; +int num_iterat = 8; // should be context gas value - 2 int h(int i) { diff --git a/tests/regression/80-context_gas_sens/06-call_in_loop.c b/tests/regression/80-context_gas_sens/06-call_in_loop.c new file mode 100644 index 0000000000..92a751bf9d --- /dev/null +++ b/tests/regression/80-context_gas_sens/06-call_in_loop.c @@ -0,0 +1,31 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(num_iterat); + __goblint_check(res == 1); + result += res; + } + __goblint_check(result == 5); // TODO +} diff --git a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c new file mode 100644 index 0000000000..1a4dbfcebc --- /dev/null +++ b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c @@ -0,0 +1,29 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(i); + __goblint_check(res == 1); // TODO + result += res; + } + __goblint_check(result == 5); // TODO +} diff --git a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c new file mode 100644 index 0000000000..29fa50ee6e --- /dev/null +++ b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 2; // should be context gas value - 1 + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } + +} diff --git a/tests/regression/81-context_gas_insens/01-multiple_param_simple.c b/tests/regression/81-context_gas_insens/01-multiple_param_simple.c new file mode 100644 index 0000000000..9e6e4b870b --- /dev/null +++ b/tests/regression/81-context_gas_insens/01-multiple_param_simple.c @@ -0,0 +1,18 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example +int num_iterat = 100; + +int f(int x, int y) +{ + if (x == 0) + { + __goblint_check(y == 0); // UNKNOWN + return 0; + } + f(--x, --y); +} + +int main() +{ + f(num_iterat, num_iterat); +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c b/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c new file mode 100644 index 0000000000..4fd2156dc2 --- /dev/null +++ b/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Basic example + boundary check for simple recursion +#include + +int num_iterat = 9; // should be context gas value - 1 +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); // UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c b/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c new file mode 100644 index 0000000000..ef678dc7ee --- /dev/null +++ b/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly + boundary check for multiple recursions +#include + +int num_iterat = 9; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + int result = res1 + res2 + res3 + res4 + res5; + + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/04-function_chain.c b/tests/regression/81-context_gas_insens/04-function_chain.c new file mode 100644 index 0000000000..04e2fa83b6 --- /dev/null +++ b/tests/regression/81-context_gas_insens/04-function_chain.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 9; // should be context gas value - 1 + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); // UNKNOWN +} diff --git a/tests/regression/81-context_gas_insens/05-ackermann.c b/tests/regression/81-context_gas_insens/05-ackermann.c new file mode 100644 index 0000000000..90187d5a9f --- /dev/null +++ b/tests/regression/81-context_gas_insens/05-ackermann.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// This code would result in a StackOverflow if it is analyses fully context sensitive +#include + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) { + ack (4,1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/06-call_in_loop.c b/tests/regression/81-context_gas_insens/06-call_in_loop.c new file mode 100644 index 0000000000..04545ab177 --- /dev/null +++ b/tests/regression/81-context_gas_insens/06-call_in_loop.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 1000; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + for (int i = num_iterat; i > 0; i--) + { + int result = f(i); + __goblint_check(result == 1); // UNKNOWN + } +} diff --git a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c new file mode 100644 index 0000000000..248515c7ae --- /dev/null +++ b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +#include + +int num_iterat = 20; // should be context gas value - 1 + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); //UNKNOWN + __goblint_check(res2 == 1); //UNKNOWN + } + +} diff --git a/tests/regression/81-context_gas_insens/08-loop_unrolling.c b/tests/regression/81-context_gas_insens/08-loop_unrolling.c new file mode 100644 index 0000000000..8a560cc689 --- /dev/null +++ b/tests/regression/81-context_gas_insens/08-loop_unrolling.c @@ -0,0 +1,39 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// TODO +#include + +int num_iterat = 3; + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int f(int i) +{ + if (i > 0) + { + for (; i >= 0; i--) + { + int res = g(i); + __goblint_check(res == 1); + return res; + } + } + return -1; +} + +int main(void) +{ + f(num_iterat); + return 0; +} From 50d779e43fa53f642ac9116b59e13acf54ffdc7f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 23 Nov 2023 13:14:46 +0100 Subject: [PATCH 051/128] fixed indentation, added kCallstring module, just a first draft --- src/analyses/kCallsting.ml | 29 +++++++++++++++++++++++++++++ src/framework/constraints.ml | 8 ++++---- 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/analyses/kCallsting.ml diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallsting.ml new file mode 100644 index 0000000000..72a4d49468 --- /dev/null +++ b/src/analyses/kCallsting.ml @@ -0,0 +1,29 @@ +open GoblintCil +open Pretty +open GobPretty +open Analyses +open Cil + +module Spec (D: Lattice.S) : Analyses.MCPSpec = +struct + include Analyses.IdentitySpec + + module D = StackDomain.Dom1 + module C = StackDomain.Dom1 + + let name () = "k-callstring" + let startstate _ = D.bot () + let exitstate _ = D.bot () + + let concat_with_limit k d args = + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = k - List.length d in + let args_to_concat = take remaining_space args in + List.rev_append (List.rev args_to_concat) d + + +end \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 3009d6924c..b2288f3c31 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -499,10 +499,10 @@ end module CGName = struct let name = "contextGas" end module IntConf = - struct - let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) - let names x = Format.asprintf "%d" x - end +struct + let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) + let names x = Format.asprintf "%d" x +end (** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) From f0812d9e5c6c14321b2f3daf92e8101f4a41b2fa Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 23 Nov 2023 18:56:35 +0100 Subject: [PATCH 052/128] added kCallstring to goblint_lib; fixed indentation --- src/analyses/kCallsting.ml | 6 ------ src/framework/control.ml | 40 +++++++++++++++++++------------------- src/goblint_lib.ml | 1 + 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallsting.ml index 72a4d49468..ec1641abff 100644 --- a/src/analyses/kCallsting.ml +++ b/src/analyses/kCallsting.ml @@ -1,8 +1,4 @@ -open GoblintCil -open Pretty -open GobPretty open Analyses -open Cil module Spec (D: Lattice.S) : Analyses.MCPSpec = struct @@ -24,6 +20,4 @@ struct let remaining_space = k - List.length d in let args_to_concat = take remaining_space args in List.rev_append (List.rev args_to_concat) d - - end \ No newline at end of file diff --git a/src/framework/control.ml b/src/framework/control.ml index d5b45cdf9f..0df110f8c1 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,26 +20,26 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) in + (module MCP.MCP2 : Spec) + |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 5a2e0d3e0e..5a454605a7 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -148,6 +148,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination +module KCallstring = KCallstring module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace From 5eb87d9d0308b8ad59f9eb5989e42348a114c2dd Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 24 Nov 2023 09:45:07 +0100 Subject: [PATCH 053/128] fixed typo in file name; added new testcases; adapted existing ones --- .../{kCallsting.ml => kCallstring.ml} | 9 +++--- ...{06-call_in_loop.c => 06-loop_unrolling.c} | 4 ++- .../80-context_gas_sens/07-call_in_loop_adv.c | 2 ++ .../08-circle_call_and_loops.c | 3 +- .../80-context_gas_sens/09-main_recursion.c | 25 +++++++++++++++ .../81-context_gas_insens/04-function_chain.c | 1 + .../81-context_gas_insens/06-call_in_loop.c | 3 +- .../07-circle_call_and_loops.c | 4 +-- .../81-context_gas_insens/08-loop_unrolling.c | 32 +++++++------------ .../81-context_gas_insens/09-main_recursion.c | 24 ++++++++++++++ .../81-context_gas_insens/10-endless_loop.c | 24 ++++++++++++++ 11 files changed, 101 insertions(+), 30 deletions(-) rename src/analyses/{kCallsting.ml => kCallstring.ml} (70%) rename tests/regression/80-context_gas_sens/{06-call_in_loop.c => 06-loop_unrolling.c} (81%) create mode 100644 tests/regression/80-context_gas_sens/09-main_recursion.c create mode 100644 tests/regression/81-context_gas_insens/09-main_recursion.c create mode 100644 tests/regression/81-context_gas_insens/10-endless_loop.c diff --git a/src/analyses/kCallsting.ml b/src/analyses/kCallstring.ml similarity index 70% rename from src/analyses/kCallsting.ml rename to src/analyses/kCallstring.ml index ec1641abff..aea2a5ce91 100644 --- a/src/analyses/kCallsting.ml +++ b/src/analyses/kCallstring.ml @@ -1,17 +1,18 @@ open Analyses +open GoblintCil -module Spec (D: Lattice.S) : Analyses.MCPSpec = +module Spec : Analyses.MCPSpec = struct include Analyses.IdentitySpec module D = StackDomain.Dom1 module C = StackDomain.Dom1 - let name () = "k-callstring" + let name () = "k callstring" let startstate _ = D.bot () let exitstate _ = D.bot () - let concat_with_limit k d args = + (*let concat_with_limit k d args = let rec take n = function | [] -> [] | x :: xs when n > 0 -> x :: take (n - 1) xs @@ -19,5 +20,5 @@ struct in let remaining_space = k - List.length d in let args_to_concat = take remaining_space args in - List.rev_append (List.rev args_to_concat) d + List.rev_append (List.rev args_to_concat) d*) end \ No newline at end of file diff --git a/tests/regression/80-context_gas_sens/06-call_in_loop.c b/tests/regression/80-context_gas_sens/06-loop_unrolling.c similarity index 81% rename from tests/regression/80-context_gas_sens/06-call_in_loop.c rename to tests/regression/80-context_gas_sens/06-loop_unrolling.c index 92a751bf9d..63c29e6a47 100644 --- a/tests/regression/80-context_gas_sens/06-call_in_loop.c +++ b/tests/regression/80-context_gas_sens/06-loop_unrolling.c @@ -1,4 +1,6 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if recursion in loops are handled properly + loop unrolling +// TODO #include int num_iterat = 3; diff --git a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c index 1a4dbfcebc..d395229ea4 100644 --- a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c +++ b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c @@ -1,4 +1,6 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if recursion in loop is handled properly + iterator variable = function parameter +// TODO #include int f(int i) diff --git a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c index 29fa50ee6e..a0ff11c4da 100644 --- a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c +++ b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if recursion in loops is handled properly #include -int num_iterat = 2; // should be context gas value - 1 +int num_iterat = 2; int f(int i); diff --git a/tests/regression/80-context_gas_sens/09-main_recursion.c b/tests/regression/80-context_gas_sens/09-main_recursion.c new file mode 100644 index 0000000000..22b48103fa --- /dev/null +++ b/tests/regression/80-context_gas_sens/09-main_recursion.c @@ -0,0 +1,25 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if only recursion in main works properly + boundary check +// TODO +#include + +int num_iterat = 11; // WHY is context gas value + 1 the limit??? + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat--; + int res = main(); + __goblint_check(res == 5); + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} diff --git a/tests/regression/81-context_gas_insens/04-function_chain.c b/tests/regression/81-context_gas_insens/04-function_chain.c index 04e2fa83b6..1cafd8086e 100644 --- a/tests/regression/81-context_gas_insens/04-function_chain.c +++ b/tests/regression/81-context_gas_insens/04-function_chain.c @@ -1,4 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks if function chains are handled properly + boundary check #include int num_iterat = 9; // should be context gas value - 1 diff --git a/tests/regression/81-context_gas_insens/06-call_in_loop.c b/tests/regression/81-context_gas_insens/06-call_in_loop.c index 04545ab177..9a4f139fb8 100644 --- a/tests/regression/81-context_gas_insens/06-call_in_loop.c +++ b/tests/regression/81-context_gas_insens/06-call_in_loop.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks proper handling of recursion in loops + iterator variable = function parameter #include -int num_iterat = 1000; // should be context gas value - 1 +int num_iterat = 1000; int f(int i) { diff --git a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c index 248515c7ae..8b8e1b7bc7 100644 --- a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c +++ b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c @@ -1,7 +1,8 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks proper handling of recursions in loops #include -int num_iterat = 20; // should be context gas value - 1 +int num_iterat = 20; int f(int i); @@ -44,5 +45,4 @@ int main(void) __goblint_check(res1 == 2); //UNKNOWN __goblint_check(res2 == 1); //UNKNOWN } - } diff --git a/tests/regression/81-context_gas_insens/08-loop_unrolling.c b/tests/regression/81-context_gas_insens/08-loop_unrolling.c index 8a560cc689..8ba865cc98 100644 --- a/tests/regression/81-context_gas_insens/08-loop_unrolling.c +++ b/tests/regression/81-context_gas_insens/08-loop_unrolling.c @@ -1,39 +1,29 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 -// TODO +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if loop unrolling makes a difference for the analysis #include -int num_iterat = 3; +int num_iterat = 20; -int g(int i) +int f(int i) { int res = 0; if (i == 0) { - res = 1; + res = 2; } if (i > 0) { - res = g(--i); + res = f(--i); } return res; } -int f(int i) +int main(void) { - if (i > 0) + for (int i = 5; i > 0; i--) { - for (; i >= 0; i--) - { - int res = g(i); - __goblint_check(res == 1); - return res; - } + int res = f(num_iterat); + __goblint_check(res == 2); //UNKNOWN } - return -1; -} -int main(void) -{ - f(num_iterat); - return 0; -} +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/09-main_recursion.c b/tests/regression/81-context_gas_insens/09-main_recursion.c new file mode 100644 index 0000000000..7cf6a52e74 --- /dev/null +++ b/tests/regression/81-context_gas_insens/09-main_recursion.c @@ -0,0 +1,24 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Without context insensitive analysis: Stack Overflow +#include + +int num_iterat = 200000; + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat--; + int res = main(); + __goblint_check(res == 5); //UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} diff --git a/tests/regression/81-context_gas_insens/10-endless_loop.c b/tests/regression/81-context_gas_insens/10-endless_loop.c new file mode 100644 index 0000000000..40e7b9941e --- /dev/null +++ b/tests/regression/81-context_gas_insens/10-endless_loop.c @@ -0,0 +1,24 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis +#include + +int num_iterat = 2; + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat ++; + int res = main(); + __goblint_check(res == 5); //UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} From 75e1931cf13d91e633351722364e6b3393dfce8a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 11:18:30 +0100 Subject: [PATCH 054/128] deleted kCallstring, created new Callstring Lifter, added new testcases for callstring and for context gas --- src/analyses/kCallstring.ml | 24 ----- src/framework/constraints.ml | 90 +++++++++++++++++++ src/framework/control.ml | 1 + src/goblint_lib.ml | 1 - .../80-context_gas_sens/10-call_in_call.c | 55 ++++++++++++ .../81-context_gas_insens/10-call_in_call.c | 55 ++++++++++++ .../regression/82-callstring/01-simple_rec.c | 21 +++++ .../82-callstring/02-multiple_rec.c | 56 ++++++++++++ .../82-callstring/03-function_chain.c | 52 +++++++++++ 9 files changed, 330 insertions(+), 25 deletions(-) delete mode 100644 src/analyses/kCallstring.ml create mode 100644 tests/regression/80-context_gas_sens/10-call_in_call.c create mode 100644 tests/regression/81-context_gas_insens/10-call_in_call.c create mode 100644 tests/regression/82-callstring/01-simple_rec.c create mode 100644 tests/regression/82-callstring/02-multiple_rec.c create mode 100644 tests/regression/82-callstring/03-function_chain.c diff --git a/src/analyses/kCallstring.ml b/src/analyses/kCallstring.ml deleted file mode 100644 index aea2a5ce91..0000000000 --- a/src/analyses/kCallstring.ml +++ /dev/null @@ -1,24 +0,0 @@ -open Analyses -open GoblintCil - -module Spec : Analyses.MCPSpec = -struct - include Analyses.IdentitySpec - - module D = StackDomain.Dom1 - module C = StackDomain.Dom1 - - let name () = "k callstring" - let startstate _ = D.bot () - let exitstate _ = D.bot () - - (*let concat_with_limit k d args = - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = k - List.length d in - let args_to_concat = take remaining_space args in - List.rev_append (List.rev args_to_concat) d*) -end \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index b2288f3c31..be6d8681a9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -593,6 +593,96 @@ struct end +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context*) +module CallstringLifter (S:Spec) + : Spec with module C = Printable.Liszt (CilType.Fundec) + and module G = S.G += +struct + include S + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Liszt (CilType.Fundec) + let dummy = [] + let callDepthHeight = 10 + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = callDepthHeight - List.length elem in + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + end + + module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) + module G = S.G + module C = CallStack + module V = S.V + module P = + struct + include S.P + let of_elt (x, _) = of_elt x + end + + let name () = S.name ()^" with k callstring approach" + let startstate v = S.startstate v, [] + let exitstate v = S.exitstate v, [] + let morphstate v (d,l) = S.morphstate v d, l + + (* returns the call stack of the given ctx*) + let stack ctx = + snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) + + let context fd (d,l) = l + + let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = + (* D.t -> S.D.t *) + {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, stack ctx) es) + ; context = (fun () -> ctx_failwith "no context (k Callstring)") + } + + let print f ctx ctx' = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx); + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx'); + printf "\n\n" + + let enter ctx r f args = + let new_stack = CallStack.push (stack ctx) [f] in + let ctx' = {ctx with context = (fun () -> new_stack) + ; local = (fst ctx.local, new_stack)} in + if not !AnalysisState.postsolving then print f ctx ctx'; + let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) + liftmap_tup (S.enter (conv ctx') r f args) + + let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f + + let sync ctx reason = S.sync (conv ctx) reason, stack ctx + let query ctx q = S.query (conv ctx) q + let assign ctx lval expr = S.assign (conv ctx) lval expr, stack ctx + let vdecl ctx v = S.vdecl (conv ctx) v, stack ctx + let body ctx fundec = S.body (conv ctx) fundec, stack ctx + let branch ctx e tv = S.branch (conv ctx) e tv, stack ctx + let return ctx r f = S.return (conv ctx) r f, stack ctx + let asm ctx = S.asm (conv ctx), stack ctx + let skip ctx = S.skip (conv ctx), stack ctx + let special ctx r f args = S.special (conv ctx) r f args, stack ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx + let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx + let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) + let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx + let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx + +end + module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index 0df110f8c1..a3f1555295 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,6 +21,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) + |> lift (get_bool "ana.context.callstring") (module CallstringLifter) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 5a454605a7..5a2e0d3e0e 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -148,7 +148,6 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination -module KCallstring = KCallstring module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/80-context_gas_sens/10-call_in_call.c b/tests/regression/80-context_gas_sens/10-call_in_call.c new file mode 100644 index 0000000000..4d25cb89ad --- /dev/null +++ b/tests/regression/80-context_gas_sens/10-call_in_call.c @@ -0,0 +1,55 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +// TODO: is this behavior correct? +#include + +int num_iterat = 8; // should be context gas value - 2 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/10-call_in_call.c b/tests/regression/81-context_gas_insens/10-call_in_call.c new file mode 100644 index 0000000000..c355c92603 --- /dev/null +++ b/tests/regression/81-context_gas_insens/10-call_in_call.c @@ -0,0 +1,55 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +// TODO: is this behavior correct? +#include + +int num_iterat = 9; // should be context gas value - 1 + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); // UNKNOWN +} \ No newline at end of file diff --git a/tests/regression/82-callstring/01-simple_rec.c b/tests/regression/82-callstring/01-simple_rec.c new file mode 100644 index 0000000000..f974ce63ce --- /dev/null +++ b/tests/regression/82-callstring/01-simple_rec.c @@ -0,0 +1,21 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 12; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); +} diff --git a/tests/regression/82-callstring/02-multiple_rec.c b/tests/regression/82-callstring/02-multiple_rec.c new file mode 100644 index 0000000000..31f99c3533 --- /dev/null +++ b/tests/regression/82-callstring/02-multiple_rec.c @@ -0,0 +1,56 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 2; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); +} diff --git a/tests/regression/82-callstring/03-function_chain.c b/tests/regression/82-callstring/03-function_chain.c new file mode 100644 index 0000000000..47c4c3ae21 --- /dev/null +++ b/tests/regression/82-callstring/03-function_chain.c @@ -0,0 +1,52 @@ +// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 9; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); +} From f4b84572db8b34193c36420460c8f7aea2b533a0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 12:30:56 +0100 Subject: [PATCH 055/128] fixed a typo in a file name --- .../{10-endless_loop.c => 11-endless_loop.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/regression/81-context_gas_insens/{10-endless_loop.c => 11-endless_loop.c} (100%) diff --git a/tests/regression/81-context_gas_insens/10-endless_loop.c b/tests/regression/81-context_gas_insens/11-endless_loop.c similarity index 100% rename from tests/regression/81-context_gas_insens/10-endless_loop.c rename to tests/regression/81-context_gas_insens/11-endless_loop.c From 54a7798dae81836db3eef040b2e3ca895ab8f7dc Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 18:57:21 +0100 Subject: [PATCH 056/128] made the callstring approach modular (different types of callstack elements), currently two types: stmt and fundec, added option to emable and disable both lifters --- src/config/options.schema.json | 15 +++++- src/framework/constraints.ml | 86 +++++++++++++++++++++++++--------- src/framework/control.ml | 3 +- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index bcb7745eb3..ab69c5368d 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -960,8 +960,19 @@ }, "ctx_gas": { "title": "ana.context.ctx_gas", - "description": - "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false + }, + "callstring_fundec": { + "title": "ana.context.callstring_fundec", + "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Fundec", + "type": "boolean", + "default": false + }, + "callstring_stmt": { + "title": "ana.context.callstring_stmt", + "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Stmt", "type": "boolean", "default": false } diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index be6d8681a9..531127b296 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -537,7 +537,7 @@ struct let cg_val ctx = snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - let name () = S.name ()^" with context gas" + let name () = S.name ()^" with context gas (" ^ (string_of_int cg_init_val) ^")" let startstate v = S.startstate v, cg_init_val let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i @@ -566,7 +566,7 @@ struct | [] -> " " | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) - let enter ctx r f args = + let enter ctx r f args = let ctx_dec = dec_context_gas ctx in if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in @@ -593,19 +593,29 @@ struct end -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context*) -module CallstringLifter (S:Spec) - : Spec with module C = Printable.Liszt (CilType.Fundec) - and module G = S.G +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module CallstringLifter (S:Spec) (CT:Callstack_Type) + : Spec with module G = S.G = struct include S (* simulates a call stack of depth k*) module CallStack = struct - include Printable.Liszt (CilType.Fundec) + include Printable.Liszt (CT) let dummy = [] - let callDepthHeight = 10 + let depth = 2 let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -613,9 +623,13 @@ struct | x :: xs when n > 0 -> x :: take (n - 1) xs | _ -> [] in - let remaining_space = callDepthHeight - List.length elem in - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem + let remaining_space = depth - List.length elem in (*TODO: if we stick with the list it must be assumed that the list length can be larger than the depth*) + if remaining_space >= 0 + then + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + else + List.rev(take depth (List.rev elem)) end module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) @@ -628,7 +642,7 @@ struct let of_elt (x, _) = of_elt x end - let name () = S.name ()^" with k callstring approach" + let name () = S.name ()^" with k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" let startstate v = S.startstate v, [] let exitstate v = S.exitstate v, [] let morphstate v (d,l) = S.morphstate v d, l @@ -643,22 +657,15 @@ struct (* D.t -> S.D.t *) {ctx with local = fst ctx.local ; split = (fun d es -> ctx.split (d, stack ctx) es) - ; context = (fun () -> ctx_failwith "no context (k Callstring)") + ; context = (fun () -> ctx_failwith "no context (k Callstring)") (* TODO: correct?*) } - let print f ctx ctx' = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx); - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (stack ctx'); - printf "\n\n" - let enter ctx r f args = - let new_stack = CallStack.push (stack ctx) [f] in + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (stack ctx) elem in let ctx' = {ctx with context = (fun () -> new_stack) ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then print f ctx ctx'; + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) liftmap_tup (S.enter (conv ctx') r f args) @@ -680,9 +687,42 @@ struct let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx +end +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "Fundec" + let pushElem f args ctx = [f] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" end +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "Stmt" + let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> [stmt] + | _ -> printf "not a stmt\n"; [] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +module CallstringLifter_Fundec (S:Spec) = CallstringLifter (S:Spec) (Fundec) +module CallstringLifter_Stmt (S:Spec) = CallstringLifter (S:Spec) (Stmt) + module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index a3f1555295..b183592b57 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,7 +21,8 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.callstring") (module CallstringLifter) + |> lift (get_bool "ana.context.callstring_fundec") (module CallstringLifter_Fundec) + |> lift (get_bool "ana.context.callstring_stmt") (module CallstringLifter_Stmt) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) From 3b2a1d02f9256c07e7a2b07d8b6f0d8e9a769e28 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 27 Nov 2023 19:40:10 +0100 Subject: [PATCH 057/128] deleted main tracking from Callstring lifter; added testcases --- src/framework/constraints.ml | 22 ++++--- .../82-callstring_Fundec/01-simple_rec_sens.c | 22 +++++++ .../82-callstring_Fundec/02-simple_rec_ins.c | 22 +++++++ .../03-multiple_rec_sens.c | 59 +++++++++++++++++++ .../04-multiple_rec_ins.c | 59 +++++++++++++++++++ .../05-function_chain_sens.c} | 4 +- .../06-function_chain_ins.c | 54 +++++++++++++++++ .../01-simple_rec_sens.c} | 5 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 22 +++++++ .../03-multiple_rec_sens.c} | 7 ++- .../83-callstring_Stmt/04-multiple_rec_ins.c | 59 +++++++++++++++++++ .../05-function_chain_sens.c | 54 +++++++++++++++++ .../06-function_chain_ins.c | 54 +++++++++++++++++ 13 files changed, 429 insertions(+), 14 deletions(-) create mode 100644 tests/regression/82-callstring_Fundec/01-simple_rec_sens.c create mode 100644 tests/regression/82-callstring_Fundec/02-simple_rec_ins.c create mode 100644 tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c create mode 100644 tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c rename tests/regression/{82-callstring/03-function_chain.c => 82-callstring_Fundec/05-function_chain_sens.c} (82%) create mode 100644 tests/regression/82-callstring_Fundec/06-function_chain_ins.c rename tests/regression/{82-callstring/01-simple_rec.c => 83-callstring_Stmt/01-simple_rec_sens.c} (58%) create mode 100644 tests/regression/83-callstring_Stmt/02-simple_rec_ins.c rename tests/regression/{82-callstring/02-multiple_rec.c => 83-callstring_Stmt/03-multiple_rec_sens.c} (78%) create mode 100644 tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c create mode 100644 tests/regression/83-callstring_Stmt/05-function_chain_sens.c create mode 100644 tests/regression/83-callstring_Stmt/06-function_chain_ins.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 531127b296..6ddc858b17 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -566,7 +566,7 @@ struct | [] -> " " | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) - let enter ctx r f args = + let enter ctx r f args = let ctx_dec = dec_context_gas ctx in if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in @@ -615,7 +615,7 @@ struct module CallStack = struct include Printable.Liszt (CT) let dummy = [] - let depth = 2 + let depth = 10 let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -661,13 +661,17 @@ struct } let enter ctx r f args = - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) - ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); - let liftmap_tup = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) - liftmap_tup (S.enter (conv ctx') r f args) + let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) + if CilType.Fundec.show f = "main" + then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) + else( + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (stack ctx) elem in + let ctx' = {ctx with context = (fun () -> new_stack) + ; local = (fst ctx.local, new_stack)} in + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); + liftmap_tup new_stack (S.enter (conv ctx') r f args)) + let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c new file mode 100644 index 0000000000..a8dd15ebb4 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 9; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c new file mode 100644 index 0000000000..c597ec80ea --- /dev/null +++ b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c new file mode 100644 index 0000000000..547f9b4c44 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 9; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c new file mode 100644 index 0000000000..e23af9a938 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/82-callstring/03-function_chain.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c similarity index 82% rename from tests/regression/82-callstring/03-function_chain.c rename to tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 47c4c3ae21..71fbbf59b4 100644 --- a/tests/regression/82-callstring/03-function_chain.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include @@ -49,4 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); + + __goblint_check(result == 1); } diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c new file mode 100644 index 0000000000..5b294209d2 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 12; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} diff --git a/tests/regression/82-callstring/01-simple_rec.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c similarity index 58% rename from tests/regression/82-callstring/01-simple_rec.c rename to tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index f974ce63ce..20e0209508 100644 --- a/tests/regression/82-callstring/01-simple_rec.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -1,8 +1,8 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set // Basic example #include -int num_iterat = 12; +int num_iterat = 10; int a = 20; int f(int i) @@ -18,4 +18,5 @@ int f(int i) int main(void) { f(num_iterat); + __goblint_check(a == 0); } diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c new file mode 100644 index 0000000000..a48ae17192 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/82-callstring/02-multiple_rec.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c similarity index 78% rename from tests/regression/82-callstring/02-multiple_rec.c rename to tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index 31f99c3533..28b9748c2c 100644 --- a/tests/regression/82-callstring/02-multiple_rec.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -1,8 +1,8 @@ -// PARAM: --enable ana.context.callstring --enable ana.int.interval_set +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include -int num_iterat = 2; +int num_iterat = 10; int f(int i) { @@ -53,4 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); } diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c new file mode 100644 index 0000000000..6eeefacc91 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c new file mode 100644 index 0000000000..422bcb4b7b --- /dev/null +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 10; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); +} diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c new file mode 100644 index 0000000000..c17d01d09f --- /dev/null +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 13; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} From 0c21a3a179cb1e8377bf1ea21f41e0dd4164cd26 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 28 Nov 2023 14:59:24 +0100 Subject: [PATCH 058/128] added new testcases, a few explanations in constraints --- src/framework/constraints.ml | 10 ++-- .../03-multiple_rec_sens.c | 1 + .../05-function_chain_sens.c | 2 +- .../07-call_in_call_sens.c | 54 +++++++++++++++++++ .../82-callstring_Fundec/08-ackermann.c | 27 ++++++++++ .../09-circle_call_and_loops.c | 48 +++++++++++++++++ .../10-circle_call_and_big_loop.c | 46 ++++++++++++++++ .../11-big_call_and_loop.c | 49 +++++++++++++++++ .../05-function_chain_sens.c | 2 +- .../83-callstring_Stmt/07-call_in_call.c | 54 +++++++++++++++++++ .../08-circle_call_and_big_loop.c | 46 ++++++++++++++++ 11 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 tests/regression/82-callstring_Fundec/07-call_in_call_sens.c create mode 100644 tests/regression/82-callstring_Fundec/08-ackermann.c create mode 100644 tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c create mode 100644 tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c create mode 100644 tests/regression/82-callstring_Fundec/11-big_call_and_loop.c create mode 100644 tests/regression/83-callstring_Stmt/07-call_in_call.c create mode 100644 tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6ddc858b17..73455ce647 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -615,7 +615,7 @@ struct module CallStack = struct include Printable.Liszt (CT) let dummy = [] - let depth = 10 + let depth = 10 (* must be >= 0 *) let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -623,7 +623,7 @@ struct | x :: xs when n > 0 -> x :: take (n - 1) xs | _ -> [] in - let remaining_space = depth - List.length elem in (*TODO: if we stick with the list it must be assumed that the list length can be larger than the depth*) + let remaining_space = depth - List.length elem in if remaining_space >= 0 then let remaining_stack = take remaining_space (List.rev stack) in @@ -664,12 +664,12 @@ struct let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) if CilType.Fundec.show f = "main" then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) - else( + else ( let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) + let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); + if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); (* just for debugging purpose*) liftmap_tup new_stack (S.enter (conv ctx') r f args)) diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 547f9b4c44..87fe4778d7 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -49,6 +49,7 @@ int h(int i) int main(void) { int res1 = f(num_iterat); + __goblint_check(res1 == 1); int res2 = g(num_iterat); int res3 = h(num_iterat); int res4 = h(num_iterat); diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 71fbbf59b4..9eb4a15bef 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -2,7 +2,7 @@ // Checks if function chains are handled properly #include -int num_iterat = 9; +int num_iterat = 11; int h(int i) { diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c new file mode 100644 index 0000000000..0d26f57944 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 9; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c new file mode 100644 index 0000000000..6ecb4766ef --- /dev/null +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -0,0 +1,27 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// This code would result in a StackOverflow if it is analyses fully context sensitive +#include + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) { + ack (4,1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c new file mode 100644 index 0000000000..94847d7873 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed +#include + +int num_iterat = 200; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 2); //UNKNOWN + __goblint_check(res2 == 1); //UNKNOWN + } +} diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c new file mode 100644 index 0000000000..35f9a66f7c --- /dev/null +++ b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c new file mode 100644 index 0000000000..3591b8f4da --- /dev/null +++ b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c @@ -0,0 +1,49 @@ +// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result +// TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) +#include + +int num_iterat = 90; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(9); + int res2 = g(9); + __goblint_check(res1 == 1); // TODO + __goblint_check(res2 == 2); // TODO + for (int i = 10; i > 0; i--) + { + int res3 = f(num_iterat); + int res4 = g(num_iterat); + __goblint_check(res3 == 1); // TODO + __goblint_check(res4 == 2); // TODO + } +} diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index 422bcb4b7b..c3094efe4e 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -2,7 +2,7 @@ // Checks if function chains are handled properly #include -int num_iterat = 10; +int num_iterat = 12; int h(int i) { diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c new file mode 100644 index 0000000000..47e6dd515b --- /dev/null +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -0,0 +1,54 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c new file mode 100644 index 0000000000..60d5d95f29 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} From f29cfc5be7023e211299667952cf89c585039ea9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 4 Dec 2023 13:46:54 +0100 Subject: [PATCH 059/128] moved callstring ana from lifter to analysis (must be tested), adapted testcases --- src/analyses/callstringAnalysis.ml | 100 +++++++++++++ src/config/options.schema.json | 16 +-- src/framework/constraints.ml | 134 ------------------ src/framework/control.ml | 2 - src/goblint_lib.ml | 1 + .../80-context_gas_sens/06-loop_unrolling.c | 5 +- .../80-context_gas_sens/09-main_recursion.c | 15 ++ .../80-context_gas_sens/10-call_in_call.c | 3 +- .../81-context_gas_insens/10-call_in_call.c | 1 - .../82-callstring_Fundec/01-simple_rec_sens.c | 2 +- .../82-callstring_Fundec/02-simple_rec_ins.c | 2 +- .../03-multiple_rec_sens.c | 2 +- .../04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../07-call_in_call_sens.c | 2 +- .../82-callstring_Fundec/08-ackermann.c | 2 +- .../09-circle_call_and_loops.c | 2 +- .../10-circle_call_and_big_loop.c | 2 +- .../11-big_call_and_loop.c | 4 +- .../82-callstring_Fundec/12-loop_unrolling.c | 34 +++++ .../83-callstring_Stmt/01-simple_rec_sens.c | 2 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 2 +- .../83-callstring_Stmt/03-multiple_rec_sens.c | 2 +- .../83-callstring_Stmt/04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../83-callstring_Stmt/07-call_in_call.c | 2 +- .../08-circle_call_and_big_loop.c | 2 +- 29 files changed, 177 insertions(+), 174 deletions(-) create mode 100644 src/analyses/callstringAnalysis.ml create mode 100644 tests/regression/82-callstring_Fundec/12-loop_unrolling.c diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml new file mode 100644 index 0000000000..01a459183a --- /dev/null +++ b/src/analyses/callstringAnalysis.ml @@ -0,0 +1,100 @@ +open GoblintCil +open Analyses +open Printf + +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module Spec (CT:Callstack_Type) : MCPSpec= +struct + include Analyses.IdentitySpec + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Liszt (CT) + let dummy = [] + let depth = 10 (* must be >= 0 *) + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + let rec take n = function + | [] -> [] + | x :: xs when n > 0 -> x :: take (n - 1) xs + | _ -> [] + in + let remaining_space = depth - List.length elem in + if remaining_space >= 0 + then + let remaining_stack = take remaining_space (List.rev stack) in + List.rev_append remaining_stack elem + else + List.rev(take depth (List.rev elem)) + end + + module D = Lattice.FakeSingleton(CallStack) + module C = CallStack + module V = EmptyV + module G = Lattice.Unit + + let name () = "k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" + let startstate v = [] + let exitstate v = [] + + let context fd d = d + + let enter ctx r f args = + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push (ctx.local) elem in + let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) + ; local = new_stack} in + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) + [ctx.local, new_stack] +end + +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "Fundec" + let pushElem f args ctx = [f] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" +end + +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "Stmt" + let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> [stmt] + | _ -> printf "not a stmt\n"; [] + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +module CallstringLifter_Fundec = Spec (Fundec) +module CallstringLifter_Stmt = Spec (Stmt) + +let _ = + MCP.register_analysis (module CallstringLifter_Fundec : MCPSpec); + MCP.register_analysis (module CallstringLifter_Stmt : MCPSpec) + + diff --git a/src/config/options.schema.json b/src/config/options.schema.json index ab69c5368d..ad780f7cb2 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -532,7 +532,9 @@ "wideningThresholds", "memsafetySpecification", "termination", - "tmpSpecialAnalysis" + "tmpSpecialAnalysis", + "callstring_fundec", + "callstring_stmt" ] }, "default": [ @@ -963,18 +965,6 @@ "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", "type": "boolean", "default": false - }, - "callstring_fundec": { - "title": "ana.context.callstring_fundec", - "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Fundec", - "type": "boolean", - "default": false - }, - "callstring_stmt": { - "title": "ana.context.callstring_stmt", - "description": "If enabled, the last k elements of the callstack are used as context. The tcallstack elements are of type Stmt", - "type": "boolean", - "default": false } }, "additionalProperties": false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 73455ce647..f150754e6a 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -593,140 +593,6 @@ struct end -(* Specifies the type of the callstack elements for the CallstringLifter*) -module type Callstack_Type = -sig - include CilType.S - val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) -end - -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context - With the CT argument it is possible to specify the type of the Callstack elements -*) -module CallstringLifter (S:Spec) (CT:Callstack_Type) - : Spec with module G = S.G -= -struct - include S - - (* simulates a call stack of depth k*) - module CallStack = struct - include Printable.Liszt (CT) - let dummy = [] - let depth = 10 (* must be >= 0 *) - - let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = depth - List.length elem in - if remaining_space >= 0 - then - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem - else - List.rev(take depth (List.rev elem)) - end - - module D = Lattice.Prod (S.D) (Lattice.FakeSingleton(CallStack)) - module G = S.G - module C = CallStack - module V = S.V - module P = - struct - include S.P - let of_elt (x, _) = of_elt x - end - - let name () = S.name ()^" with k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" - let startstate v = S.startstate v, [] - let exitstate v = S.exitstate v, [] - let morphstate v (d,l) = S.morphstate v d, l - - (* returns the call stack of the given ctx*) - let stack ctx = - snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - - let context fd (d,l) = l - - let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = - (* D.t -> S.D.t *) - {ctx with local = fst ctx.local - ; split = (fun d es -> ctx.split (d, stack ctx) es) - ; context = (fun () -> ctx_failwith "no context (k Callstring)") (* TODO: correct?*) - } - - let enter ctx r f args = - let liftmap_tup new_stack = List.map (fun (x,y) -> (x, stack ctx), (y, new_stack)) in (* new_stack = snd ctx'.local *) - if CilType.Fundec.show f = "main" - then liftmap_tup (stack ctx) (S.enter (conv ctx) r f args) - else ( - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (stack ctx) elem in - let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) - ; local = (fst ctx.local, new_stack)} in - if not !AnalysisState.postsolving then CT.printStack f args (stack ctx) (stack ctx'); (* just for debugging purpose*) - liftmap_tup new_stack (S.enter (conv ctx') r f args)) - - - let liftmap f ctx = List.map (fun (x) -> (x, stack ctx)) f - - let sync ctx reason = S.sync (conv ctx) reason, stack ctx - let query ctx q = S.query (conv ctx) q - let assign ctx lval expr = S.assign (conv ctx) lval expr, stack ctx - let vdecl ctx v = S.vdecl (conv ctx) v, stack ctx - let body ctx fundec = S.body (conv ctx) fundec, stack ctx - let branch ctx e tv = S.branch (conv ctx) e tv, stack ctx - let return ctx r f = S.return (conv ctx) r f, stack ctx - let asm ctx = S.asm (conv ctx), stack ctx - let skip ctx = S.skip (conv ctx), stack ctx - let special ctx r f args = S.special (conv ctx) r f args, stack ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (None) (fst es) f_ask, stack ctx - let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx - let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's also possible to push to the stack*) - let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), stack ctx - let event ctx e octx = S.event (conv ctx) e (conv octx), stack ctx -end - -module Fundec:Callstack_Type = struct - include CilType.Fundec - let stackTypeName = "Fundec" - let pushElem f args ctx = [f] - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; - printf "\n\n" -end - -module Stmt:Callstack_Type = struct - include CilType.Stmt - let stackTypeName = "Stmt" - let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) - | Statement stmt -> [stmt] - | _ -> printf "not a stmt\n"; [] - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; - printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; - printf "\n\n" -end - -(* Lifters for the Callstring approach with different Callstack element types*) -module CallstringLifter_Fundec (S:Spec) = CallstringLifter (S:Spec) (Fundec) -module CallstringLifter_Stmt (S:Spec) = CallstringLifter (S:Spec) (Stmt) - module type Increment = sig val increment: increment_data option diff --git a/src/framework/control.ml b/src/framework/control.ml index b183592b57..0df110f8c1 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,8 +21,6 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.callstring_fundec") (module CallstringLifter_Fundec) - |> lift (get_bool "ana.context.callstring_stmt") (module CallstringLifter_Stmt) |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 5a2e0d3e0e..550e5771f8 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -148,6 +148,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination +module CallstringAnalysis = CallstringAnalysis module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/80-context_gas_sens/06-loop_unrolling.c b/tests/regression/80-context_gas_sens/06-loop_unrolling.c index 63c29e6a47..b95c7a8638 100644 --- a/tests/regression/80-context_gas_sens/06-loop_unrolling.c +++ b/tests/regression/80-context_gas_sens/06-loop_unrolling.c @@ -26,8 +26,9 @@ int main(void) for (int i = 5; i > 0; i--) { res = f(num_iterat); - __goblint_check(res == 1); + __goblint_check(res == 1); result += res; } - __goblint_check(result == 5); // TODO + __goblint_check(res == 1); + __goblint_check(result == 5); //TODO } diff --git a/tests/regression/80-context_gas_sens/09-main_recursion.c b/tests/regression/80-context_gas_sens/09-main_recursion.c index 22b48103fa..01bf3a0c64 100644 --- a/tests/regression/80-context_gas_sens/09-main_recursion.c +++ b/tests/regression/80-context_gas_sens/09-main_recursion.c @@ -5,6 +5,21 @@ int num_iterat = 11; // WHY is context gas value + 1 the limit??? +/* +main mit 11: 10 -> 9 +main mit 10: 9 -> 8 +main mit 9: 8 -> 7 +main mit 8: 7 -> 6 +main mit 7: 6 -> 5 +main mit 6: 5 -> 4 +main mit 5: 4 -> 3 +main mit 4: 3 -> 2 +main mit 3: 2 -> 1 +main mit 2: 1 -> 0 +main mit 1: 0 -> 0 +main mit 0: 0 -> 0 +*/ + int main(void) { if (num_iterat > 0) diff --git a/tests/regression/80-context_gas_sens/10-call_in_call.c b/tests/regression/80-context_gas_sens/10-call_in_call.c index 4d25cb89ad..b3eac1d382 100644 --- a/tests/regression/80-context_gas_sens/10-call_in_call.c +++ b/tests/regression/80-context_gas_sens/10-call_in_call.c @@ -1,6 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set // Interesting if nested recursions are handled properly -// TODO: is this behavior correct? #include int num_iterat = 8; // should be context gas value - 2 @@ -49,7 +48,7 @@ int h(int i) int main(void) { - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + int res = f(g(h(num_iterat))); // h(8) = 3; g(3) = 2; f(2) = 1 __goblint_check(res == 1); } \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/10-call_in_call.c b/tests/regression/81-context_gas_insens/10-call_in_call.c index c355c92603..db60a35b80 100644 --- a/tests/regression/81-context_gas_insens/10-call_in_call.c +++ b/tests/regression/81-context_gas_insens/10-call_in_call.c @@ -1,6 +1,5 @@ // PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set // Interesting if nested recursions are handled properly -// TODO: is this behavior correct? #include int num_iterat = 9; // should be context gas value - 1 diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c index a8dd15ebb4..7548fe63dc 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c index c597ec80ea..77c544e794 100644 --- a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 87fe4778d7..3bef88d1b3 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c index e23af9a938..61e53c45d8 100644 --- a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 9eb4a15bef..c65bb8bdd4 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c index 5b294209d2..c9f7653e9f 100644 --- a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c index 0d26f57944..11ae47b759 100644 --- a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c index 6ecb4766ef..8082e2f082 100644 --- a/tests/regression/82-callstring_Fundec/08-ackermann.c +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // This code would result in a StackOverflow if it is analyses fully context sensitive #include diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c index 94847d7873..3fd8175e7f 100644 --- a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c index 35f9a66f7c..9ca346bac4 100644 --- a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c index 3591b8f4da..941756bdce 100644 --- a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c +++ b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c @@ -1,9 +1,9 @@ -// PARAM: --enable ana.context.callstring_fundec --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result // TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) #include -int num_iterat = 90; +int num_iterat = 10; int f(int i) { diff --git a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c new file mode 100644 index 0000000000..15f54a1b80 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c @@ -0,0 +1,34 @@ +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 +// Checks if recursion in loops are handled properly + loop unrolling +// TODO +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + int res = 0; + int result = 0; + for (int i = 5; i > 0; i--) + { + res = f(num_iterat); + __goblint_check(res == 1); + result += res; + } + __goblint_check(res == 1); + __goblint_check(result == 5); //TODO +} diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index 20e0209508..b7bf539693 100644 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c index a48ae17192..da58b8a881 100644 --- a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index 28b9748c2c..7dc7e04a98 100644 --- a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c index 6eeefacc91..5614802151 100644 --- a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index c3094efe4e..085210b8a2 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c index c17d01d09f..8debbe9f46 100644 --- a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c index 47e6dd515b..7ef3a83194 100644 --- a/tests/regression/83-callstring_Stmt/07-call_in_call.c +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c index 60d5d95f29..38e7051736 100644 --- a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c +++ b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.callstring_stmt --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed #include From ddd2070a9382ae67ae20c3d50fae610e7c6ea0b1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 5 Dec 2023 16:53:48 +0100 Subject: [PATCH 060/128] used options.schema.json for variable storing; used different Lattice in callstring; adapted callstringAna -> should be working, missing: only callstring context is used for the analysis --- src/analyses/callstringAnalysis.ml | 25 +++++++++++-------------- src/config/options.schema.json | 12 ++++++++++++ src/framework/constraints.ml | 13 +++++-------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 01a459183a..94a4e93aab 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -1,6 +1,7 @@ -open GoblintCil open Analyses open Printf +open GoblintCil +open GobConfig (* Specifies the type of the callstack elements for the CallstringLifter*) module type Callstack_Type = @@ -14,15 +15,14 @@ end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context With the CT argument it is possible to specify the type of the Callstack elements *) -module Spec (CT:Callstack_Type) : MCPSpec= +module Spec (CT:Callstack_Type) : MCPSpec = struct include Analyses.IdentitySpec (* simulates a call stack of depth k*) module CallStack = struct include Printable.Liszt (CT) - let dummy = [] - let depth = 10 (* must be >= 0 *) + let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) let rec take n = function @@ -39,12 +39,12 @@ struct List.rev(take depth (List.rev elem)) end - module D = Lattice.FakeSingleton(CallStack) + module D = Lattice.Fake(CallStack) module C = CallStack module V = EmptyV module G = Lattice.Unit - let name () = "k-callstring approach ("^ CT.stackTypeName ^", k = " ^ (string_of_int CallStack.depth)^")" + let name () = "callstring_"^ CT.stackTypeName let startstate v = [] let exitstate v = [] @@ -53,7 +53,7 @@ struct let enter ctx r f args = let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (ctx.local) elem in - let ctx' = {ctx with context = (fun () -> new_stack) (* in case conv ctx makes the context to fail, this is not necessary*) + let ctx' = {ctx with context = (fun () -> new_stack) ; local = new_stack} in if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) [ctx.local, new_stack] @@ -61,7 +61,7 @@ end module Fundec:Callstack_Type = struct include CilType.Fundec - let stackTypeName = "Fundec" + let stackTypeName = "fundec" let pushElem f args ctx = [f] let printStack f expL listA listB = @@ -75,7 +75,7 @@ end module Stmt:Callstack_Type = struct include CilType.Stmt - let stackTypeName = "Stmt" + let stackTypeName = "stmt" let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) | Statement stmt -> [stmt] | _ -> printf "not a stmt\n"; [] @@ -90,11 +90,8 @@ module Stmt:Callstack_Type = struct end (* Lifters for the Callstring approach with different Callstack element types*) -module CallstringLifter_Fundec = Spec (Fundec) -module CallstringLifter_Stmt = Spec (Stmt) - let _ = - MCP.register_analysis (module CallstringLifter_Fundec : MCPSpec); - MCP.register_analysis (module CallstringLifter_Stmt : MCPSpec) + MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec) (* name: callstring_stmt*) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index ad780f7cb2..bb2862b599 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -965,6 +965,18 @@ "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", "type": "boolean", "default": false + }, + "ctx_gas_value": { + "title": "ana.context.ctx_gas_value", + "description": "Number of calls that are analyzed context sensitive. Used for the ContextGasLifter. Must be >= 0!", + "type": "integer", + "default": 10 + }, + "callStack_height": { + "title": "ana.context.callStack_height", + "description": "Number of elements of the callStack that should be used as context for the callsting analysis. Must be >= 0!", + "type": "integer", + "default": 10 } }, "additionalProperties": false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index f150754e6a..182f04a5dc 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -531,14 +531,12 @@ struct let of_elt (x, _) = of_elt x end - let cg_init_val = 10 (* initial value of context gas*) - (* returns context gas value of the given ctx*) let cg_val ctx = snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) - let name () = S.name ()^" with context gas (" ^ (string_of_int cg_init_val) ^")" - let startstate v = S.startstate v, cg_init_val + let name () = S.name ()^" with context gas" + let startstate v = S.startstate v, (get_int "ana.context.ctx_gas_value") let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i @@ -561,14 +559,14 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - let rec showExprList args = (*TODO: delete, just here for printing*) + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) @@ -590,7 +588,6 @@ struct let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's possible to decrease the counter also here*) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx - end module type Increment = From 958b6193c50ebf63b235aa7bf71eb2a8c2ec2f59 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 5 Dec 2023 19:12:28 +0100 Subject: [PATCH 061/128] built right context for callstring analysis in mcp; deleted unnecessary entry in options.schema.json; some random modules due to a lot of installations BECAUSE GOBLINTS MAKE AND MAKE INSTALL IS NOT WORKING AND I DONT KNOW WHY! --- node_modules/.package-lock.json | 19 +++++ node_modules/resolve-url/.jshintrc | 44 +++++++++++ node_modules/resolve-url/LICENSE | 21 +++++ node_modules/resolve-url/bower.json | 15 ++++ node_modules/resolve-url/changelog.md | 15 ++++ node_modules/resolve-url/component.json | 15 ++++ node_modules/resolve-url/package.json | 34 ++++++++ node_modules/resolve-url/readme.md | 83 ++++++++++++++++++++ node_modules/resolve-url/resolve-url.js | 47 +++++++++++ node_modules/resolve-url/test/resolve-url.js | 70 +++++++++++++++++ node_modules/urix/.jshintrc | 42 ++++++++++ node_modules/urix/LICENSE | 21 +++++ node_modules/urix/index.js | 17 ++++ node_modules/urix/package.json | 25 ++++++ node_modules/urix/readme.md | 46 +++++++++++ node_modules/urix/test/index.js | 43 ++++++++++ package-lock.json | 38 +++++++++ package.json | 6 ++ src/analyses/mCP.ml | 18 +++-- src/config/options.schema.json | 12 +-- 20 files changed, 619 insertions(+), 12 deletions(-) create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/resolve-url/.jshintrc create mode 100644 node_modules/resolve-url/LICENSE create mode 100644 node_modules/resolve-url/bower.json create mode 100644 node_modules/resolve-url/changelog.md create mode 100644 node_modules/resolve-url/component.json create mode 100644 node_modules/resolve-url/package.json create mode 100644 node_modules/resolve-url/readme.md create mode 100644 node_modules/resolve-url/resolve-url.js create mode 100644 node_modules/resolve-url/test/resolve-url.js create mode 100644 node_modules/urix/.jshintrc create mode 100644 node_modules/urix/LICENSE create mode 100644 node_modules/urix/index.js create mode 100644 node_modules/urix/package.json create mode 100644 node_modules/urix/readme.md create mode 100644 node_modules/urix/test/index.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000000..1ea8705627 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,19 @@ +{ + "name": "GobContextGas", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + } + } +} diff --git a/node_modules/resolve-url/.jshintrc b/node_modules/resolve-url/.jshintrc new file mode 100644 index 0000000000..aaf335801c --- /dev/null +++ b/node_modules/resolve-url/.jshintrc @@ -0,0 +1,44 @@ +{ + "bitwise": true, + "camelcase": true, + "curly": false, + "eqeqeq": true, + "es3": true, + "forin": true, + "immed": false, + "indent": false, + "latedef": "nofunc", + "newcap": false, + "noarg": true, + "noempty": true, + "nonew": false, + "plusplus": false, + "quotmark": false, + "undef": true, + "unused": "vars", + "strict": false, + "trailing": true, + "maxparams": 5, + "maxdepth": false, + "maxstatements": false, + "maxcomplexity": false, + "maxlen": 100, + + "asi": true, + "expr": true, + "globalstrict": true, + "smarttabs": true, + "sub": true, + + "node": true, + "browser": true, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false, + "define": false + } +} diff --git a/node_modules/resolve-url/LICENSE b/node_modules/resolve-url/LICENSE new file mode 100644 index 0000000000..0595be3671 --- /dev/null +++ b/node_modules/resolve-url/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/resolve-url/bower.json b/node_modules/resolve-url/bower.json new file mode 100644 index 0000000000..31aa6f4ea7 --- /dev/null +++ b/node_modules/resolve-url/bower.json @@ -0,0 +1,15 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "authors": ["Simon Lydell"], + "license": "MIT", + "main": "resolve-url.js", + "keywords": [ + "resolve", + "url" + ], + "ignore": [ + ".*" + ] +} diff --git a/node_modules/resolve-url/changelog.md b/node_modules/resolve-url/changelog.md new file mode 100644 index 0000000000..2a4a6304ca --- /dev/null +++ b/node_modules/resolve-url/changelog.md @@ -0,0 +1,15 @@ +### Version 0.2.1 (2014-02-25) ### + +- Fix edge case when (accidentally) supplying only one argument, and that + argument happens to be a falsy value such as `undefined` or `null`. + + +### Version 0.2.0 (2014-02-24) ### + +- Disallow passing 0 arguments. It’s weird and inconsistent between browsers. + (Backwards incompatible change.) + + +### Version 0.1.0 (2014-02-23) ### + +- Initial release. diff --git a/node_modules/resolve-url/component.json b/node_modules/resolve-url/component.json new file mode 100644 index 0000000000..f37cf00554 --- /dev/null +++ b/node_modules/resolve-url/component.json @@ -0,0 +1,15 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "license": "MIT", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "main": "resolve-url.js", + "repo": "lydell/resolve-url", + "keywords": [ + "resolve", + "url" + ], + "scripts": [ + "resolve-url.js" + ] +} diff --git a/node_modules/resolve-url/package.json b/node_modules/resolve-url/package.json new file mode 100644 index 0000000000..9442366332 --- /dev/null +++ b/node_modules/resolve-url/package.json @@ -0,0 +1,34 @@ +{ + "name": "resolve-url", + "version": "0.2.1", + "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", + "author": "Simon Lydell", + "license": "MIT", + "main": "resolve-url.js", + "repository": "lydell/resolve-url", + "keywords": [ + "resolve", + "url" + ], + "scripts": { + "test": "jshint resolve-url.js test/ && testling -u" + }, + "devDependencies": { + "testling": "~1.6.0", + "jshint": "~2.4.3", + "tape": "~2.5.0" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "chrome/latest", + "firefox/latest", + "opera/12", + "opera/latest", + "safari/5", + "iphone/6", + "android-browser/4" + ] + } +} diff --git a/node_modules/resolve-url/readme.md b/node_modules/resolve-url/readme.md new file mode 100644 index 0000000000..edfff7357c --- /dev/null +++ b/node_modules/resolve-url/readme.md @@ -0,0 +1,83 @@ +Overview +======== + +[![browser support](https://ci.testling.com/lydell/resolve-url.png)](https://ci.testling.com/lydell/resolve-url) + +Like Node.js’ [`path.resolve`]/[`url.resolve`] for the browser. + +```js +var resolveUrl = require("resolve-url") + +window.location +// https://example.com/articles/resolving-urls/edit + +resolveUrl("remove") +// https://example.com/articles/resolving-urls/remove + +resolveUrl("/static/scripts/app.js") +// https://example.com/static/scripts/app.js + +// Imagine /static/scripts/app.js contains `//# sourceMappingURL=../source-maps/app.js.map` +resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map") +// https://example.com/static/source-maps/app.js.map + +resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee") +// https://example.com/static/coffee/app.coffee + +resolveUrl("//cdn.example.com/jquery.js") +// https://cdn.example.com/jquery.js + +resolveUrl("http://foo.org/") +// http://foo.org/ +``` + + +Installation +============ + +- `npm install resolve-url` +- `bower install resolve-url` +- `component install lydell/resolve-url` + +Works with CommonJS, AMD and browser globals, through UMD. + + +Usage +===== + +### `resolveUrl(...urls)` ### + +Pass one or more urls. Resolves the last one to an absolute url, using the +previous ones and `window.location`. + +It’s like starting out on `window.location`, and then clicking links with the +urls as `href` attributes in order, from left to right. + +Unlike Node.js’ [`path.resolve`], this function always goes through all of the +arguments, from left to right. `path.resolve` goes from right to left and only +in the worst case goes through them all. Should that matter. + +Actually, the function is _really_ like clicking a lot of links in series: An +actual `` gets its `href` attribute set for each url! This means that the +url resolution of the browser is used, which makes this module really +light-weight. + +Also note that this functions deals with urls, not paths, so in that respect it +has more in common with Node.js’ [`url.resolve`]. But the arguments are more +like [`path.resolve`]. + +[`path.resolve`]: http://nodejs.org/api/path.html#path_path_resolve_from_to +[`url.resolve`]: http://nodejs.org/api/url.html#url_url_resolve_from_to + + +Tests +===== + +Run `npm test`, which lints the code and then gives you a link to open in a +browser of choice (using `testling`). + + +License +======= + +[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/resolve-url/resolve-url.js b/node_modules/resolve-url/resolve-url.js new file mode 100644 index 0000000000..19e8d040ec --- /dev/null +++ b/node_modules/resolve-url/resolve-url.js @@ -0,0 +1,47 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +void (function(root, factory) { + if (typeof define === "function" && define.amd) { + define(factory) + } else if (typeof exports === "object") { + module.exports = factory() + } else { + root.resolveUrl = factory() + } +}(this, function() { + + function resolveUrl(/* ...urls */) { + var numUrls = arguments.length + + if (numUrls === 0) { + throw new Error("resolveUrl requires at least one argument; got none.") + } + + var base = document.createElement("base") + base.href = arguments[0] + + if (numUrls === 1) { + return base.href + } + + var head = document.getElementsByTagName("head")[0] + head.insertBefore(base, head.firstChild) + + var a = document.createElement("a") + var resolved + + for (var index = 1; index < numUrls; index++) { + a.href = arguments[index] + resolved = a.href + base.href = resolved + } + + head.removeChild(base) + + return resolved + } + + return resolveUrl + +})); diff --git a/node_modules/resolve-url/test/resolve-url.js b/node_modules/resolve-url/test/resolve-url.js new file mode 100644 index 0000000000..18532edd32 --- /dev/null +++ b/node_modules/resolve-url/test/resolve-url.js @@ -0,0 +1,70 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var test = require("tape") + +var resolveUrl = require("../") + +"use strict" + +test("resolveUrl", function(t) { + + t.plan(7) + + t.equal(typeof resolveUrl, "function", "is a function") + + t.equal( + resolveUrl("https://example.com/"), + "https://example.com/" + ) + + var loc = "https://example.com/articles/resolving-urls/edit" + + t.equal( + resolveUrl(loc, "remove"), + "https://example.com/articles/resolving-urls/remove" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js"), + "https://example.com/static/scripts/app.js" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map"), + "https://example.com/static/source-maps/app.js.map" + ) + + t.equal( + resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee"), + "https://example.com/static/coffee/app.coffee" + ) + + t.equal( + resolveUrl(loc, "//cdn.example.com/jquery.js"), + "https://cdn.example.com/jquery.js" + ) + +}) + +test("edge cases", function(t) { + + t.plan(4) + + t["throws"](resolveUrl, /at least one argument/, "throws with no arguments") + + var accidentallyUndefined + var result + t.doesNotThrow( + function() { result = resolveUrl(accidentallyUndefined) }, + "undefined is still an argument" + ) + t.ok(result.match(/\/undefined$/), "undefined is stringified") + + t.equal( + resolveUrl("http://foo.org/test", undefined, {}, ["a/b"], null), + "http://foo.org/a/null", + "arguments are stringified" + ) + +}) diff --git a/node_modules/urix/.jshintrc b/node_modules/urix/.jshintrc new file mode 100644 index 0000000000..9d1a618361 --- /dev/null +++ b/node_modules/urix/.jshintrc @@ -0,0 +1,42 @@ +{ + "bitwise": true, + "camelcase": true, + "curly": false, + "eqeqeq": true, + "es3": false, + "forin": true, + "immed": false, + "indent": false, + "latedef": "nofunc", + "newcap": false, + "noarg": true, + "noempty": true, + "nonew": false, + "plusplus": false, + "quotmark": true, + "undef": true, + "unused": "vars", + "strict": false, + "trailing": true, + "maxparams": 5, + "maxdepth": false, + "maxstatements": false, + "maxcomplexity": false, + "maxlen": 100, + + "asi": true, + "expr": true, + "globalstrict": true, + "smarttabs": true, + "sub": true, + + "node": true, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false + } +} diff --git a/node_modules/urix/LICENSE b/node_modules/urix/LICENSE new file mode 100644 index 0000000000..0595be3671 --- /dev/null +++ b/node_modules/urix/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/urix/index.js b/node_modules/urix/index.js new file mode 100644 index 0000000000..dc6ef2700f --- /dev/null +++ b/node_modules/urix/index.js @@ -0,0 +1,17 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") + +"use strict" + +function urix(aPath) { + if (path.sep === "\\") { + return aPath + .replace(/\\/g, "/") + .replace(/^[a-z]:\/?/i, "/") + } + return aPath +} + +module.exports = urix diff --git a/node_modules/urix/package.json b/node_modules/urix/package.json new file mode 100644 index 0000000000..992e329594 --- /dev/null +++ b/node_modules/urix/package.json @@ -0,0 +1,25 @@ +{ + "name": "urix", + "version": "0.1.0", + "author": "Simon Lydell", + "license": "MIT", + "description": "Makes Windows-style paths more unix and URI friendly.", + "main": "index.js", + "repository": "lydell/urix", + "keywords": [ + "path", + "url", + "uri", + "unix", + "windows", + "backslash", + "slash" + ], + "scripts": { + "test": "jshint index.js test/ && mocha" + }, + "devDependencies": { + "mocha": "^1.17.1", + "jshint": "^2.4.4" + } +} diff --git a/node_modules/urix/readme.md b/node_modules/urix/readme.md new file mode 100644 index 0000000000..b258b98635 --- /dev/null +++ b/node_modules/urix/readme.md @@ -0,0 +1,46 @@ +[![Build Status](https://travis-ci.org/lydell/urix.png?branch=master)](https://travis-ci.org/lydell/urix) + +Overview +======== + +Makes Windows-style paths more unix and URI friendly. Useful if you work with +paths that eventually will be used in URLs. + +```js +var urix = require("urix") + +// On Windows: +urix("c:\\users\\you\\foo") +// /users/you/foo + +// On unix-like systems: +urix("c:\\users\\you\\foo") +// c:\users\you\foo +``` + + +Installation +============ + +`npm install urix` + +```js +var urix = require("urix") +``` + + +Usage +===== + +### `urix(path)` ### + +On Windows, replaces all backslashes with slashes and uses a slash instead of a +drive letter and a colon for absolute paths. + +On unix-like systems it is a no-op. + + +License +======= + +[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/urix/test/index.js b/node_modules/urix/test/index.js new file mode 100644 index 0000000000..5333f24635 --- /dev/null +++ b/node_modules/urix/test/index.js @@ -0,0 +1,43 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") +var assert = require("assert") +var urix = require("../") + +"use stict" + +function test(testPath, expected) { + path.sep = "\\" + assert.equal(urix(testPath), expected) + path.sep = "/" + assert.equal(urix(testPath), testPath) +} + +describe("urix", function() { + + it("is a function", function() { + assert.equal(typeof urix, "function") + }) + + + it("converts backslashes to slashes", function() { + test("a\\b\\c", "a/b/c") + test("\\a\\b\\c", "/a/b/c") + test("a/b\\c", "a/b/c") + test("\\\\a\\\\\\b///c", "//a///b///c") + }) + + + it("changes the drive letter to a slash", function() { + test("c:\\a", "/a") + test("C:\\a", "/a") + test("z:\\a", "/a") + test("c:a", "/a") + test("c:/a", "/a") + test("c:\\\\a", "//a") + test("c://a", "//a") + test("c:\\//a", "///a") + }) + +}) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..4f5e3ab2f2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,38 @@ +{ + "name": "GobContextGas", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "GobContextGas", + "dependencies": { + "resolve-url": "^0.2.1", + "urix": "^0.1.0" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + } + }, + "dependencies": { + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..8d7a4d3861 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "resolve-url": "^0.2.1", + "urix": "^0.1.0" + } +} diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 50f6d5409b..f9e914b4a1 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -76,11 +76,15 @@ struct List.map f in let xs = get_string_list "ana.activated" in + let callstring_enabled = (mem "callstring_fundec" xs) || (mem "callstring_stmt" xs) in + let cont_callstring = filter (fun x -> x <> "callstring_fundec" && x <> "callstring_stmt") xs in (*the contexts that are insensitive due to the callstring approach*) let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; path_sens := map' find_id @@ get_string_list "ana.path_sens"; - cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + if callstring_enabled + then cont_inse := map' find_id cont_callstring + else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; check_deps !activated; activated := topo_sort_an !activated; activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; @@ -105,7 +109,7 @@ struct let ys = fold_left one_el [] xs in List.rev ys, !dead - let context fd x = + let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> if mem n !cont_inse then @@ -180,13 +184,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/config/options.schema.json b/src/config/options.schema.json index bb2862b599..97a03b2d6c 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -532,9 +532,7 @@ "wideningThresholds", "memsafetySpecification", "termination", - "tmpSpecialAnalysis", - "callstring_fundec", - "callstring_stmt" + "tmpSpecialAnalysis" ] }, "default": [ @@ -639,7 +637,11 @@ "title": "ana.base.strings.domain", "description": "Domain for string literals.", "type": "string", - "enum": ["unit", "flat", "disjoint"], + "enum": [ + "unit", + "flat", + "disjoint" + ], "default": "flat" } }, @@ -2205,7 +2207,7 @@ }, "memleak": { "title": "warn.memleak", - "type":"object", + "type": "object", "properties": { "memcleanup": { "title": "warn.memleak.memcleanup", From 8fbfe6729e11d3807d45fd84386de7e4a4eda3d7 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 6 Dec 2023 12:06:22 +0100 Subject: [PATCH 062/128] now also multiple calls are handled properly by the callstring Ana; added testcaseses using both callstring Anas --- node_modules/.package-lock.json | 19 ----- node_modules/resolve-url/.jshintrc | 44 ---------- node_modules/resolve-url/LICENSE | 21 ----- node_modules/resolve-url/bower.json | 15 ---- node_modules/resolve-url/changelog.md | 15 ---- node_modules/resolve-url/component.json | 15 ---- node_modules/resolve-url/package.json | 34 -------- node_modules/resolve-url/readme.md | 83 ------------------- node_modules/resolve-url/resolve-url.js | 47 ----------- node_modules/resolve-url/test/resolve-url.js | 70 ---------------- node_modules/urix/.jshintrc | 42 ---------- node_modules/urix/LICENSE | 21 ----- node_modules/urix/index.js | 17 ---- node_modules/urix/package.json | 25 ------ node_modules/urix/readme.md | 46 ---------- node_modules/urix/test/index.js | 43 ---------- package-lock.json | 38 --------- src/analyses/callstringAnalysis.ml | 16 ++-- .../84-callstring_both/01-simple_rec_sens.c | 22 +++++ .../84-callstring_both/02-simple_rec_ins.c | 22 +++++ .../84-callstring_both/03-multiple_rec_sens.c | 59 +++++++++++++ .../84-callstring_both/04-multiple_rec_ins.c | 59 +++++++++++++ 22 files changed, 171 insertions(+), 602 deletions(-) delete mode 100644 node_modules/.package-lock.json delete mode 100644 node_modules/resolve-url/.jshintrc delete mode 100644 node_modules/resolve-url/LICENSE delete mode 100644 node_modules/resolve-url/bower.json delete mode 100644 node_modules/resolve-url/changelog.md delete mode 100644 node_modules/resolve-url/component.json delete mode 100644 node_modules/resolve-url/package.json delete mode 100644 node_modules/resolve-url/readme.md delete mode 100644 node_modules/resolve-url/resolve-url.js delete mode 100644 node_modules/resolve-url/test/resolve-url.js delete mode 100644 node_modules/urix/.jshintrc delete mode 100644 node_modules/urix/LICENSE delete mode 100644 node_modules/urix/index.js delete mode 100644 node_modules/urix/package.json delete mode 100644 node_modules/urix/readme.md delete mode 100644 node_modules/urix/test/index.js delete mode 100644 package-lock.json create mode 100644 tests/regression/84-callstring_both/01-simple_rec_sens.c create mode 100644 tests/regression/84-callstring_both/02-simple_rec_ins.c create mode 100644 tests/regression/84-callstring_both/03-multiple_rec_sens.c create mode 100644 tests/regression/84-callstring_both/04-multiple_rec_ins.c diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json deleted file mode 100644 index 1ea8705627..0000000000 --- a/node_modules/.package-lock.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "GobContextGas", - "lockfileVersion": 2, - "requires": true, - "packages": { - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - } - } -} diff --git a/node_modules/resolve-url/.jshintrc b/node_modules/resolve-url/.jshintrc deleted file mode 100644 index aaf335801c..0000000000 --- a/node_modules/resolve-url/.jshintrc +++ /dev/null @@ -1,44 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": false, - "eqeqeq": true, - "es3": true, - "forin": true, - "immed": false, - "indent": false, - "latedef": "nofunc", - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": false, - "undef": true, - "unused": "vars", - "strict": false, - "trailing": true, - "maxparams": 5, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 100, - - "asi": true, - "expr": true, - "globalstrict": true, - "smarttabs": true, - "sub": true, - - "node": true, - "browser": true, - "globals": { - "describe": false, - "it": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false, - "define": false - } -} diff --git a/node_modules/resolve-url/LICENSE b/node_modules/resolve-url/LICENSE deleted file mode 100644 index 0595be3671..0000000000 --- a/node_modules/resolve-url/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/resolve-url/bower.json b/node_modules/resolve-url/bower.json deleted file mode 100644 index 31aa6f4ea7..0000000000 --- a/node_modules/resolve-url/bower.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "authors": ["Simon Lydell"], - "license": "MIT", - "main": "resolve-url.js", - "keywords": [ - "resolve", - "url" - ], - "ignore": [ - ".*" - ] -} diff --git a/node_modules/resolve-url/changelog.md b/node_modules/resolve-url/changelog.md deleted file mode 100644 index 2a4a6304ca..0000000000 --- a/node_modules/resolve-url/changelog.md +++ /dev/null @@ -1,15 +0,0 @@ -### Version 0.2.1 (2014-02-25) ### - -- Fix edge case when (accidentally) supplying only one argument, and that - argument happens to be a falsy value such as `undefined` or `null`. - - -### Version 0.2.0 (2014-02-24) ### - -- Disallow passing 0 arguments. It’s weird and inconsistent between browsers. - (Backwards incompatible change.) - - -### Version 0.1.0 (2014-02-23) ### - -- Initial release. diff --git a/node_modules/resolve-url/component.json b/node_modules/resolve-url/component.json deleted file mode 100644 index f37cf00554..0000000000 --- a/node_modules/resolve-url/component.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "license": "MIT", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "main": "resolve-url.js", - "repo": "lydell/resolve-url", - "keywords": [ - "resolve", - "url" - ], - "scripts": [ - "resolve-url.js" - ] -} diff --git a/node_modules/resolve-url/package.json b/node_modules/resolve-url/package.json deleted file mode 100644 index 9442366332..0000000000 --- a/node_modules/resolve-url/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "resolve-url", - "version": "0.2.1", - "description": "Like Node.js’ `path.resolve`/`url.resolve` for the browser.", - "author": "Simon Lydell", - "license": "MIT", - "main": "resolve-url.js", - "repository": "lydell/resolve-url", - "keywords": [ - "resolve", - "url" - ], - "scripts": { - "test": "jshint resolve-url.js test/ && testling -u" - }, - "devDependencies": { - "testling": "~1.6.0", - "jshint": "~2.4.3", - "tape": "~2.5.0" - }, - "testling": { - "files": "test/*.js", - "browsers": [ - "ie/8..latest", - "chrome/latest", - "firefox/latest", - "opera/12", - "opera/latest", - "safari/5", - "iphone/6", - "android-browser/4" - ] - } -} diff --git a/node_modules/resolve-url/readme.md b/node_modules/resolve-url/readme.md deleted file mode 100644 index edfff7357c..0000000000 --- a/node_modules/resolve-url/readme.md +++ /dev/null @@ -1,83 +0,0 @@ -Overview -======== - -[![browser support](https://ci.testling.com/lydell/resolve-url.png)](https://ci.testling.com/lydell/resolve-url) - -Like Node.js’ [`path.resolve`]/[`url.resolve`] for the browser. - -```js -var resolveUrl = require("resolve-url") - -window.location -// https://example.com/articles/resolving-urls/edit - -resolveUrl("remove") -// https://example.com/articles/resolving-urls/remove - -resolveUrl("/static/scripts/app.js") -// https://example.com/static/scripts/app.js - -// Imagine /static/scripts/app.js contains `//# sourceMappingURL=../source-maps/app.js.map` -resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map") -// https://example.com/static/source-maps/app.js.map - -resolveUrl("/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee") -// https://example.com/static/coffee/app.coffee - -resolveUrl("//cdn.example.com/jquery.js") -// https://cdn.example.com/jquery.js - -resolveUrl("http://foo.org/") -// http://foo.org/ -``` - - -Installation -============ - -- `npm install resolve-url` -- `bower install resolve-url` -- `component install lydell/resolve-url` - -Works with CommonJS, AMD and browser globals, through UMD. - - -Usage -===== - -### `resolveUrl(...urls)` ### - -Pass one or more urls. Resolves the last one to an absolute url, using the -previous ones and `window.location`. - -It’s like starting out on `window.location`, and then clicking links with the -urls as `href` attributes in order, from left to right. - -Unlike Node.js’ [`path.resolve`], this function always goes through all of the -arguments, from left to right. `path.resolve` goes from right to left and only -in the worst case goes through them all. Should that matter. - -Actually, the function is _really_ like clicking a lot of links in series: An -actual `` gets its `href` attribute set for each url! This means that the -url resolution of the browser is used, which makes this module really -light-weight. - -Also note that this functions deals with urls, not paths, so in that respect it -has more in common with Node.js’ [`url.resolve`]. But the arguments are more -like [`path.resolve`]. - -[`path.resolve`]: http://nodejs.org/api/path.html#path_path_resolve_from_to -[`url.resolve`]: http://nodejs.org/api/url.html#url_url_resolve_from_to - - -Tests -===== - -Run `npm test`, which lints the code and then gives you a link to open in a -browser of choice (using `testling`). - - -License -======= - -[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/resolve-url/resolve-url.js b/node_modules/resolve-url/resolve-url.js deleted file mode 100644 index 19e8d040ec..0000000000 --- a/node_modules/resolve-url/resolve-url.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -void (function(root, factory) { - if (typeof define === "function" && define.amd) { - define(factory) - } else if (typeof exports === "object") { - module.exports = factory() - } else { - root.resolveUrl = factory() - } -}(this, function() { - - function resolveUrl(/* ...urls */) { - var numUrls = arguments.length - - if (numUrls === 0) { - throw new Error("resolveUrl requires at least one argument; got none.") - } - - var base = document.createElement("base") - base.href = arguments[0] - - if (numUrls === 1) { - return base.href - } - - var head = document.getElementsByTagName("head")[0] - head.insertBefore(base, head.firstChild) - - var a = document.createElement("a") - var resolved - - for (var index = 1; index < numUrls; index++) { - a.href = arguments[index] - resolved = a.href - base.href = resolved - } - - head.removeChild(base) - - return resolved - } - - return resolveUrl - -})); diff --git a/node_modules/resolve-url/test/resolve-url.js b/node_modules/resolve-url/test/resolve-url.js deleted file mode 100644 index 18532edd32..0000000000 --- a/node_modules/resolve-url/test/resolve-url.js +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var test = require("tape") - -var resolveUrl = require("../") - -"use strict" - -test("resolveUrl", function(t) { - - t.plan(7) - - t.equal(typeof resolveUrl, "function", "is a function") - - t.equal( - resolveUrl("https://example.com/"), - "https://example.com/" - ) - - var loc = "https://example.com/articles/resolving-urls/edit" - - t.equal( - resolveUrl(loc, "remove"), - "https://example.com/articles/resolving-urls/remove" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js"), - "https://example.com/static/scripts/app.js" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map"), - "https://example.com/static/source-maps/app.js.map" - ) - - t.equal( - resolveUrl(loc, "/static/scripts/app.js", "../source-maps/app.js.map", "../coffee/app.coffee"), - "https://example.com/static/coffee/app.coffee" - ) - - t.equal( - resolveUrl(loc, "//cdn.example.com/jquery.js"), - "https://cdn.example.com/jquery.js" - ) - -}) - -test("edge cases", function(t) { - - t.plan(4) - - t["throws"](resolveUrl, /at least one argument/, "throws with no arguments") - - var accidentallyUndefined - var result - t.doesNotThrow( - function() { result = resolveUrl(accidentallyUndefined) }, - "undefined is still an argument" - ) - t.ok(result.match(/\/undefined$/), "undefined is stringified") - - t.equal( - resolveUrl("http://foo.org/test", undefined, {}, ["a/b"], null), - "http://foo.org/a/null", - "arguments are stringified" - ) - -}) diff --git a/node_modules/urix/.jshintrc b/node_modules/urix/.jshintrc deleted file mode 100644 index 9d1a618361..0000000000 --- a/node_modules/urix/.jshintrc +++ /dev/null @@ -1,42 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": false, - "eqeqeq": true, - "es3": false, - "forin": true, - "immed": false, - "indent": false, - "latedef": "nofunc", - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": true, - "undef": true, - "unused": "vars", - "strict": false, - "trailing": true, - "maxparams": 5, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 100, - - "asi": true, - "expr": true, - "globalstrict": true, - "smarttabs": true, - "sub": true, - - "node": true, - "globals": { - "describe": false, - "it": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false - } -} diff --git a/node_modules/urix/LICENSE b/node_modules/urix/LICENSE deleted file mode 100644 index 0595be3671..0000000000 --- a/node_modules/urix/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/urix/index.js b/node_modules/urix/index.js deleted file mode 100644 index dc6ef2700f..0000000000 --- a/node_modules/urix/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = require("path") - -"use strict" - -function urix(aPath) { - if (path.sep === "\\") { - return aPath - .replace(/\\/g, "/") - .replace(/^[a-z]:\/?/i, "/") - } - return aPath -} - -module.exports = urix diff --git a/node_modules/urix/package.json b/node_modules/urix/package.json deleted file mode 100644 index 992e329594..0000000000 --- a/node_modules/urix/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "urix", - "version": "0.1.0", - "author": "Simon Lydell", - "license": "MIT", - "description": "Makes Windows-style paths more unix and URI friendly.", - "main": "index.js", - "repository": "lydell/urix", - "keywords": [ - "path", - "url", - "uri", - "unix", - "windows", - "backslash", - "slash" - ], - "scripts": { - "test": "jshint index.js test/ && mocha" - }, - "devDependencies": { - "mocha": "^1.17.1", - "jshint": "^2.4.4" - } -} diff --git a/node_modules/urix/readme.md b/node_modules/urix/readme.md deleted file mode 100644 index b258b98635..0000000000 --- a/node_modules/urix/readme.md +++ /dev/null @@ -1,46 +0,0 @@ -[![Build Status](https://travis-ci.org/lydell/urix.png?branch=master)](https://travis-ci.org/lydell/urix) - -Overview -======== - -Makes Windows-style paths more unix and URI friendly. Useful if you work with -paths that eventually will be used in URLs. - -```js -var urix = require("urix") - -// On Windows: -urix("c:\\users\\you\\foo") -// /users/you/foo - -// On unix-like systems: -urix("c:\\users\\you\\foo") -// c:\users\you\foo -``` - - -Installation -============ - -`npm install urix` - -```js -var urix = require("urix") -``` - - -Usage -===== - -### `urix(path)` ### - -On Windows, replaces all backslashes with slashes and uses a slash instead of a -drive letter and a colon for absolute paths. - -On unix-like systems it is a no-op. - - -License -======= - -[The X11 (“MIT”) License](LICENSE). diff --git a/node_modules/urix/test/index.js b/node_modules/urix/test/index.js deleted file mode 100644 index 5333f24635..0000000000 --- a/node_modules/urix/test/index.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = require("path") -var assert = require("assert") -var urix = require("../") - -"use stict" - -function test(testPath, expected) { - path.sep = "\\" - assert.equal(urix(testPath), expected) - path.sep = "/" - assert.equal(urix(testPath), testPath) -} - -describe("urix", function() { - - it("is a function", function() { - assert.equal(typeof urix, "function") - }) - - - it("converts backslashes to slashes", function() { - test("a\\b\\c", "a/b/c") - test("\\a\\b\\c", "/a/b/c") - test("a/b\\c", "a/b/c") - test("\\\\a\\\\\\b///c", "//a///b///c") - }) - - - it("changes the drive letter to a slash", function() { - test("c:\\a", "/a") - test("C:\\a", "/a") - test("z:\\a", "/a") - test("c:a", "/a") - test("c:/a", "/a") - test("c:\\\\a", "//a") - test("c://a", "//a") - test("c:\\//a", "///a") - }) - -}) diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 4f5e3ab2f2..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "GobContextGas", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "GobContextGas", - "dependencies": { - "resolve-url": "^0.2.1", - "urix": "^0.1.0" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - } - }, - "dependencies": { - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" - } - } -} diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 94a4e93aab..1edf14540c 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -48,17 +48,17 @@ struct let startstate v = [] let exitstate v = [] - let context fd d = d - let enter ctx r f args = let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push (ctx.local) elem in - let ctx' = {ctx with context = (fun () -> new_stack) - ; local = new_stack} in - if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) (ctx'.local); (* just for debugging purpose*) + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) [ctx.local, new_stack] + + let combine_env ctx lval fexp f args fc au f_ask = + ctx.local end + module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" @@ -76,9 +76,11 @@ end module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" - let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + let pushElem f args ctx = + match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) | Statement stmt -> [stmt] - | _ -> printf "not a stmt\n"; [] + | _ -> [] (* first statement is filtered*) + let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); diff --git a/tests/regression/84-callstring_both/01-simple_rec_sens.c b/tests/regression/84-callstring_both/01-simple_rec_sens.c new file mode 100644 index 0000000000..210ecfb4d8 --- /dev/null +++ b/tests/regression/84-callstring_both/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/84-callstring_both/02-simple_rec_ins.c b/tests/regression/84-callstring_both/02-simple_rec_ins.c new file mode 100644 index 0000000000..7be2bedcf7 --- /dev/null +++ b/tests/regression/84-callstring_both/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/84-callstring_both/03-multiple_rec_sens.c b/tests/regression/84-callstring_both/03-multiple_rec_sens.c new file mode 100644 index 0000000000..0b7977a28f --- /dev/null +++ b/tests/regression/84-callstring_both/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/84-callstring_both/04-multiple_rec_ins.c b/tests/regression/84-callstring_both/04-multiple_rec_ins.c new file mode 100644 index 0000000000..65903ff22d --- /dev/null +++ b/tests/regression/84-callstring_both/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} From d0b6e83a7cda1c7994f3ec623f91276331031fb4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 6 Dec 2023 14:40:17 +0100 Subject: [PATCH 063/128] 2 lists for stack representation in callstring --- src/analyses/callstringAnalysis.ml | 58 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 1edf14540c..da5127a2f6 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -8,8 +8,8 @@ module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t list (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t list -> t list -> unit (* a helper function to print the callstack *) + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> (t list * t list) -> (t list * t list) -> unit (* a helper function to print the callstack *) end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context @@ -21,22 +21,20 @@ struct (* simulates a call stack of depth k*) module CallStack = struct - include Printable.Liszt (CT) + include Printable.Prod (Printable.Liszt (CT)) (Printable.Liszt (CT)) let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) + let length (stack_first, stack_last) = List.length stack_first + List.length stack_last let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - let rec take n = function - | [] -> [] - | x :: xs when n > 0 -> x :: take (n - 1) xs - | _ -> [] - in - let remaining_space = depth - List.length elem in - if remaining_space >= 0 - then - let remaining_stack = take remaining_space (List.rev stack) in - List.rev_append remaining_stack elem - else - List.rev(take depth (List.rev elem)) + match elem with + | None -> stack + | Some e -> + match (length stack >= depth), stack with + | _, ([], []) -> [e], [] + | false, ([], last) -> List.rev last, [e] + | false, (stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] + | true, ([], last) -> List.tl(List.rev(last)), [e] + | true, (s::stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] end module D = Lattice.Fake(CallStack) @@ -45,12 +43,12 @@ struct module G = Lattice.Unit let name () = "callstring_"^ CT.stackTypeName - let startstate v = [] - let exitstate v = [] + let startstate v = ([],[]) + let exitstate v = ([],[]) let enter ctx r f args = - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push (ctx.local) elem in + let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack: CallStack.t = CallStack.push ctx.local elem in if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) [ctx.local, new_stack] @@ -62,14 +60,16 @@ end module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" - let pushElem f args ctx = [f] + let pushElem f args ctx = Some f - let printStack f expL listA listB = + let printStack f expL (listA1, listA2) (listB1, listB2) = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listA2); printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listB2); printf "\n\n" end @@ -78,16 +78,18 @@ module Stmt:Callstack_Type = struct let stackTypeName = "stmt" let pushElem f args ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) - | Statement stmt -> [stmt] - | _ -> [] (* first statement is filtered*) + | Statement stmt -> Some stmt + | _ -> None (* first statement is filtered*) - let printStack f expL listA listB = + let printStack f expL (listA1, listA2) (listB1, listB2) = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listA2); printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listB2); printf "\n\n" end From 5cc34a2401a051242fc4403a626b3f6cf1b4ef7b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Dec 2023 11:21:58 +0100 Subject: [PATCH 064/128] added location for callstack type, added queue impl in printable, added sv comp files, added tests for loc --- conf/svcomp80-context_gas.json | 98 +++++++++++++++++ conf/svcomp82-callstringFundec.json | 99 +++++++++++++++++ conf/svcomp83-callstringLoc.json | 99 +++++++++++++++++ conf/svcomp84-callstringBoth.json | 100 ++++++++++++++++++ src/analyses/callstringAnalysis.ml | 25 ++++- src/common/domains/printable.ml | 35 ++++++ .../85-callstring_Loc/01-simple_rec_sens.c | 22 ++++ .../85-callstring_Loc/02-simple_rec_ins.c | 22 ++++ .../85-callstring_Loc/03-multiple_rec_sens.c | 59 +++++++++++ .../85-callstring_Loc/04-multiple_rec_ins.c | 59 +++++++++++ .../05-function_chain_sens.c | 54 ++++++++++ .../85-callstring_Loc/06-function_chain_ins.c | 54 ++++++++++ .../85-callstring_Loc/07-call_in_call.c | 54 ++++++++++ .../08-circle_call_and_big_loop.c | 46 ++++++++ 14 files changed, 824 insertions(+), 2 deletions(-) create mode 100644 conf/svcomp80-context_gas.json create mode 100644 conf/svcomp82-callstringFundec.json create mode 100644 conf/svcomp83-callstringLoc.json create mode 100644 conf/svcomp84-callstringBoth.json create mode 100644 tests/regression/85-callstring_Loc/01-simple_rec_sens.c create mode 100644 tests/regression/85-callstring_Loc/02-simple_rec_ins.c create mode 100644 tests/regression/85-callstring_Loc/03-multiple_rec_sens.c create mode 100644 tests/regression/85-callstring_Loc/04-multiple_rec_ins.c create mode 100644 tests/regression/85-callstring_Loc/05-function_chain_sens.c create mode 100644 tests/regression/85-callstring_Loc/06-function_chain_ins.c create mode 100644 tests/regression/85-callstring_Loc/07-call_in_call.c create mode 100644 tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c diff --git a/conf/svcomp80-context_gas.json b/conf/svcomp80-context_gas.json new file mode 100644 index 0000000000..9647039e25 --- /dev/null +++ b/conf/svcomp80-context_gas.json @@ -0,0 +1,98 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": true, + "ctx_gas_value": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp82-callstringFundec.json b/conf/svcomp82-callstringFundec.json new file mode 100644 index 0000000000..c34af435dc --- /dev/null +++ b/conf/svcomp82-callstringFundec.json @@ -0,0 +1,99 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_fundec" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp83-callstringLoc.json b/conf/svcomp83-callstringLoc.json new file mode 100644 index 0000000000..d13afb3a13 --- /dev/null +++ b/conf/svcomp83-callstringLoc.json @@ -0,0 +1,99 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_loc" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/conf/svcomp84-callstringBoth.json b/conf/svcomp84-callstringBoth.json new file mode 100644 index 0000000000..5ea84689db --- /dev/null +++ b/conf/svcomp84-callstringBoth.json @@ -0,0 +1,100 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "callstring_fundec", + "callstring_loc" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "callStack_height": 10 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate" + } + } +} \ No newline at end of file diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index da5127a2f6..525aa31339 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -26,7 +26,7 @@ struct let length (stack_first, stack_last) = List.length stack_first + List.length stack_last let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - match elem with + match elem with | None -> stack | Some e -> match (length stack >= depth), stack with @@ -93,9 +93,30 @@ module Stmt:Callstack_Type = struct printf "\n\n" end + +module Location:Callstack_Type = struct + include CilType.Location + let stackTypeName = "loc" + let pushElem f args ctx = + let q = Queue.create () in + Queue.push 1 q; + Some !Tracing.current_loc + + let printStack f expL (listA1, listA2) (listB1, listB2) = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listA2); + printf "\nList neu: "; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB1; + List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listB2); + printf "\n\n" +end + (* Lifters for the Callstring approach with different Callstack element types*) let _ = MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) - MCP.register_analysis (module Spec (Stmt) : MCPSpec) (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index d3530f40de..5f277e979f 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -506,6 +506,41 @@ module Prod4 (Base1: S) (Base2: S) (Base3: S) (Base4: S) = struct let arbitrary () = QCheck.quad (Base1.arbitrary ()) (Base2.arbitrary ()) (Base3.arbitrary ()) (Base4.arbitrary ()) end + +module Queue (Base: S) = +struct + type t = Base.t Queue.t + include Std + + let queue_map f q = + let mapped_queue = Queue.create () in + Queue.iter (fun x -> Queue.push (f x) mapped_queue) q; + mapped_queue + + let show x = + let elem = Queue.fold (fun acc elem -> elem :: acc) [] x |> List.rev in + "[" ^ (String.concat ", " elem) ^ "]" + + let pretty () x = text (show x) + let name () = Base.name () ^ "queue" + (* TODO more efficient impl*) + + let relift x = queue_map Base.relift x + + let printXml f xs = + let xs_copy = Queue.copy xs in + let rec loop n q = + if Queue.is_empty q then () + else + let x = Queue.pop q in + BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; + loop (n+1) (xs_copy) + in + BatPrintf.fprintf f "\n\n"; + loop 0 xs_copy; + BatPrintf.fprintf f "\n\n" +end + module Liszt (Base: S) = struct type t = Base.t list [@@deriving eq, ord, hash, to_yojson] diff --git a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c new file mode 100644 index 0000000000..d0639cae6a --- /dev/null +++ b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c new file mode 100644 index 0000000000..791742154d --- /dev/null +++ b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c @@ -0,0 +1,22 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 11; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c new file mode 100644 index 0000000000..1ef2a12f89 --- /dev/null +++ b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); +} diff --git a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c new file mode 100644 index 0000000000..b53aa47b32 --- /dev/null +++ b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c @@ -0,0 +1,59 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if multiple recursions are handled properly +#include + +int num_iterat = 11; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + int res5 = h(num_iterat); + + int result = res1 + res2 + res3 + res4 + res5; + __goblint_check(result == 5); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/05-function_chain_sens.c b/tests/regression/85-callstring_Loc/05-function_chain_sens.c new file mode 100644 index 0000000000..18e6605dd3 --- /dev/null +++ b/tests/regression/85-callstring_Loc/05-function_chain_sens.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 12; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); +} diff --git a/tests/regression/85-callstring_Loc/06-function_chain_ins.c b/tests/regression/85-callstring_Loc/06-function_chain_ins.c new file mode 100644 index 0000000000..4ce249d956 --- /dev/null +++ b/tests/regression/85-callstring_Loc/06-function_chain_ins.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks if function chains are handled properly +#include + +int num_iterat = 13; + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int result = f(num_iterat); + + __goblint_check(result == 1); //UNKNOWN +} diff --git a/tests/regression/85-callstring_Loc/07-call_in_call.c b/tests/regression/85-callstring_Loc/07-call_in_call.c new file mode 100644 index 0000000000..5ddb98235e --- /dev/null +++ b/tests/regression/85-callstring_Loc/07-call_in_call.c @@ -0,0 +1,54 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Interesting if nested recursions are handled properly +#include + +int num_iterat = 10; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int main(void) +{ + int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 + + __goblint_check(res == 1); +} \ No newline at end of file diff --git a/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c new file mode 100644 index 0000000000..b730dfd3f8 --- /dev/null +++ b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c @@ -0,0 +1,46 @@ +// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed +#include + +int num_iterat = 2; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(num_iterat); + int res2 = g(num_iterat); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} From 6743228d5736d15f4cd29991e0f358fb8a23c973 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Dec 2023 14:36:18 +0100 Subject: [PATCH 065/128] implemented Queue completely, added new callstringAna for usage of queue (either the queue implementation or the 2 list implementation will stay) --- src/analyses/callstringAnalysis.ml | 4 +- src/analyses/callstringAnalysisQueue.ml | 118 ++++++++++++++++++++++++ src/common/domains/printable.ml | 25 ++++- 3 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 src/analyses/callstringAnalysisQueue.ml diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 525aa31339..d622d14c51 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -117,6 +117,4 @@ end let _ = MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) - MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) - - + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) \ No newline at end of file diff --git a/src/analyses/callstringAnalysisQueue.ml b/src/analyses/callstringAnalysisQueue.ml new file mode 100644 index 0000000000..45cc3f04ec --- /dev/null +++ b/src/analyses/callstringAnalysisQueue.ml @@ -0,0 +1,118 @@ +open Analyses +open Printf +open GoblintCil +open GobConfig + +(* Specifies the type of the callstack elements for the CallstringLifter*) +module type Callstack_Type = +sig + include CilType.S + val stackTypeName: string + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) + val printStack: fundec -> exp list -> t Queue.t -> t Queue.t -> unit (* a helper function to print the callstack *) +end + +(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context + With the CT argument it is possible to specify the type of the Callstack elements +*) +module Spec (CT:Callstack_Type) : MCPSpec = +struct + include Analyses.IdentitySpec + + (* simulates a call stack of depth k*) + module CallStack = struct + include Printable.Queue (CT) + let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) + + let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + match elem with + | None -> stack + | Some e -> + Queue.push e stack; (* pushes new element to stack*) + (* remove elements from stack, till the depth k is guaranteed*) + let excess_length = max 0 (Queue.length stack - depth) in + for _ = 1 to excess_length do + ignore (Queue.pop stack) + done; + stack + end + + module D = Lattice.Fake(CallStack) + module C = CallStack + module V = EmptyV + module G = Lattice.Unit + module Q = Printable.Queue (Printable.Strings) + + let name () = "callstring_"^ CT.stackTypeName + let startstate v = Queue.create () + let exitstate v = Queue.create () + + let enter ctx r f args = + let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let old_stack: CallStack.t = Queue.copy ctx.local in + let new_stack: CallStack.t = CallStack.push old_stack elem in + if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) + [ctx.local, new_stack] + + let combine_env ctx lval fexp f args fc au f_ask = + ctx.local +end + + +module Fundec:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "fundec" + let pushElem f args ctx = Some f + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + printf "\n\n" +end + +module Stmt:Callstack_Type = struct + include CilType.Stmt + let stackTypeName = "stmt" + let pushElem f args ctx = + match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + | Statement stmt -> Some stmt + | _ -> None (* first statement is filtered*) + + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + printf "\n\n" +end + + +module Location:Callstack_Type = struct + include CilType.Location + let stackTypeName = "loc" + let pushElem f args ctx = + let q = Queue.create () in + Queue.push 1 q; + Some !Tracing.current_loc + + let printStack f expL listA listB = + printf "fundec: %s\n" (CilType.Fundec.show f); + printf "List alt: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA; + printf "\nList neu: "; + Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB; + printf "\n\n" +end + +(* Lifters for the Callstring approach with different Callstack element types*) +let _ = + MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) + MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) + + diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index 5f277e979f..c3c74d88b9 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -506,19 +506,18 @@ module Prod4 (Base1: S) (Base2: S) (Base3: S) (Base4: S) = struct let arbitrary () = QCheck.quad (Base1.arbitrary ()) (Base2.arbitrary ()) (Base3.arbitrary ()) (Base4.arbitrary ()) end - module Queue (Base: S) = struct type t = Base.t Queue.t include Std - + let queue_map f q = let mapped_queue = Queue.create () in Queue.iter (fun x -> Queue.push (f x) mapped_queue) q; mapped_queue let show x = - let elem = Queue.fold (fun acc elem -> elem :: acc) [] x |> List.rev in + let elem = Queue.fold (fun acc elem -> Base.show elem :: acc) [] x |> List.rev in "[" ^ (String.concat ", " elem) ^ "]" let pretty () x = text (show x) @@ -539,6 +538,26 @@ struct BatPrintf.fprintf f "\n\n"; loop 0 xs_copy; BatPrintf.fprintf f "\n\n" + + let rec equal_helper a b = + if Queue.is_empty a then true + else ( + let a_v = Queue.pop a in + let b_v = Queue.pop b in + if Base.equal a_v b_v + then equal_helper a b + else false) + + let equal a b = + if Queue.length a <> Queue.length b then false + else + let a_copy = Queue.copy a in + let b_copy = Queue.copy b in + equal_helper a_copy b_copy + + let to_yojson x = `String (show x) + let hash = Hashtbl.hash + let compare = Stdlib.compare end module Liszt (Base: S) = From 2acb942766ed86e6eb331bf65fbaf28013fdcf29 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 9 Dec 2023 19:30:59 +0100 Subject: [PATCH 066/128] adapted sv comp files for callstring and ctx gas; added queue implementation (queue2L); added Queue printable (using queue2L); deleted alternative callstring Ana; added Location to mCP differenciation --- conf/svcomp80-context_gas.json | 49 +++++++- conf/svcomp82-callstringFundec.json | 49 +++++++- ...Both.json => svcomp83-callstringStmt.json} | 52 +++++++- ...ngLoc.json => svcomp85-callstringLoc.json} | 49 +++++++- src/analyses/callstringAnalysis.ml | 54 ++++---- src/analyses/callstringAnalysisQueue.ml | 118 ------------------ src/analyses/mCP.ml | 4 +- src/common/domains/printable.ml | 48 ++----- src/common/util/queue2L.ml | 111 ++++++++++++++++ 9 files changed, 339 insertions(+), 195 deletions(-) rename conf/{svcomp84-callstringBoth.json => svcomp83-callstringStmt.json} (58%) rename conf/{svcomp83-callstringLoc.json => svcomp85-callstringLoc.json} (58%) delete mode 100644 src/analyses/callstringAnalysisQueue.ml create mode 100644 src/common/util/queue2L.ml diff --git a/conf/svcomp80-context_gas.json b/conf/svcomp80-context_gas.json index 9647039e25..dcf9c6b630 100644 --- a/conf/svcomp80-context_gas.json +++ b/conf/svcomp80-context_gas.json @@ -72,6 +72,22 @@ "race": { "free": false, "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] } }, "exp": { @@ -92,7 +108,38 @@ "witness": { "graphml": { "enabled": true, - "id": "enumerate" + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] } + }, + "pre": { + "enabled": false } } \ No newline at end of file diff --git a/conf/svcomp82-callstringFundec.json b/conf/svcomp82-callstringFundec.json index c34af435dc..5c53cc5597 100644 --- a/conf/svcomp82-callstringFundec.json +++ b/conf/svcomp82-callstringFundec.json @@ -73,6 +73,22 @@ "race": { "free": false, "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] } }, "exp": { @@ -93,7 +109,38 @@ "witness": { "graphml": { "enabled": true, - "id": "enumerate" + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] } + }, + "pre": { + "enabled": false } } \ No newline at end of file diff --git a/conf/svcomp84-callstringBoth.json b/conf/svcomp83-callstringStmt.json similarity index 58% rename from conf/svcomp84-callstringBoth.json rename to conf/svcomp83-callstringStmt.json index 5ea84689db..dbc750c49b 100644 --- a/conf/svcomp84-callstringBoth.json +++ b/conf/svcomp83-callstringStmt.json @@ -31,8 +31,7 @@ "region", "thread", "threadJoins", - "callstring_fundec", - "callstring_loc" + "callstring_stmt" ], "path_sens": [ "mutex", @@ -74,6 +73,22 @@ "race": { "free": false, "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] } }, "exp": { @@ -94,7 +109,38 @@ "witness": { "graphml": { "enabled": true, - "id": "enumerate" + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] } + }, + "pre": { + "enabled": false } } \ No newline at end of file diff --git a/conf/svcomp83-callstringLoc.json b/conf/svcomp85-callstringLoc.json similarity index 58% rename from conf/svcomp83-callstringLoc.json rename to conf/svcomp85-callstringLoc.json index d13afb3a13..0bb6632525 100644 --- a/conf/svcomp83-callstringLoc.json +++ b/conf/svcomp85-callstringLoc.json @@ -73,6 +73,22 @@ "race": { "free": false, "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] } }, "exp": { @@ -93,7 +109,38 @@ "witness": { "graphml": { "enabled": true, - "id": "enumerate" + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] } + }, + "pre": { + "enabled": false } } \ No newline at end of file diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index d622d14c51..740bf577fb 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -9,7 +9,7 @@ sig include CilType.S val stackTypeName: string val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> (t list * t list) -> (t list * t list) -> unit (* a helper function to print the callstack *) + val printStack: fundec -> exp list -> t Queue2L.t -> t Queue2L.t -> unit (* a helper function to print the callstack *) end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context @@ -21,20 +21,16 @@ struct (* simulates a call stack of depth k*) module CallStack = struct - include Printable.Prod (Printable.Liszt (CT)) (Printable.Liszt (CT)) + include Printable.PQueue (CT) let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) - let length (stack_first, stack_last) = List.length stack_first + List.length stack_last let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) match elem with | None -> stack | Some e -> - match (length stack >= depth), stack with - | _, ([], []) -> [e], [] - | false, ([], last) -> List.rev last, [e] - | false, (stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] - | true, ([], last) -> List.tl(List.rev(last)), [e] - | true, (s::stack_first, stack_last) -> stack_first @ List.rev stack_last, [e] + let new_stack = Queue2L.push e stack in (* pushes new element to stack*) + (* remove elements from stack, till the depth k is guaranteed*) + Queue2L.del_n_elem (Queue2L.length new_stack - depth) new_stack end module D = Lattice.Fake(CallStack) @@ -43,13 +39,13 @@ struct module G = Lattice.Unit let name () = "callstring_"^ CT.stackTypeName - let startstate v = ([],[]) - let exitstate v = ([],[]) + let startstate v = Queue2L.create () + let exitstate v = Queue2L.create () let enter ctx r f args = - let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack: CallStack.t = CallStack.push ctx.local elem in - if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) + let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack = CallStack.push ctx.local elem in + if not !AnalysisState.postsolving then CT.printStack f args ctx.local new_stack; (* just for debugging purpose*) [ctx.local, new_stack] let combine_env ctx lval fexp f args fc au f_ask = @@ -62,17 +58,16 @@ module Fundec:Callstack_Type = struct let stackTypeName = "fundec" let pushElem f args ctx = Some f - let printStack f expL (listA1, listA2) (listB1, listB2) = + let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listA2); + Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) (List.rev listB2); + Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; printf "\n\n" end + module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" @@ -81,15 +76,12 @@ module Stmt:Callstack_Type = struct | Statement stmt -> Some stmt | _ -> None (* first statement is filtered*) - - let printStack f expL (listA1, listA2) (listB1, listB2) = + let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listA2); + Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) (List.rev listB2); + Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; printf "\n\n" end @@ -97,19 +89,15 @@ end module Location:Callstack_Type = struct include CilType.Location let stackTypeName = "loc" - let pushElem f args ctx = - let q = Queue.create () in - Queue.push 1 q; + let pushElem f args ctx = Some !Tracing.current_loc - let printStack f expL (listA1, listA2) (listB1, listB2) = + let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listA2); + Queue2L.iter (fun x -> Printf.printf "%s;\n " (CilType.Location.show x)) listA; printf "\nList neu: "; - List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB1; - List.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) (List.rev listB2); + Queue2L.iter (fun x -> Printf.printf "%s;\n " (CilType.Location.show x)) listB; printf "\n\n" end diff --git a/src/analyses/callstringAnalysisQueue.ml b/src/analyses/callstringAnalysisQueue.ml deleted file mode 100644 index 45cc3f04ec..0000000000 --- a/src/analyses/callstringAnalysisQueue.ml +++ /dev/null @@ -1,118 +0,0 @@ -open Analyses -open Printf -open GoblintCil -open GobConfig - -(* Specifies the type of the callstack elements for the CallstringLifter*) -module type Callstack_Type = -sig - include CilType.S - val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t Queue.t -> t Queue.t -> unit (* a helper function to print the callstack *) -end - -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context - With the CT argument it is possible to specify the type of the Callstack elements -*) -module Spec (CT:Callstack_Type) : MCPSpec = -struct - include Analyses.IdentitySpec - - (* simulates a call stack of depth k*) - module CallStack = struct - include Printable.Queue (CT) - let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) - - let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) - match elem with - | None -> stack - | Some e -> - Queue.push e stack; (* pushes new element to stack*) - (* remove elements from stack, till the depth k is guaranteed*) - let excess_length = max 0 (Queue.length stack - depth) in - for _ = 1 to excess_length do - ignore (Queue.pop stack) - done; - stack - end - - module D = Lattice.Fake(CallStack) - module C = CallStack - module V = EmptyV - module G = Lattice.Unit - module Q = Printable.Queue (Printable.Strings) - - let name () = "callstring_"^ CT.stackTypeName - let startstate v = Queue.create () - let exitstate v = Queue.create () - - let enter ctx r f args = - let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let old_stack: CallStack.t = Queue.copy ctx.local in - let new_stack: CallStack.t = CallStack.push old_stack elem in - if not !AnalysisState.postsolving then CT.printStack f args (ctx.local) new_stack; (* just for debugging purpose*) - [ctx.local, new_stack] - - let combine_env ctx lval fexp f args fc au f_ask = - ctx.local -end - - -module Fundec:Callstack_Type = struct - include CilType.Fundec - let stackTypeName = "fundec" - let pushElem f args ctx = Some f - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; - printf "\nList neu: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; - printf "\n\n" -end - -module Stmt:Callstack_Type = struct - include CilType.Stmt - let stackTypeName = "stmt" - let pushElem f args ctx = - match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) - | Statement stmt -> Some stmt - | _ -> None (* first statement is filtered*) - - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; - printf "\nList neu: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; - printf "\n\n" -end - - -module Location:Callstack_Type = struct - include CilType.Location - let stackTypeName = "loc" - let pushElem f args ctx = - let q = Queue.create () in - Queue.push 1 q; - Some !Tracing.current_loc - - let printStack f expL listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listA; - printf "\nList neu: "; - Queue.iter (fun x -> Printf.printf "%s; " (CilType.Location.show x)) listB; - printf "\n\n" -end - -(* Lifters for the Callstring approach with different Callstack element types*) -let _ = - MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) - MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) - MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) - - diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index f9e914b4a1..fd8c51a67a 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -76,8 +76,8 @@ struct List.map f in let xs = get_string_list "ana.activated" in - let callstring_enabled = (mem "callstring_fundec" xs) || (mem "callstring_stmt" xs) in - let cont_callstring = filter (fun x -> x <> "callstring_fundec" && x <> "callstring_stmt") xs in (*the contexts that are insensitive due to the callstring approach*) + let callstring_enabled = (mem "callstring_fundec" xs) || (mem "callstring_stmt" xs) ||(mem "callstring_loc" xs) in + let cont_callstring = filter (fun x -> x <> "callstring_fundec" && x <> "callstring_stmt" && x <> "callstring_loc") xs in (*the contexts that are insensitive due to the callstring approach*) let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index c3c74d88b9..0add0245b0 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -506,58 +506,34 @@ module Prod4 (Base1: S) (Base2: S) (Base3: S) (Base4: S) = struct let arbitrary () = QCheck.quad (Base1.arbitrary ()) (Base2.arbitrary ()) (Base3.arbitrary ()) (Base4.arbitrary ()) end -module Queue (Base: S) = +module PQueue (Base: S) = struct - type t = Base.t Queue.t + type t = Base.t Queue2L.t [@@deriving eq, ord] include Std - let queue_map f q = - let mapped_queue = Queue.create () in - Queue.iter (fun x -> Queue.push (f x) mapped_queue) q; - mapped_queue - let show x = - let elem = Queue.fold (fun acc elem -> Base.show elem :: acc) [] x |> List.rev in - "[" ^ (String.concat ", " elem) ^ "]" + let elem = Queue2L.map_to_list Base.show x in + "[" ^ (String.concat ", " elem) ^ "]" (* TODO more efficient impl*) let pretty () x = text (show x) let name () = Base.name () ^ "queue" - (* TODO more efficient impl*) - let relift x = queue_map Base.relift x + let relift x =Queue2L.map Base.relift x let printXml f xs = - let xs_copy = Queue.copy xs in let rec loop n q = - if Queue.is_empty q then () - else - let x = Queue.pop q in - BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; - loop (n+1) (xs_copy) + let (x, xs) = Queue2L.dequeue_tup_opt q in + match x with + | None -> () + | Some x -> (BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; + loop (n+1) (xs)) in BatPrintf.fprintf f "\n\n"; - loop 0 xs_copy; + loop 0 xs; BatPrintf.fprintf f "\n\n" - let rec equal_helper a b = - if Queue.is_empty a then true - else ( - let a_v = Queue.pop a in - let b_v = Queue.pop b in - if Base.equal a_v b_v - then equal_helper a b - else false) - - let equal a b = - if Queue.length a <> Queue.length b then false - else - let a_copy = Queue.copy a in - let b_copy = Queue.copy b in - equal_helper a_copy b_copy - let to_yojson x = `String (show x) - let hash = Hashtbl.hash - let compare = Stdlib.compare + let hash q = Hashtbl.hash(Queue2L.list_of_queue q) (*TODO*) end module Liszt (Base: S) = diff --git a/src/common/util/queue2L.ml b/src/common/util/queue2L.ml new file mode 100644 index 0000000000..6979800596 --- /dev/null +++ b/src/common/util/queue2L.ml @@ -0,0 +1,111 @@ +(* A Queue (FIFO) implementation, using two Lists for efficient push and pop handling*) +(** + Queue: remove here, 1, 2, 3, 4, add here + is stored in two lists: [1,2]*[4,3] +*) + +exception Empty + +type 'a t = Queue of 'a list * 'a list + +let create () = Queue ([], []) +let length (Queue (q_first, q_last)) = List.length q_first + List.length q_last +let is_empty = function + | Queue ([], []) -> true + | _ -> false + +let clear (Queue (q_first, q_last)) = Queue ([], []) + +let list_of_queue = function + | Queue (q_first, []) -> q_first + | Queue (q_first, q_last) -> q_first @ List.rev q_last + +let queue_of_list list = Queue (list,[]) + +let equal eq q1 q2 = + if length q1 <> length q2 then false + else List.equal eq (list_of_queue q1) (list_of_queue q2) + +let compare cmp q1 q2 = + List.compare cmp (list_of_queue q1) (list_of_queue q2) + +let add ele (Queue (q_first, q_last)) = Queue (q_first, ele :: q_last) +let push = add +let enqueue = add + +let peek = function (* returns the removed element*) + | Queue ([], q_last) -> ( + match List.rev q_last with + | [] -> raise Empty + | x::xs -> x) + | Queue (x::q_first, q_last) -> x + +let peek_opt = function (* returns the removed element as option*) + | Queue ([], q_last) -> ( + match List.rev q_last with + | [] -> None + | x::xs -> Some x) + | Queue (x::q_first, q_last) -> Some x + +let dequeue = function (* returns the remaining queue after removing one element*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> Queue ([], []) + | x::xs -> Queue(xs, [])) + | Queue (x::q_first, q_last) -> Queue (q_first, q_last) + +let dequeue_tup = function (* returns the removed element and the remaining queue*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> raise Empty + | x::xs -> (x , Queue(xs, []))) + | Queue (x::q_first, q_last) -> (x, Queue (q_first, q_last)) + +let dequeue_tup_opt = function (* returns the removed element and the remaining queue*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> (None, Queue ([], [])) + | x::xs -> (Some x , Queue(xs, []))) + | Queue (x::q_first, q_last) -> (Some x, Queue (q_first, q_last)) + +let del_n_elem n (Queue (q_first, q_last)) = + let rec del n (Queue (q_first, q_last)) = + if n = 0 then (Queue (q_first, q_last)) + else + match q_first, q_last with + | [], [] -> Queue ([], []) + | [], xs -> del n (Queue (List.rev xs, [])) + | x::xs, ys -> del (n-1) (Queue (xs, ys)) + in + if n <= 0 then (Queue (q_first, q_last)) + else( + if length (Queue (q_first, q_last)) <= n + then Queue ([], []) + else + let l_first = List.length q_first in + if l_first <= n + then del (n-l_first) (Queue (List.rev q_last, [])) + else del n (Queue (q_first, q_last))) + +let iter f (Queue (q_first, q_last)) = + List.iter f q_first; + List.iter f (List.rev q_last) + +let map f (Queue (q_first, q_last)) = + Queue (List.map f q_first, List.map f q_last) + +let map_to_list f (Queue (q_first, q_last)) = + List.map f q_first @ List.rev (List.map f q_last) + +let fold_left f accu q = List.fold_left f accu (list_of_queue q) +let fold_right f accu q = List.fold_right f accu (list_of_queue q) + +let assoc x (Queue (q_first, q_last)) = + match List.assoc_opt x q_first, List.assoc_opt x q_last with + | None, None -> raise Not_found + | Some y, _ -> y + | None, Some y -> y + +let mem_assoc x (Queue (q_first, q_last)) = List.mem_assoc x q_first || List.mem_assoc x q_last + + From 3f712b27345b04e6b74702853618817d7b6003d2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 9 Dec 2023 21:09:52 +0100 Subject: [PATCH 067/128] added gobview, changed Tracing to Goblint_tracing, added queue2L to goblint_std --- gobview | 1 + src/analyses/callstringAnalysis.ml | 2 +- src/util/std/goblint_std.ml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 160000 gobview diff --git a/gobview b/gobview new file mode 160000 index 0000000000..1d8302e069 --- /dev/null +++ b/gobview @@ -0,0 +1 @@ +Subproject commit 1d8302e069a999df950dbcff83815ee9ae1f6a07 diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 740bf577fb..b6be8523ee 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -90,7 +90,7 @@ module Location:Callstack_Type = struct include CilType.Location let stackTypeName = "loc" let pushElem f args ctx = - Some !Tracing.current_loc + Some !Goblint_tracing.current_loc let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); diff --git a/src/util/std/goblint_std.ml b/src/util/std/goblint_std.ml index 0d548cac08..f6d97f2bc2 100644 --- a/src/util/std/goblint_std.ml +++ b/src/util/std/goblint_std.ml @@ -23,3 +23,4 @@ module GobQCheck = GobQCheck module GobYaml = GobYaml module GobYojson = GobYojson module GobZ = GobZ +module Queue2L = Queue2L From 62a87a2de8eb3fd36afc8e0511d72c87f81ecd60 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 9 Dec 2023 23:22:14 +0100 Subject: [PATCH 068/128] deleted unnecessary sv comp secification --- conf/svcomp83-callstringLoc.json | 99 -------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 conf/svcomp83-callstringLoc.json diff --git a/conf/svcomp83-callstringLoc.json b/conf/svcomp83-callstringLoc.json deleted file mode 100644 index d13afb3a13..0000000000 --- a/conf/svcomp83-callstringLoc.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "callstring_loc" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "ctx_gas": false, - "callStack_height": 10 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate" - } - } -} \ No newline at end of file From e15046362b2a2d86d33b0b919386a2dffc6865b6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 10 Dec 2023 09:15:37 +0100 Subject: [PATCH 069/128] removed print statements for sv comp run --- src/analyses/callstringAnalysis.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index b6be8523ee..11f56600e7 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -45,7 +45,7 @@ struct let enter ctx r f args = let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) let new_stack = CallStack.push ctx.local elem in - if not !AnalysisState.postsolving then CT.printStack f args ctx.local new_stack; (* just for debugging purpose*) + (*if not !AnalysisState.postsolving then CT.printStack f args ctx.local new_stack; *)(* just for debugging purpose*) [ctx.local, new_stack] let combine_env ctx lval fexp f args fc au f_ask = @@ -61,9 +61,9 @@ module Fundec:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listA; + Queue2L.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Fundec.show x)) listB; + Queue2L.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listB; printf "\n\n" end @@ -79,9 +79,9 @@ module Stmt:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listA; + Queue2L.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> Printf.printf "%s; " (CilType.Stmt.show x)) listB; + Queue2L.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listB; printf "\n\n" end @@ -95,9 +95,9 @@ module Location:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> Printf.printf "%s;\n " (CilType.Location.show x)) listA; + Queue2L.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> Printf.printf "%s;\n " (CilType.Location.show x)) listB; + Queue2L.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listB; printf "\n\n" end From 72c68c4d1259918f636ce94fd1b023c3d71e1e72 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 20 Dec 2023 11:24:43 +0100 Subject: [PATCH 070/128] renamed Queue2L -> QueueImmut; made mcp implementation more efficient; implemented own hash for PQueue; used Flat lattice for callstring --- src/analyses/callstringAnalysis.ml | 48 +++++---- src/analyses/mCP.ml | 17 ++-- src/common/domains/printable.ml | 14 +-- src/common/util/queue2L.ml | 111 -------------------- src/common/util/queueImmut.ml | 158 +++++++++++++++++++++++++++++ src/framework/constraints.ml | 3 +- src/util/std/goblint_std.ml | 2 +- 7 files changed, 207 insertions(+), 146 deletions(-) delete mode 100644 src/common/util/queue2L.ml create mode 100644 src/common/util/queueImmut.ml diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 11f56600e7..32340ea2db 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -8,8 +8,8 @@ module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) (*pushElem could be currently also a single element*) - val printStack: fundec -> exp list -> t Queue2L.t -> t Queue2L.t -> unit (* a helper function to print the callstack *) + val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) + val printStack: fundec -> exp list -> t QueueImmut.t -> t QueueImmut.t -> unit (* a helper function to print the callstack *) end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context @@ -28,25 +28,39 @@ struct match elem with | None -> stack | Some e -> - let new_stack = Queue2L.push e stack in (* pushes new element to stack*) + let new_stack = QueueImmut.push e stack in (* pushes new element to stack*) (* remove elements from stack, till the depth k is guaranteed*) - Queue2L.del_n_elem (Queue2L.length new_stack - depth) new_stack + match (QueueImmut.length new_stack - depth) with + | x when x <= 0 -> new_stack + | 1 -> QueueImmut.dequeue new_stack + | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" + end - module D = Lattice.Fake(CallStack) + module D = Lattice.Flat (CallStack) (Printable.DefaultNames) module C = CallStack module V = EmptyV module G = Lattice.Unit let name () = "callstring_"^ CT.stackTypeName - let startstate v = Queue2L.create () - let exitstate v = Queue2L.create () + let startstate v = `Lifted (QueueImmut.create ()) + let exitstate v = `Lifted (QueueImmut.create ()) + + (*let threadenter ctx ~multiple lval f args = + let elem: CT.t option = CT.pushElemVar f args ctx in + let new_stack: C.t = CallStack.push ctx.local elem in + CT.printStackVar f args ctx.local new_stack; (* just for debugging purpose*) + [new_stack]*) + + let context fd x = match x with + | `Lifted x -> x + | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO*) let enter ctx r f args = - let elem = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack = CallStack.push ctx.local elem in - (*if not !AnalysisState.postsolving then CT.printStack f args ctx.local new_stack; *)(* just for debugging purpose*) - [ctx.local, new_stack] + let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack: C.t = CallStack.push (context f ctx.local) elem in + (*CT.printStack f args ctx.local new_stack; *)(* just for debugging purpose*) + [ctx.local, `Lifted new_stack] let combine_env ctx lval fexp f args fc au f_ask = ctx.local @@ -61,9 +75,9 @@ module Fundec:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listA; + QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listB; + QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listB; printf "\n\n" end @@ -79,9 +93,9 @@ module Stmt:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listA; + QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listB; + QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listB; printf "\n\n" end @@ -95,9 +109,9 @@ module Location:Callstack_Type = struct let printStack f expL listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; - Queue2L.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listA; + QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listA; printf "\nList neu: "; - Queue2L.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listB; + QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listB; printf "\n\n" end diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index fd8c51a67a..862e004878 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -76,8 +76,9 @@ struct List.map f in let xs = get_string_list "ana.activated" in - let callstring_enabled = (mem "callstring_fundec" xs) || (mem "callstring_stmt" xs) ||(mem "callstring_loc" xs) in - let cont_callstring = filter (fun x -> x <> "callstring_fundec" && x <> "callstring_stmt" && x <> "callstring_loc") xs in (*the contexts that are insensitive due to the callstring approach*) + let callstring_list = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"] in + let callstring_enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false callstring_list in + let cont_callstring = filter (fun x -> not (mem x callstring_list)) xs in (*the contexts that are insensitive due to the callstring approach*) let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; @@ -109,7 +110,7 @@ struct let ys = fold_left one_el [] xs in List.rev ys, !dead - let context fd x = + let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> if mem n !cont_inse then @@ -184,13 +185,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index 0add0245b0..246dc21507 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -508,21 +508,21 @@ end module PQueue (Base: S) = struct - type t = Base.t Queue2L.t [@@deriving eq, ord] + type t = Base.t QueueImmut.t [@@deriving eq, ord] include Std let show x = - let elem = Queue2L.map_to_list Base.show x in - "[" ^ (String.concat ", " elem) ^ "]" (* TODO more efficient impl*) + let elem = QueueImmut.map_to_list Base.show x in + "[" ^ (String.concat ", " elem) ^ "]" let pretty () x = text (show x) let name () = Base.name () ^ "queue" - let relift x =Queue2L.map Base.relift x + let relift x = QueueImmut.map Base.relift x let printXml f xs = let rec loop n q = - let (x, xs) = Queue2L.dequeue_tup_opt q in + let (x, xs) = QueueImmut.dequeue_tup_opt q in match x with | None -> () | Some x -> (BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; @@ -532,8 +532,8 @@ struct loop 0 xs; BatPrintf.fprintf f "\n\n" - let to_yojson x = `String (show x) - let hash q = Hashtbl.hash(Queue2L.list_of_queue q) (*TODO*) + let to_yojson q = `List (QueueImmut.map_to_list (Base.to_yojson) q) + let hash (q: Base.t QueueImmut.t) = QueueImmut.fold_left (fun acc x -> (acc + 71) * (Base.hash x)) 11 q end module Liszt (Base: S) = diff --git a/src/common/util/queue2L.ml b/src/common/util/queue2L.ml deleted file mode 100644 index 6979800596..0000000000 --- a/src/common/util/queue2L.ml +++ /dev/null @@ -1,111 +0,0 @@ -(* A Queue (FIFO) implementation, using two Lists for efficient push and pop handling*) -(** - Queue: remove here, 1, 2, 3, 4, add here - is stored in two lists: [1,2]*[4,3] -*) - -exception Empty - -type 'a t = Queue of 'a list * 'a list - -let create () = Queue ([], []) -let length (Queue (q_first, q_last)) = List.length q_first + List.length q_last -let is_empty = function - | Queue ([], []) -> true - | _ -> false - -let clear (Queue (q_first, q_last)) = Queue ([], []) - -let list_of_queue = function - | Queue (q_first, []) -> q_first - | Queue (q_first, q_last) -> q_first @ List.rev q_last - -let queue_of_list list = Queue (list,[]) - -let equal eq q1 q2 = - if length q1 <> length q2 then false - else List.equal eq (list_of_queue q1) (list_of_queue q2) - -let compare cmp q1 q2 = - List.compare cmp (list_of_queue q1) (list_of_queue q2) - -let add ele (Queue (q_first, q_last)) = Queue (q_first, ele :: q_last) -let push = add -let enqueue = add - -let peek = function (* returns the removed element*) - | Queue ([], q_last) -> ( - match List.rev q_last with - | [] -> raise Empty - | x::xs -> x) - | Queue (x::q_first, q_last) -> x - -let peek_opt = function (* returns the removed element as option*) - | Queue ([], q_last) -> ( - match List.rev q_last with - | [] -> None - | x::xs -> Some x) - | Queue (x::q_first, q_last) -> Some x - -let dequeue = function (* returns the remaining queue after removing one element*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> Queue ([], []) - | x::xs -> Queue(xs, [])) - | Queue (x::q_first, q_last) -> Queue (q_first, q_last) - -let dequeue_tup = function (* returns the removed element and the remaining queue*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> raise Empty - | x::xs -> (x , Queue(xs, []))) - | Queue (x::q_first, q_last) -> (x, Queue (q_first, q_last)) - -let dequeue_tup_opt = function (* returns the removed element and the remaining queue*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> (None, Queue ([], [])) - | x::xs -> (Some x , Queue(xs, []))) - | Queue (x::q_first, q_last) -> (Some x, Queue (q_first, q_last)) - -let del_n_elem n (Queue (q_first, q_last)) = - let rec del n (Queue (q_first, q_last)) = - if n = 0 then (Queue (q_first, q_last)) - else - match q_first, q_last with - | [], [] -> Queue ([], []) - | [], xs -> del n (Queue (List.rev xs, [])) - | x::xs, ys -> del (n-1) (Queue (xs, ys)) - in - if n <= 0 then (Queue (q_first, q_last)) - else( - if length (Queue (q_first, q_last)) <= n - then Queue ([], []) - else - let l_first = List.length q_first in - if l_first <= n - then del (n-l_first) (Queue (List.rev q_last, [])) - else del n (Queue (q_first, q_last))) - -let iter f (Queue (q_first, q_last)) = - List.iter f q_first; - List.iter f (List.rev q_last) - -let map f (Queue (q_first, q_last)) = - Queue (List.map f q_first, List.map f q_last) - -let map_to_list f (Queue (q_first, q_last)) = - List.map f q_first @ List.rev (List.map f q_last) - -let fold_left f accu q = List.fold_left f accu (list_of_queue q) -let fold_right f accu q = List.fold_right f accu (list_of_queue q) - -let assoc x (Queue (q_first, q_last)) = - match List.assoc_opt x q_first, List.assoc_opt x q_last with - | None, None -> raise Not_found - | Some y, _ -> y - | None, Some y -> y - -let mem_assoc x (Queue (q_first, q_last)) = List.mem_assoc x q_first || List.mem_assoc x q_last - - diff --git a/src/common/util/queueImmut.ml b/src/common/util/queueImmut.ml new file mode 100644 index 0000000000..d454e9b2ca --- /dev/null +++ b/src/common/util/queueImmut.ml @@ -0,0 +1,158 @@ +(* A Queue (FIFO, imutable) implementation, using two Lists for efficient push and pop handling. + + Example Queue: remove here, 1, 2, 3, 4, add here + Representation as Queue: Queue([1,2], [4,3]) or Queue([1], [4,3,2]) or Queue([1,2,3,4], []) or ... +*) + +exception Empty + +type 'a t = Queue of 'a list * 'a list + +(** Return a new queue, initially empty. *) +let create () = Queue ([], []) +let length (Queue (q_first, q_last)) = List.length q_first + List.length q_last + +(** Return [true] if the given queue is empty, [false] otherwise. *) +let is_empty = function + | Queue ([], []) -> true + | _ -> false + +(** Discard all elements from a queue. *) +let clear (Queue (q_first, q_last)) = Queue ([], []) + +(** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_first]*) +let get_first_list (Queue (q_first, q_last)) = q_first + +(** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_last]*) +let get_last_list (Queue (q_first, q_last)) = q_last + +(** Converts a queue into a list. *) +let list_of_queue = function + | Queue (q_first, []) -> q_first + | Queue (q_first, q_last) -> q_first @ List.rev q_last + +(** Converts a list into a queue. *) +let queue_of_list list = Queue (list,[]) + +let equal eq q1 q2 = List.equal eq (list_of_queue q1) (list_of_queue q2) + +let compare cmp q1 q2 = List.compare cmp (list_of_queue q1) (list_of_queue q2) + +(** [add x q] adds the element [x] at the end of the queue [q] and returns the resulting queue*) +let add ele (Queue (q_first, q_last)) = Queue (q_first, ele :: q_last) +(** [push] is a synonym for [add]. *) +let push = add + +(** [enqueue] is a synonym for [add]. *) +let enqueue = add + +(** [peek q] returns the first element in queue [q], or raises {!Empty} if the queue is empty. *) +let peek = function (* returns the removed element*) + | Queue ([], q_last) -> ( + match List.rev q_last with + | [] -> raise Empty + | x::xs -> x) + | Queue (x::q_first, q_last) -> x + +(** [peek_opt q] returns the first element in queue [q] as option, or returns [None] if the queue is empty.*) +let peek_opt = function (* returns the removed element as option*) + | Queue ([], q_last) -> ( + match List.rev q_last with + | [] -> None + | x::xs -> Some x) + | Queue (x::q_first, q_last) -> Some x + +(** [dequeue q] removes the first element in queue [q] + and returns the remaining queue.*) +let dequeue = function (* returns the remaining queue after removing one element*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> Queue ([], []) + | x::xs -> Queue(xs, [])) + | Queue (x::q_first, q_last) -> Queue (q_first, q_last) + +(** [dequeue_tup q] removes the first element in queue [q] + and returns it with the remaining queue in a tuple. + In case of an empty queue it raises {!Empty}.*) +let dequeue_tup = function (* returns the removed element and the remaining queue*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> raise Empty + | x::xs -> (x , Queue(xs, []))) + | Queue (x::q_first, q_last) -> (x, Queue (q_first, q_last)) + +(** [dequeue_tup q] removes the first element in queue [q] + and returns it with the remaining queue in a tuple. + In case of an empty queue the first element is [None]*) +let dequeue_tup_opt = function (* returns the removed element and the remaining queue*) + | Queue ([], q_last) -> ( + match List.rev q_last with (*List.rev q_last is moved to the first list*) + | [] -> (None, Queue ([], [])) + | x::xs -> (Some x , Queue(xs, []))) + | Queue (x::q_first, q_last) -> (Some x, Queue (q_first, q_last)) + +(** [del_n_elem n q] deletes the first n elements of the queue*) +let del_n_elem n (Queue (q_first, q_last)) = + let rec del n (Queue (q_first, q_last)) = + if n = 0 then (Queue (q_first, q_last)) + else + match q_first, q_last with + | [], [] -> Queue ([], []) + | [], xs -> del n (Queue (List.rev xs, [])) + | x::xs, ys -> del (n-1) (Queue (xs, ys)) + in + if n <= 0 then (Queue (q_first, q_last)) (* check if command is used correctly *) + else( + if length (Queue (q_first, q_last)) <= n (* check if everything is deleted *) + then Queue ([], []) + else + let l_first = List.length q_first in + if l_first <= n (* check if the whole first list is deleted *) + then del (n-l_first) (Queue (List.rev q_last, [])) + else del n (Queue (q_first, q_last))) + +(** [iter f q] applies [f] in turn to all elements of [q], + from the least recently entered to the most recently entered.*) +let iter f (Queue (q_first, q_last)) = + List.iter f q_first; + List.iter f (List.rev q_last) + +(** [map f [a1; ...; an]] applies function [f] to [a1, ..., an], + and builds the queue [[f a1; ...; f an]] + with the results returned by [f]. Not tail-recursive.*) +let map f (Queue (q_first, q_last)) = + Queue (List.map f q_first, List.map f q_last) + +(** [map_to_list f q] is equivalent to [map f l], but returns a list instead of a queue*) +let map_to_list f (Queue (q_first, q_last)) = + List.map f q_first @ List.rev (List.map f q_last) + +(** [fold_left f accu [b1; ...; bn]] is + [f (... (f (f accu b1) b2) ...) bn].*) +let fold_left f accu (Queue (q_first, q_last)) = + let res = List.fold_left f accu q_first in + List.fold_left f res (List.rev q_last) + + +(** [fold_right f [a1; ...; an] accu] is + [f a1 (f a2 (... (f an accu) ...))]. Not tail-recursive.*) +let fold_right f (Queue (q_first, q_last)) accu = + List.fold_right f (List.rev q_last) accu |> List.fold_right f q_first + +(** [assoc a q] returns the value associated with key [a] in the queue of + pairs [q]. That is, + [assoc a { ...; (a,b); ...}= b] + if [(a,b)] is the leftmost binding of [a] in queue [q]. + @raise Not_found if there is no value associated with [a] in the + queue [q].*) +let assoc x (Queue (q_first, q_last)) = + match List.assoc_opt x q_first, List.assoc_opt x q_last with + | None, None -> raise Not_found + | Some y, _ -> y + | None, Some y -> y + +(** Same as {!assoc}, but simply return [true] if a binding exists, + and [false] if no bindings exist for the given key.*) +let mem_assoc x (Queue (q_first, q_last)) = List.mem_assoc x q_first || List.mem_assoc x q_last + + diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 182f04a5dc..39e8c9ccbf 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -6,7 +6,6 @@ open GoblintCil open MyCFG open Analyses open GobConfig -include Printf module M = Messages @@ -566,7 +565,7 @@ struct let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) + (*if not !AnalysisState.postsolving then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) diff --git a/src/util/std/goblint_std.ml b/src/util/std/goblint_std.ml index f6d97f2bc2..da13343468 100644 --- a/src/util/std/goblint_std.ml +++ b/src/util/std/goblint_std.ml @@ -23,4 +23,4 @@ module GobQCheck = GobQCheck module GobYaml = GobYaml module GobYojson = GobYojson module GobZ = GobZ -module Queue2L = Queue2L +module QueueImmut = QueueImmut From b96a8cce31b5b1ec44d069fdeee9696bbc870a77 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 2 Jan 2024 19:59:36 +0100 Subject: [PATCH 071/128] renamed CFName to NoContext, used stored context gas value for IntConf, added 2 test cases, more efficient implementation for QueueImmut --- .devcontainer/devcontainer.json | 9 ++-- src/common/util/queueImmut.ml | 30 +++++++++--- src/framework/constraints.ml | 16 +++---- .../81-context_gas_insens/12-circle_up_down.c | 48 +++++++++++++++++++ .../13-mutualRecursion.c | 33 +++++++++++++ 5 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 tests/regression/81-context_gas_insens/12-circle_up_down.c create mode 100644 tests/regression/81-context_gas_insens/13-mutualRecursion.c diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index af25a29e3f..5d0336ccf9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,10 +13,11 @@ "runArgs": ["--init", "--env-file", ".devcontainer/devcontainer.env"], // TODO: why --init added by default? "extensions": [ - "ocamllabs.ocaml-platform", - "hackwaly.ocamlearlybird", - "zepalmer.ocaml-indentation" - ], + "ocamllabs.ocaml-platform", + "hackwaly.ocamlearlybird", + "zepalmer.ocaml-indentation", + "AllanBlanchard.ocp-indent" + ], "settings": {}, } diff --git a/src/common/util/queueImmut.ml b/src/common/util/queueImmut.ml index d454e9b2ca..d1c6fe288d 100644 --- a/src/common/util/queueImmut.ml +++ b/src/common/util/queueImmut.ml @@ -21,10 +21,10 @@ let is_empty = function let clear (Queue (q_first, q_last)) = Queue ([], []) (** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_first]*) -let get_first_list (Queue (q_first, q_last)) = q_first +let get_first_list (Queue (q_first, q_last)) = q_first (** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_last]*) -let get_last_list (Queue (q_first, q_last)) = q_last +let get_last_list (Queue (q_first, q_last)) = q_last (** Converts a queue into a list. *) let list_of_queue = function @@ -34,9 +34,26 @@ let list_of_queue = function (** Converts a list into a queue. *) let queue_of_list list = Queue (list,[]) -let equal eq q1 q2 = List.equal eq (list_of_queue q1) (list_of_queue q2) - -let compare cmp q1 q2 = List.compare cmp (list_of_queue q1) (list_of_queue q2) +let rec equal eq q1 q2 = + match q1, q2 with + | Queue ([], []), Queue ([], []) -> true + | Queue ([], []), Queue ([], x) | Queue ([], []), Queue (x, []) + | Queue (x, []), Queue ([], []) | Queue ([], x), Queue ([], []) -> false + | Queue ([], q1_last), Queue (q2_first, q2_last) -> equal eq (Queue (List.rev q1_last, [])) (Queue (q2_first, q2_last)) + | Queue (q1_first, q1_last), Queue ([], q2_last) -> equal eq (Queue (q1_first, q1_last)) (Queue (List.rev q2_last, [])) + | Queue (x1::q1_first, q1_last), Queue (x2::q2_first, q2_last) -> eq x1 x2 && equal eq (Queue (q1_first, q1_last)) (Queue (q2_first, q2_last)) + +let rec compare cmp q1 q2 = + match q1, q2 with + | Queue ([], []), Queue ([], []) -> 0 + | Queue ([], []), Queue ([], x) | Queue ([], []), Queue (x, []) -> -1 + | Queue (x, []), Queue ([], []) | Queue ([], x), Queue ([], []) -> 1 + | Queue ([], q1_last), Queue (q2_first, q2_last) -> compare cmp (Queue (List.rev q1_last, [])) (Queue (q2_first, q2_last)) + | Queue (q1_first, q1_last), Queue ([], q2_last) -> compare cmp (Queue (q1_first, q1_last)) (Queue (List.rev q2_last, [])) + | Queue (x1::q1_first, q1_last), Queue (x2::q2_first, q2_last) -> + let c = cmp x1 x2 in + if c <> 0 then c + else compare cmp (Queue (q1_first, q1_last)) (Queue (q2_first, q2_last)) (** [add x q] adds the element [x] at the end of the queue [q] and returns the resulting queue*) let add ele (Queue (q_first, q_last)) = Queue (q_first, ele :: q_last) @@ -125,7 +142,7 @@ let map f (Queue (q_first, q_last)) = (** [map_to_list f q] is equivalent to [map f l], but returns a list instead of a queue*) let map_to_list f (Queue (q_first, q_last)) = - List.map f q_first @ List.rev (List.map f q_last) + List.map f q_first @ List.rev_map f q_last (** [fold_left f accu [b1; ...; bn]] is [f (... (f (f accu b1) b2) ...) bn].*) @@ -133,7 +150,6 @@ let fold_left f accu (Queue (q_first, q_last)) = let res = List.fold_left f accu q_first in List.fold_left f res (List.rev q_last) - (** [fold_right f [a1; ...; an] accu] is [f a1 (f a2 (... (f an accu) ...))]. Not tail-recursive.*) let fold_right f (Queue (q_first, q_last)) accu = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 39e8c9ccbf..862a8df773 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -496,10 +496,10 @@ struct let event (ctx:(D.t,G.t,C.t,V.t) ctx) (e:Events.t) (octx:(D.t,G.t,C.t,V.t) ctx):D.t = lift_fun ctx D.lift S.event ((|>) (conv octx) % (|>) e) `Bot end -module CGName = struct let name = "contextGas" end +module NoContext = struct let name = "no context" end module IntConf = struct - let n () = max_int (* TODO: Shouldn't matter if this value is bigger than cg_init_val*) + let n () = get_int "ana.context.ctx_gas_value" + 1 let names x = Format.asprintf "%d" x end @@ -507,7 +507,7 @@ end If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) - and module C = Printable.Prod (Printable.Option (S.C) (CGName)) (Printable.Chain (IntConf)) + and module C = Printable.Prod (Printable.Option (S.C) (NoContext)) (Printable.Chain (IntConf)) and module G = S.G = struct @@ -521,8 +521,8 @@ struct end module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) + module C = Context_Gas_Prod (Printable.Option (S.C) (NoContext)) (Printable.Chain (IntConf)) module G = S.G - module C = Context_Gas_Prod (Printable.Option (S.C) (CGName)) (Lattice.Chain (IntConf)) module V = S.V module P = struct @@ -536,7 +536,7 @@ struct let name () = S.name ()^" with context gas" let startstate v = S.startstate v, (get_int "ana.context.ctx_gas_value") - let exitstate v = S.exitstate v, 0 (* TODO: probably doesn't matter*) + let exitstate v = S.exitstate v, (get_int "ana.context.ctx_gas_value") (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = @@ -558,14 +558,14 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - (*let rec showExprList args = (*TODO: delete, just here for printing*) + let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) + if not !AnalysisState.postsolving then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in liftmap_tup (S.enter (conv ctx_dec) r f args) diff --git a/tests/regression/81-context_gas_insens/12-circle_up_down.c b/tests/regression/81-context_gas_insens/12-circle_up_down.c new file mode 100644 index 0000000000..8707290fe2 --- /dev/null +++ b/tests/regression/81-context_gas_insens/12-circle_up_down.c @@ -0,0 +1,48 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// Checks proper handling of recursions in loops +#include + +int num_iterat = 20; + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(i + 1); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(i - 2) + g(i - 3); + } + return res; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + for (int i = 2; i > 0; i--) + { + res1 = f(num_iterat); + res2 = g(num_iterat); + __goblint_check(res1 == 6765); // UNKNOWN + __goblint_check(res2 == 10946); // UNKNOWN + } +} diff --git a/tests/regression/81-context_gas_insens/13-mutualRecursion.c b/tests/regression/81-context_gas_insens/13-mutualRecursion.c new file mode 100644 index 0000000000..a5d8f3a9f3 --- /dev/null +++ b/tests/regression/81-context_gas_insens/13-mutualRecursion.c @@ -0,0 +1,33 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.sv-comp.functions --enable ana.float.interval --enable ana.int.interval --enable ana.autotune.enabled --set ana.base.arrays.domain partitioned --set ana.activated[+] expRelation +/* + * Date: 07/07/2015 + * Created by: Ton Chanh Le (chanhle@comp.nus.edu.sg) + */ + +extern int __VERIFIER_nondet_int(); + +int f(int x); +int g(int x); + +int f(int x) +{ + if (x <= 0) + return 0; + else + return g(x) + g(x + 1); +} + +int g(int x) +{ + if (x <= 0) + return 0; + else + return f(x - 1) + f(x - 2); +} + +int main() +{ + int x = __VERIFIER_nondet_int(); + int res = g(x); + __goblint_check(res == 0); // UNKNOWN +} \ No newline at end of file From 161d2ffa19ae04797703da624e546c81c0af5a9e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 4 Jan 2024 22:47:59 +0100 Subject: [PATCH 072/128] disabled options in autotune which may caused failing sv-comps (big problems with apron) --- src/autoTune.ml | 6 +++--- src/framework/constraints.ml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 3cda36a302..36567ce700 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -242,7 +242,7 @@ let focusOnMemSafetySpecification () = let focusOnTermination (spec: Svcomp.Specification.t) = match spec with | Termination -> - let terminationAnas = ["termination"; "threadflag"; "apron"] in + let terminationAnas = ["termination"; "threadflag"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; set_string "sem.int.signed_overflow" "assume_none"; @@ -446,9 +446,9 @@ let apronOctagonOption factors file = let cost = (Batteries.Int.pow (locals + globals) 3) * (factors.instructions / 70) in let activateVars () = print_endline @@ "Octagon: " ^ string_of_int cost; - set_bool "annotation.goblint_relation_track" true; + (*set_bool "annotation.goblint_relation_track" true;*) set_string "ana.apron.domain" "octagon"; - set_auto "ana.activated[+]" "apron"; + (*set_auto "ana.activated[+]" "apron";*) set_bool "ana.apron.threshold_widening" true; set_string "ana.apron.threshold_widening_constants" "comparisons"; print_endline "Enabled octagon domain for:"; diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 10a13cc1da..0683f77e8f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -565,10 +565,10 @@ struct | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) let enter ctx r f args = - let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + let ctx_dec = dec_context_gas ctx in + if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in - liftmap_tup (S.enter (conv ctx_dec) r f args) + liftmap_tup (S.enter (conv ctx_dec) r f args) (* TODO: hier ctx oder ctx_dec???*) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f From 3c4ff7d0b9a889c7719db2b2561ece69abf06238 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 5 Jan 2024 12:02:58 +0100 Subject: [PATCH 073/128] updated gobview with master, correct condition for test --- gobview | 2 +- tests/regression/81-context_gas_insens/13-mutualRecursion.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gobview b/gobview index 1d8302e069..54346ca9f1 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit 1d8302e069a999df950dbcff83815ee9ae1f6a07 +Subproject commit 54346ca9f15186e0b190c47f9f41bd5061208300 diff --git a/tests/regression/81-context_gas_insens/13-mutualRecursion.c b/tests/regression/81-context_gas_insens/13-mutualRecursion.c index a5d8f3a9f3..88a955ab8a 100644 --- a/tests/regression/81-context_gas_insens/13-mutualRecursion.c +++ b/tests/regression/81-context_gas_insens/13-mutualRecursion.c @@ -29,5 +29,5 @@ int main() { int x = __VERIFIER_nondet_int(); int res = g(x); - __goblint_check(res == 0); // UNKNOWN + __goblint_check(res == 0); } \ No newline at end of file From 0d73e265dbeebc2e71c3fa14dcaff6ee2106ff9d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 9 Jan 2024 11:38:08 +0100 Subject: [PATCH 074/128] autotune: standard config, callstring: shortend code, added threadenter; constraint: added threadenter; testcases for context gas combined and extended --- src/analyses/callstringAnalysis.ml | 39 +++++---- src/autoTune.ml | 6 +- src/framework/constraints.ml | 14 +-- .../80-context_gas/01-basic_tests.c | 33 +++++++ .../02-multiple_function_chain_tests.c | 74 ++++++++++++++++ .../80-context_gas/03-contextGas0.c | 23 +++++ .../80-context_gas/04-contextGasNeg.c | 23 +++++ .../05-ackermann.c | 2 +- .../80-context_gas/06-circle_call.c | 51 +++++++++++ .../80-context_gas/07-loop_unrolling.c | 64 ++++++++++++++ .../09-main_recursion_insens.c} | 0 .../10-main_recursion_sens.c} | 2 +- .../80-context_gas/11-thread_handling.c | 86 +++++++++++++++++++ .../12-endless_loop.c} | 2 +- .../01-basic_multiple_param_simple.c | 18 ---- .../02-boundary_check_simple_rec.c | 22 ----- .../03-boundary_check_multiple_rec.c | 59 ------------- .../04-hardcoded_recursion.c | 47 ---------- .../80-context_gas_sens/05-function_chain.c | 55 ------------ .../80-context_gas_sens/06-loop_unrolling.c | 34 -------- .../80-context_gas_sens/07-call_in_loop_adv.c | 31 ------- .../08-circle_call_and_loops.c | 49 ----------- .../80-context_gas_sens/10-call_in_call.c | 54 ------------ .../01-multiple_param_simple.c | 18 ---- .../02-boundary_check_simple_rec.c | 22 ----- .../03-boundary_check_multiple_rec.c | 59 ------------- .../81-context_gas_insens/04-function_chain.c | 55 ------------ .../81-context_gas_insens/06-call_in_loop.c | 28 ------ .../07-circle_call_and_loops.c | 48 ----------- .../81-context_gas_insens/08-loop_unrolling.c | 29 ------- .../81-context_gas_insens/10-call_in_call.c | 54 ------------ .../81-context_gas_insens/12-circle_up_down.c | 48 ----------- .../13-mutualRecursion.c | 33 ------- 33 files changed, 392 insertions(+), 790 deletions(-) create mode 100644 tests/regression/80-context_gas/01-basic_tests.c create mode 100644 tests/regression/80-context_gas/02-multiple_function_chain_tests.c create mode 100644 tests/regression/80-context_gas/03-contextGas0.c create mode 100644 tests/regression/80-context_gas/04-contextGasNeg.c rename tests/regression/{81-context_gas_insens => 80-context_gas}/05-ackermann.c (92%) create mode 100644 tests/regression/80-context_gas/06-circle_call.c create mode 100644 tests/regression/80-context_gas/07-loop_unrolling.c rename tests/regression/{81-context_gas_insens/09-main_recursion.c => 80-context_gas/09-main_recursion_insens.c} (100%) rename tests/regression/{80-context_gas_sens/09-main_recursion.c => 80-context_gas/10-main_recursion_sens.c} (94%) create mode 100644 tests/regression/80-context_gas/11-thread_handling.c rename tests/regression/{81-context_gas_insens/11-endless_loop.c => 80-context_gas/12-endless_loop.c} (91%) delete mode 100644 tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c delete mode 100644 tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c delete mode 100644 tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c delete mode 100644 tests/regression/80-context_gas_sens/04-hardcoded_recursion.c delete mode 100644 tests/regression/80-context_gas_sens/05-function_chain.c delete mode 100644 tests/regression/80-context_gas_sens/06-loop_unrolling.c delete mode 100644 tests/regression/80-context_gas_sens/07-call_in_loop_adv.c delete mode 100644 tests/regression/80-context_gas_sens/08-circle_call_and_loops.c delete mode 100644 tests/regression/80-context_gas_sens/10-call_in_call.c delete mode 100644 tests/regression/81-context_gas_insens/01-multiple_param_simple.c delete mode 100644 tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c delete mode 100644 tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c delete mode 100644 tests/regression/81-context_gas_insens/04-function_chain.c delete mode 100644 tests/regression/81-context_gas_insens/06-call_in_loop.c delete mode 100644 tests/regression/81-context_gas_insens/07-circle_call_and_loops.c delete mode 100644 tests/regression/81-context_gas_insens/08-loop_unrolling.c delete mode 100644 tests/regression/81-context_gas_insens/10-call_in_call.c delete mode 100644 tests/regression/81-context_gas_insens/12-circle_up_down.c delete mode 100644 tests/regression/81-context_gas_insens/13-mutualRecursion.c diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 1bbb13c830..8bc0291358 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -8,8 +8,8 @@ module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> exp list -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) - val printStack: fundec -> exp list -> t QueueImmut.t -> t QueueImmut.t -> unit (* a helper function to print the callstack *) + val pushElem: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) + val printStack: fundec -> t QueueImmut.t -> t QueueImmut.t -> unit (* a helper function to print the callstack *) end (** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context @@ -42,77 +42,84 @@ struct module V = EmptyV module G = Lattice.Unit + (*let unlift x = match x with + | `Lifted x -> x + | _ -> failwith "Callstring: Unlift error! The domain cannot be derived from Top or Bottom!"*) (* TODO*) + let name () = "callstring_"^ CT.stackTypeName let startstate v = `Lifted (QueueImmut.create ()) let exitstate v = `Lifted (QueueImmut.create ()) - (*let threadenter ctx ~multiple lval f args = - let elem: CT.t option = CT.pushElemVar f args ctx in - let new_stack: C.t = CallStack.push ctx.local elem in - CT.printStackVar f args ctx.local new_stack; (* just for debugging purpose*) - [new_stack]*) - let context fd x = match x with | `Lifted x -> x | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO*) let enter ctx r f args = - let elem: CT.t option = CT.pushElem f args ctx in (* a list of elements that should be pushed onto the stack*) + let elem: CT.t option = CT.pushElem f ctx in (* a list of elements that should be pushed onto the stack*) let new_stack: C.t = CallStack.push (context f ctx.local) elem in - (*CT.printStack f args ctx.local new_stack; *)(* just for debugging purpose*) + (*CT.printStack f (unlift ctx.local) new_stack;*) (* just for debugging purpose*) [ctx.local, `Lifted new_stack] let combine_env ctx lval fexp f args fc au f_ask = ctx.local + + let threadenter ctx ~multiple lval v args = + let elem: CT.t option = CT.pushElem (Cilfacade.find_varinfo_fundec v) ctx in (* a list of elements that should be pushed onto the stack*) + let new_stack: C.t = CallStack.push (context v ctx.local) elem in + (*CT.printStack (Cilfacade.find_varinfo_fundec v) (unlift ctx.local) new_stack; *)(* just for debugging purpose*) + [`Lifted new_stack] end module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" - let pushElem f args ctx = Some f + let pushElem f ctx = Some f - let printStack f expL listA listB = + let printStack f listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listA; printf "\nList neu: "; QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listB; printf "\n\n" + end module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" - let pushElem f args ctx = + let pushElem f ctx = match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) | Statement stmt -> Some stmt | _ -> None (* first statement is filtered*) - let printStack f expL listA listB = + let printStack f listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listA; printf "\nList neu: "; QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listB; printf "\n\n" + end module Location:Callstack_Type = struct include CilType.Location let stackTypeName = "loc" - let pushElem f args ctx = + let pushElem f ctx = Some !Goblint_tracing.current_loc - let printStack f expL listA listB = + let printStack f listA listB = printf "fundec: %s\n" (CilType.Fundec.show f); printf "List alt: "; QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listA; printf "\nList neu: "; QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listB; printf "\n\n" + end (* Lifters for the Callstring approach with different Callstack element types*) diff --git a/src/autoTune.ml b/src/autoTune.ml index 36567ce700..b2acac055e 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -242,7 +242,7 @@ let focusOnMemSafetySpecification () = let focusOnTermination (spec: Svcomp.Specification.t) = match spec with | Termination -> - let terminationAnas = ["termination"; "threadflag"] in + let terminationAnas = ["termination"; "apron"; "threadflag"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; set_string "sem.int.signed_overflow" "assume_none"; @@ -446,9 +446,9 @@ let apronOctagonOption factors file = let cost = (Batteries.Int.pow (locals + globals) 3) * (factors.instructions / 70) in let activateVars () = print_endline @@ "Octagon: " ^ string_of_int cost; - (*set_bool "annotation.goblint_relation_track" true;*) + set_bool "annotation.goblint_relation_track" true; set_string "ana.apron.domain" "octagon"; - (*set_auto "ana.activated[+]" "apron";*) + set_auto "ana.activated[+]" "apron"; set_bool "ana.apron.threshold_widening" true; set_string "ana.apron.threshold_widening_constants" "comparisons"; print_endline "Enabled octagon domain for:"; diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0683f77e8f..e673d230fd 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -559,19 +559,24 @@ struct else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) ; local = (fst ctx.local, cg_val ctx - 1)} - let rec showExprList args = (*TODO: delete, just here for printing*) + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t) + | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = let ctx_dec = dec_context_gas ctx in - if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args); + (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in - liftmap_tup (S.enter (conv ctx_dec) r f args) (* TODO: hier ctx oder ctx_dec???*) + liftmap_tup (S.enter (conv ctx) r f args) (* TODO: hier ctx oder ctx_dec???*) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f + let threadenter ctx ~multiple lval f args = + let ctx_dec = dec_context_gas ctx in + (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) + liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx_dec (* TODO: hier ctx oder ctx_dec???*) + let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q let assign ctx lval expr = S.assign (conv ctx) lval expr, cg_val ctx @@ -585,7 +590,6 @@ struct let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx - let threadenter ctx ~multiple lval f args = liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx (*TODO: it's possible to decrease the counter also here*) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end diff --git a/tests/regression/80-context_gas/01-basic_tests.c b/tests/regression/80-context_gas/01-basic_tests.c new file mode 100644 index 0000000000..95701185b6 --- /dev/null +++ b/tests/regression/80-context_gas/01-basic_tests.c @@ -0,0 +1,33 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// Basic examples + +int f(int x, int y) +{ + if (x == 0) + { + + return y; + } + return f(--x, --y); +} + +int main() +{ + int y = f(0, 0); + __goblint_check(y == 0); + + int y = f(5, 5); + __goblint_check(y == 0); + + int y = f(7, 7); + __goblint_check(y == 0); //boundary (included) + + int y = f(8, 8); + __goblint_check(y == 0); //UNKNOWN //boundary (excluded) + + int y = f(10, 10); + __goblint_check(y == 0); //UNKNOWN + + int y = f(1000, 1000); + __goblint_check(y == 0); //UNKNOWN +} \ No newline at end of file diff --git a/tests/regression/80-context_gas/02-multiple_function_chain_tests.c b/tests/regression/80-context_gas/02-multiple_function_chain_tests.c new file mode 100644 index 0000000000..c3be5cef9a --- /dev/null +++ b/tests/regression/80-context_gas/02-multiple_function_chain_tests.c @@ -0,0 +1,74 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// Tests multiple recursive function calls +#include + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + __goblint_check(f(-5) == 0); + __goblint_check(f(0) == 3); + __goblint_check(f(1) == 2); + __goblint_check(f(2) == 1); + __goblint_check(f(7) == 1); //boundary (included) + __goblint_check(f(8) == 1); //UNKNOWN //boundary (excluded) + __goblint_check(f(20) == 1); //UNKNOWN + + __goblint_check(g(-10) == 0); + __goblint_check(g(0) == 2); + __goblint_check(g(1) == 1); + + __goblint_check(h(-10) == 0); + __goblint_check(h(0) == 1); + __goblint_check(h(7) == 1); //boundary (included) + __goblint_check(h(8) == 1); //UNKNOWN //boundary (excluded) + + int res1 = h(5); + int res2 = h(4); + int result = res1 + res2; + __goblint_check(result == 2); + + __goblint_check(f(g(h(7))) == 2); // h(7) = 1; g(1) = 1; f(1) = 2; + __goblint_check(f(g(h(8))) == 2); //UNKNOWN // h(8) = UNKNOWN +} diff --git a/tests/regression/80-context_gas/03-contextGas0.c b/tests/regression/80-context_gas/03-contextGas0.c new file mode 100644 index 0000000000..85fc6ed48e --- /dev/null +++ b/tests/regression/80-context_gas/03-contextGas0.c @@ -0,0 +1,23 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 0 + +int f(int x, int y) +{ + if (x == 0) + { + + return y; + } + return f(--x, --y); +} + +int main() +{ + int y = f(0, 0); + __goblint_check(y == 0); //UNKNOWN + + int y = f(5, 5); + __goblint_check(y == 0); //UNKNOWN + + int y = f(1000, 1000); + __goblint_check(y == 0); //UNKNOWN +} \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-contextGasNeg.c b/tests/regression/80-context_gas/04-contextGasNeg.c new file mode 100644 index 0000000000..d8a5bcb483 --- /dev/null +++ b/tests/regression/80-context_gas/04-contextGasNeg.c @@ -0,0 +1,23 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value -5 + +int f(int x, int y) +{ + if (x == 0) + { + + return y; + } + return f(--x, --y); +} + +int main() +{ + int y = f(0, 0); + __goblint_check(y == 0); //UNKNOWN + + int y = f(5, 5); + __goblint_check(y == 0); //UNKNOWN + + int y = f(1000, 1000); + __goblint_check(y == 0); //UNKNOWN +} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/05-ackermann.c b/tests/regression/80-context_gas/05-ackermann.c similarity index 92% rename from tests/regression/81-context_gas_insens/05-ackermann.c rename to tests/regression/80-context_gas/05-ackermann.c index 90187d5a9f..28f3587521 100644 --- a/tests/regression/81-context_gas_insens/05-ackermann.c +++ b/tests/regression/80-context_gas/05-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 // This code would result in a StackOverflow if it is analyses fully context sensitive #include diff --git a/tests/regression/80-context_gas/06-circle_call.c b/tests/regression/80-context_gas/06-circle_call.c new file mode 100644 index 0000000000..2347ef0b70 --- /dev/null +++ b/tests/regression/80-context_gas/06-circle_call.c @@ -0,0 +1,51 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 +// Checks if recursion in loops is handled properly +#include + +int f(int i); + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(i + 1); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(i - 2) + g(i - 3); + } + return res; +} + +int main(void) +{ + printf("%i, %i\n", f(200), g(10)); + + __goblint_check(f(0) == 2); + __goblint_check(f(3) == 2); + __goblint_check(f(7) == 13); + __goblint_check(f(8) == 21); // UNKNOWN //boundary (excluded) + __goblint_check(f(9) == 34); // UNKNOWN + __goblint_check(f(20) == 6765); // UNKNOWN + + __goblint_check(g(3) == 3); + __goblint_check(g(6) == 13); // boundary (included) + __goblint_check(g(7) == 21); // UNKNOWN + __goblint_check(g(8) == 34); // UNKNOWN + __goblint_check(g(20) == 10946); // UNKNOWN +} diff --git a/tests/regression/80-context_gas/07-loop_unrolling.c b/tests/regression/80-context_gas/07-loop_unrolling.c new file mode 100644 index 0000000000..d0d5b6accc --- /dev/null +++ b/tests/regression/80-context_gas/07-loop_unrolling.c @@ -0,0 +1,64 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// TODO +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int main(void) +{ + for (int i = 1; i > 0; i--) + { + __goblint_check(f(2) == 1); + __goblint_check(f(2000) == 1); //UNKNOWN + } + + // loop should be completely unrolled + for (int i = 3; i > 0; i--) + { + __goblint_check(f(1) == 1); + __goblint_check(f(20) == 1); //UNKNOWN + } + + int res1 = 0; + int res2 = 0; + int result = 0; + + // context sensitive analysis + for (int i = 5; i > 0; i--) + { + res1 = f(3); + res2 = f(i); + __goblint_check(res1 == 1); + __goblint_check(res2 == 1); //TODO + result += res1 + res2; + } + __goblint_check(res1 == 1); + __goblint_check(res2 == 1); //TODO + __goblint_check(result == 10); //TODO + + for (int i = 5; i > 0; i--) + { + __goblint_check(f(0) == 1); + __goblint_check(f(7) == 1); //boundary (included)) + __goblint_check(f(8) == 1); //UNKNOWN //boundary (excluded) + } + + // high number of iterations + for (int i = 500; i > 0; i--) + { + __goblint_check(f(i) == 1); //UNKNOWN + __goblint_check(f(4) == 1); + } +} diff --git a/tests/regression/81-context_gas_insens/09-main_recursion.c b/tests/regression/80-context_gas/09-main_recursion_insens.c similarity index 100% rename from tests/regression/81-context_gas_insens/09-main_recursion.c rename to tests/regression/80-context_gas/09-main_recursion_insens.c diff --git a/tests/regression/80-context_gas_sens/09-main_recursion.c b/tests/regression/80-context_gas/10-main_recursion_sens.c similarity index 94% rename from tests/regression/80-context_gas_sens/09-main_recursion.c rename to tests/regression/80-context_gas/10-main_recursion_sens.c index 01bf3a0c64..867522dc52 100644 --- a/tests/regression/80-context_gas_sens/09-main_recursion.c +++ b/tests/regression/80-context_gas/10-main_recursion_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 // Checks if only recursion in main works properly + boundary check // TODO #include diff --git a/tests/regression/80-context_gas/11-thread_handling.c b/tests/regression/80-context_gas/11-thread_handling.c new file mode 100644 index 0000000000..5077baa8f8 --- /dev/null +++ b/tests/regression/80-context_gas/11-thread_handling.c @@ -0,0 +1,86 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +#include +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + int result = procedure(0); + __goblint_check(result == 8); + + result = procedure(5); + __goblint_check(result == 10); + return NULL; +} + +void *t_insens(void *arg) +{ + int result = procedure(6); + __goblint_check(result == 10); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Creat the thread + pthread_create(&id, NULL, t_sens, NULL); + + // Creat the thread + pthread_create(&id, NULL, t_insens, NULL); + return 0; +} diff --git a/tests/regression/81-context_gas_insens/11-endless_loop.c b/tests/regression/80-context_gas/12-endless_loop.c similarity index 91% rename from tests/regression/81-context_gas_insens/11-endless_loop.c rename to tests/regression/80-context_gas/12-endless_loop.c index 40e7b9941e..e350a8c722 100644 --- a/tests/regression/81-context_gas_insens/11-endless_loop.c +++ b/tests/regression/80-context_gas/12-endless_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 // Will result in an endless loop without context insensitive analysis #include diff --git a/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c b/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c deleted file mode 100644 index d1715eaced..0000000000 --- a/tests/regression/80-context_gas_sens/01-basic_multiple_param_simple.c +++ /dev/null @@ -1,18 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Basic example -int num_iterat = 5; - -int f(int x, int y) -{ - if (x == 0) - { - __goblint_check(y == 0); - return 0; - } - f(--x, --y); -} - -int main() -{ - f(num_iterat, num_iterat); -} \ No newline at end of file diff --git a/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c b/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c deleted file mode 100644 index 0856eea230..0000000000 --- a/tests/regression/80-context_gas_sens/02-boundary_check_simple_rec.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Basic example + boundary check for simple recursion -#include - -int num_iterat = 8; // should be context gas value - 2 -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); -} diff --git a/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c b/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c deleted file mode 100644 index 558b7e436f..0000000000 --- a/tests/regression/80-context_gas_sens/03-boundary_check_multiple_rec.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly + boundary check for multiple recursions -#include - -int num_iterat = 8; // should be context gas value - 2 - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - int result = res1 + res2 + res3 + res4 + res5; - - __goblint_check(result == 5); -} diff --git a/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c b/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c deleted file mode 100644 index d1ac462870..0000000000 --- a/tests/regression/80-context_gas_sens/04-hardcoded_recursion.c +++ /dev/null @@ -1,47 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if the context gas is reduced too much, due to the (not needed) function calls f(4) and f(3) -#include - -int num_iterat = 2; -int a = 20; - -int f(int i) -{ - if (i == 5) - { - a = 4; - f(4); - } - if (i == 4) - { - a = 3; - f(3); - } - if (i == 3) - { - a = 2; - f(2); - } - if (i == 2) - { - a = 1; - f(1); - } - if (i == 1) - { - a = 0; - f(0); - } - if (i == 0) - { - return 0; - } -} - -int main(void) -{ - f(num_iterat); - - // if the analysis runs fully context sensitive, "a" should be equal 0 - __goblint_check(a == 0); -} diff --git a/tests/regression/80-context_gas_sens/05-function_chain.c b/tests/regression/80-context_gas_sens/05-function_chain.c deleted file mode 100644 index 99b4f0a89d..0000000000 --- a/tests/regression/80-context_gas_sens/05-function_chain.c +++ /dev/null @@ -1,55 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if Chain-Calls are handled properly -#include - -int num_iterat = 8; // should be context gas value - 2 - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); // context sensitive -} diff --git a/tests/regression/80-context_gas_sens/06-loop_unrolling.c b/tests/regression/80-context_gas_sens/06-loop_unrolling.c deleted file mode 100644 index b95c7a8638..0000000000 --- a/tests/regression/80-context_gas_sens/06-loop_unrolling.c +++ /dev/null @@ -1,34 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 -// Checks if recursion in loops are handled properly + loop unrolling -// TODO -#include - -int num_iterat = 3; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - int res = 0; - int result = 0; - for (int i = 5; i > 0; i--) - { - res = f(num_iterat); - __goblint_check(res == 1); - result += res; - } - __goblint_check(res == 1); - __goblint_check(result == 5); //TODO -} diff --git a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c b/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c deleted file mode 100644 index d395229ea4..0000000000 --- a/tests/regression/80-context_gas_sens/07-call_in_loop_adv.c +++ /dev/null @@ -1,31 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks if recursion in loop is handled properly + iterator variable = function parameter -// TODO -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - int res = 0; - int result = 0; - for (int i = 5; i > 0; i--) - { - res = f(i); - __goblint_check(res == 1); // TODO - result += res; - } - __goblint_check(result == 5); // TODO -} diff --git a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c b/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c deleted file mode 100644 index a0ff11c4da..0000000000 --- a/tests/regression/80-context_gas_sens/08-circle_call_and_loops.c +++ /dev/null @@ -1,49 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks if recursion in loops is handled properly -#include - -int num_iterat = 2; - -int f(int i); - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = 0; - int res2 = 0; - for (int i = 2; i > 0; i--) - { - res1 = f(num_iterat); - res2 = g(num_iterat); - __goblint_check(res1 == 2); - __goblint_check(res2 == 1); - } - -} diff --git a/tests/regression/80-context_gas_sens/10-call_in_call.c b/tests/regression/80-context_gas_sens/10-call_in_call.c deleted file mode 100644 index b3eac1d382..0000000000 --- a/tests/regression/80-context_gas_sens/10-call_in_call.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if nested recursions are handled properly -#include - -int num_iterat = 8; // should be context gas value - 2 - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res = f(g(h(num_iterat))); // h(8) = 3; g(3) = 2; f(2) = 1 - - __goblint_check(res == 1); -} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/01-multiple_param_simple.c b/tests/regression/81-context_gas_insens/01-multiple_param_simple.c deleted file mode 100644 index 9e6e4b870b..0000000000 --- a/tests/regression/81-context_gas_insens/01-multiple_param_simple.c +++ /dev/null @@ -1,18 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Basic example -int num_iterat = 100; - -int f(int x, int y) -{ - if (x == 0) - { - __goblint_check(y == 0); // UNKNOWN - return 0; - } - f(--x, --y); -} - -int main() -{ - f(num_iterat, num_iterat); -} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c b/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c deleted file mode 100644 index 4fd2156dc2..0000000000 --- a/tests/regression/81-context_gas_insens/02-boundary_check_simple_rec.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Basic example + boundary check for simple recursion -#include - -int num_iterat = 9; // should be context gas value - 1 -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c b/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c deleted file mode 100644 index ef678dc7ee..0000000000 --- a/tests/regression/81-context_gas_insens/03-boundary_check_multiple_rec.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly + boundary check for multiple recursions -#include - -int num_iterat = 9; // should be context gas value - 1 - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - int result = res1 + res2 + res3 + res4 + res5; - - __goblint_check(result == 5); //UNKNOWN -} diff --git a/tests/regression/81-context_gas_insens/04-function_chain.c b/tests/regression/81-context_gas_insens/04-function_chain.c deleted file mode 100644 index 1cafd8086e..0000000000 --- a/tests/regression/81-context_gas_insens/04-function_chain.c +++ /dev/null @@ -1,55 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks if function chains are handled properly + boundary check -#include - -int num_iterat = 9; // should be context gas value - 1 - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); // UNKNOWN -} diff --git a/tests/regression/81-context_gas_insens/06-call_in_loop.c b/tests/regression/81-context_gas_insens/06-call_in_loop.c deleted file mode 100644 index 9a4f139fb8..0000000000 --- a/tests/regression/81-context_gas_insens/06-call_in_loop.c +++ /dev/null @@ -1,28 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks proper handling of recursion in loops + iterator variable = function parameter -#include - -int num_iterat = 1000; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - for (int i = num_iterat; i > 0; i--) - { - int result = f(i); - __goblint_check(result == 1); // UNKNOWN - } -} diff --git a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c b/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c deleted file mode 100644 index 8b8e1b7bc7..0000000000 --- a/tests/regression/81-context_gas_insens/07-circle_call_and_loops.c +++ /dev/null @@ -1,48 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks proper handling of recursions in loops -#include - -int num_iterat = 20; - -int f(int i); - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = 0; - int res2 = 0; - for (int i = 2; i > 0; i--) - { - res1 = f(num_iterat); - res2 = g(num_iterat); - __goblint_check(res1 == 2); //UNKNOWN - __goblint_check(res2 == 1); //UNKNOWN - } -} diff --git a/tests/regression/81-context_gas_insens/08-loop_unrolling.c b/tests/regression/81-context_gas_insens/08-loop_unrolling.c deleted file mode 100644 index 8ba865cc98..0000000000 --- a/tests/regression/81-context_gas_insens/08-loop_unrolling.c +++ /dev/null @@ -1,29 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 -// Checks if loop unrolling makes a difference for the analysis -#include - -int num_iterat = 20; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - for (int i = 5; i > 0; i--) - { - int res = f(num_iterat); - __goblint_check(res == 2); //UNKNOWN - } - -} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/10-call_in_call.c b/tests/regression/81-context_gas_insens/10-call_in_call.c deleted file mode 100644 index db60a35b80..0000000000 --- a/tests/regression/81-context_gas_insens/10-call_in_call.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Interesting if nested recursions are handled properly -#include - -int num_iterat = 9; // should be context gas value - 1 - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 - - __goblint_check(res == 1); // UNKNOWN -} \ No newline at end of file diff --git a/tests/regression/81-context_gas_insens/12-circle_up_down.c b/tests/regression/81-context_gas_insens/12-circle_up_down.c deleted file mode 100644 index 8707290fe2..0000000000 --- a/tests/regression/81-context_gas_insens/12-circle_up_down.c +++ /dev/null @@ -1,48 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set -// Checks proper handling of recursions in loops -#include - -int num_iterat = 20; - -int f(int i); - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(i + 1); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(i - 2) + g(i - 3); - } - return res; -} - -int main(void) -{ - int res1 = 0; - int res2 = 0; - for (int i = 2; i > 0; i--) - { - res1 = f(num_iterat); - res2 = g(num_iterat); - __goblint_check(res1 == 6765); // UNKNOWN - __goblint_check(res2 == 10946); // UNKNOWN - } -} diff --git a/tests/regression/81-context_gas_insens/13-mutualRecursion.c b/tests/regression/81-context_gas_insens/13-mutualRecursion.c deleted file mode 100644 index 88a955ab8a..0000000000 --- a/tests/regression/81-context_gas_insens/13-mutualRecursion.c +++ /dev/null @@ -1,33 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.sv-comp.functions --enable ana.float.interval --enable ana.int.interval --enable ana.autotune.enabled --set ana.base.arrays.domain partitioned --set ana.activated[+] expRelation -/* - * Date: 07/07/2015 - * Created by: Ton Chanh Le (chanhle@comp.nus.edu.sg) - */ - -extern int __VERIFIER_nondet_int(); - -int f(int x); -int g(int x); - -int f(int x) -{ - if (x <= 0) - return 0; - else - return g(x) + g(x + 1); -} - -int g(int x) -{ - if (x <= 0) - return 0; - else - return f(x - 1) + f(x - 2); -} - -int main() -{ - int x = __VERIFIER_nondet_int(); - int res = g(x); - __goblint_check(res == 0); -} \ No newline at end of file From 49b244abdfdc88896eafa29a4fea1bdb8d08e415 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 11 Jan 2024 21:33:15 +0100 Subject: [PATCH 075/128] added callStack_height specification to callstring tests; added new sv comp configurations; deleted unneccessary functions in QueueImmut --- conf/svcomp80-context_gas_val18.json | 145 ++++++++++++++++++ conf/svcomp80-context_gas_val30.json | 145 ++++++++++++++++++ src/common/util/queueImmut.ml | 40 +---- src/framework/constraints.ml | 8 +- .../82-callstring_Fundec/01-simple_rec_sens.c | 2 +- .../02-multiple_function_chain_tests.c | 77 ++++++++++ .../03-multiple_rec_sens.c | 2 +- .../04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../07-call_in_call_sens.c | 2 +- .../82-callstring_Fundec/08-ackermann.c | 2 +- .../09-circle_call_and_loops.c | 2 +- .../10-circle_call_and_big_loop.c | 2 +- .../11-big_call_and_loop.c | 2 +- .../82-callstring_Fundec/12-loop_unrolling.c | 2 +- .../82-callstring_Fundec/13-thread_creation.c | 92 +++++++++++ .../14-thread_creation_problem.c | 89 +++++++++++ ...2-simple_rec_ins.c => 15-simple_rec_ins.c} | 2 +- .../83-callstring_Stmt/01-simple_rec_sens.c | 2 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 2 +- .../83-callstring_Stmt/03-multiple_rec_sens.c | 2 +- .../83-callstring_Stmt/04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../06-function_chain_ins.c | 2 +- .../83-callstring_Stmt/07-call_in_call.c | 2 +- .../08-circle_call_and_big_loop.c | 2 +- .../83-callstring_Stmt/09-thread_creation.c | 88 +++++++++++ .../84-callstring_both/01-simple_rec_sens.c | 2 +- .../84-callstring_both/02-simple_rec_ins.c | 2 +- .../84-callstring_both/03-multiple_rec_sens.c | 2 +- .../84-callstring_both/04-multiple_rec_ins.c | 2 +- .../85-callstring_Loc/01-simple_rec_sens.c | 2 +- .../85-callstring_Loc/02-simple_rec_ins.c | 2 +- .../85-callstring_Loc/03-multiple_rec_sens.c | 2 +- .../85-callstring_Loc/04-multiple_rec_ins.c | 2 +- .../05-function_chain_sens.c | 2 +- .../85-callstring_Loc/06-function_chain_ins.c | 2 +- .../85-callstring_Loc/07-call_in_call.c | 2 +- .../08-circle_call_and_big_loop.c | 2 +- .../85-callstring_Loc/09-thread_creation.c | 88 +++++++++++ 41 files changed, 761 insertions(+), 75 deletions(-) create mode 100644 conf/svcomp80-context_gas_val18.json create mode 100644 conf/svcomp80-context_gas_val30.json create mode 100644 tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c create mode 100644 tests/regression/82-callstring_Fundec/13-thread_creation.c create mode 100644 tests/regression/82-callstring_Fundec/14-thread_creation_problem.c rename tests/regression/82-callstring_Fundec/{02-simple_rec_ins.c => 15-simple_rec_ins.c} (66%) create mode 100644 tests/regression/83-callstring_Stmt/09-thread_creation.c create mode 100644 tests/regression/85-callstring_Loc/09-thread_creation.c diff --git a/conf/svcomp80-context_gas_val18.json b/conf/svcomp80-context_gas_val18.json new file mode 100644 index 0000000000..cdcf813363 --- /dev/null +++ b/conf/svcomp80-context_gas_val18.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": true, + "ctx_gas_value": 18 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/svcomp80-context_gas_val30.json b/conf/svcomp80-context_gas_val30.json new file mode 100644 index 0000000000..1337059ac2 --- /dev/null +++ b/conf/svcomp80-context_gas_val30.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": true, + "ctx_gas_value": 30 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/src/common/util/queueImmut.ml b/src/common/util/queueImmut.ml index d1c6fe288d..de5743ed77 100644 --- a/src/common/util/queueImmut.ml +++ b/src/common/util/queueImmut.ml @@ -108,26 +108,6 @@ let dequeue_tup_opt = function (* returns the removed element and the remaining | x::xs -> (Some x , Queue(xs, []))) | Queue (x::q_first, q_last) -> (Some x, Queue (q_first, q_last)) -(** [del_n_elem n q] deletes the first n elements of the queue*) -let del_n_elem n (Queue (q_first, q_last)) = - let rec del n (Queue (q_first, q_last)) = - if n = 0 then (Queue (q_first, q_last)) - else - match q_first, q_last with - | [], [] -> Queue ([], []) - | [], xs -> del n (Queue (List.rev xs, [])) - | x::xs, ys -> del (n-1) (Queue (xs, ys)) - in - if n <= 0 then (Queue (q_first, q_last)) (* check if command is used correctly *) - else( - if length (Queue (q_first, q_last)) <= n (* check if everything is deleted *) - then Queue ([], []) - else - let l_first = List.length q_first in - if l_first <= n (* check if the whole first list is deleted *) - then del (n-l_first) (Queue (List.rev q_last, [])) - else del n (Queue (q_first, q_last))) - (** [iter f q] applies [f] in turn to all elements of [q], from the least recently entered to the most recently entered.*) let iter f (Queue (q_first, q_last)) = @@ -153,22 +133,4 @@ let fold_left f accu (Queue (q_first, q_last)) = (** [fold_right f [a1; ...; an] accu] is [f a1 (f a2 (... (f an accu) ...))]. Not tail-recursive.*) let fold_right f (Queue (q_first, q_last)) accu = - List.fold_right f (List.rev q_last) accu |> List.fold_right f q_first - -(** [assoc a q] returns the value associated with key [a] in the queue of - pairs [q]. That is, - [assoc a { ...; (a,b); ...}= b] - if [(a,b)] is the leftmost binding of [a] in queue [q]. - @raise Not_found if there is no value associated with [a] in the - queue [q].*) -let assoc x (Queue (q_first, q_last)) = - match List.assoc_opt x q_first, List.assoc_opt x q_last with - | None, None -> raise Not_found - | Some y, _ -> y - | None, Some y -> y - -(** Same as {!assoc}, but simply return [true] if a binding exists, - and [false] if no bindings exist for the given key.*) -let mem_assoc x (Queue (q_first, q_last)) = List.mem_assoc x q_first || List.mem_assoc x q_last - - + List.fold_right f (List.rev q_last) accu |> List.fold_right f q_first \ No newline at end of file diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e673d230fd..174f28aef9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -568,14 +568,14 @@ struct let ctx_dec = dec_context_gas ctx in (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in - liftmap_tup (S.enter (conv ctx) r f args) (* TODO: hier ctx oder ctx_dec???*) + liftmap_tup (S.enter (conv ctx) r f args) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f let threadenter ctx ~multiple lval f args = - let ctx_dec = dec_context_gas ctx in - (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) - liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx_dec (* TODO: hier ctx oder ctx_dec???*) + let ctx_dec = dec_context_gas ctx in + (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) + liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx_dec let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c index 7548fe63dc..94e02b5704 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c b/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c new file mode 100644 index 0000000000..66645ce19b --- /dev/null +++ b/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c @@ -0,0 +1,77 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Tests multiple recursive function calls +// TODO!!! +#include + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = h(--i); + } + return res; +} + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + //__goblint_check(f(-5) == 0); + //int res1 = f(0); + //__goblint_check(res1 == 3); + //__goblint_check(f(1) == 2); + //__goblint_check(f(2) == 1); + //int res2 = f(8); + //__goblint_check(res2 == 1); //boundary (included) + //__goblint_check(f(9) == 1); //UNKNOWN //boundary (excluded) + //__goblint_check(f(20) == 1); //UNKNOWN + + //__goblint_check(g(-10) == 0); + //__goblint_check(g(0) == 2); + //__goblint_check(g(1) == 1); + + //__goblint_check(h(-10) == 0); + __goblint_check(h(5) == 1); + //__goblint_check(h(8) == 1); //boundary (included) + ///__goblint_check(h(9) == 1); //UNKNOWN //boundary (excluded) + + //int res1 = h(5); + //int res2 = h(4); + //int result = res1 + res2; + //__goblint_check(result == 2); + + //__goblint_check(f(g(h(9))) == 2); // h(9) = 1; g(1) = 1; f(1) = 2; + //__goblint_check(f(g(h(10))) == 2); //UNKNOWN // h(10) = UNKNOWN +} diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 3bef88d1b3..7feca66f22 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c index 61e53c45d8..7f4b7cc686 100644 --- a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index c65bb8bdd4..521502a45c 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c index c9f7653e9f..2e4b176ea1 100644 --- a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c index 11ae47b759..7c0703a437 100644 --- a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c index 8082e2f082..08f19aea86 100644 --- a/tests/regression/82-callstring_Fundec/08-ackermann.c +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // This code would result in a StackOverflow if it is analyses fully context sensitive #include diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c index 3fd8175e7f..f5c2da3a35 100644 --- a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c index 9ca346bac4..751d4dbe5a 100644 --- a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c index 941756bdce..b977b615c6 100644 --- a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c +++ b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result // TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) #include diff --git a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c index 15f54a1b80..3ce98936e4 100644 --- a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c +++ b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 // Checks if recursion in loops are handled properly + loop unrolling // TODO #include diff --git a/tests/regression/82-callstring_Fundec/13-thread_creation.c b/tests/regression/82-callstring_Fundec/13-thread_creation.c new file mode 100644 index 0000000000..03edf9dd50 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/13-thread_creation.c @@ -0,0 +1,92 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + int result = procedure(0); + __goblint_check(result == 8); + return NULL; +} + +void *t_sens2(void *arg) +{ + int result = procedure(7); + __goblint_check(result == 10); + return NULL; +} + +void *t_insens(void *arg) +{ + int result = procedure(8); + __goblint_check(result == 10); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + pthread_t id3; + + // Creat the thread + pthread_create(&id, NULL, t_sens, NULL); + pthread_create(&id2, NULL, t_sens2, NULL); + pthread_create(&id3, NULL, t_insens, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c new file mode 100644 index 0000000000..35cc1adc09 --- /dev/null +++ b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c @@ -0,0 +1,89 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + int result = procedure(0); + __goblint_check(result == 8); //TODO + + result = procedure(3); + __goblint_check(result == 10); //TODO + return NULL; +} + +void *t_insens(void *arg) +{ + int result = procedure(6); + __goblint_check(result == 10); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + + // Creat the thread + pthread_create(&id, NULL, t_sens, NULL); + //pthread_join(id, NULL); + + // Creat the thread + pthread_create(&id2, NULL, t_insens, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c similarity index 66% rename from tests/regression/82-callstring_Fundec/02-simple_rec_ins.c rename to tests/regression/82-callstring_Fundec/15-simple_rec_ins.c index 77c544e794..0308699acf 100644 --- a/tests/regression/82-callstring_Fundec/02-simple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index b7bf539693..5d1b90b952 100644 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c index da58b8a881..347b6525a0 100644 --- a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index 7dc7e04a98..d13f8004d4 100644 --- a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c index 5614802151..0a7c6a5966 100644 --- a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index 085210b8a2..822ae4d41f 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c index 8debbe9f46..9ce5d1a5ef 100644 --- a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c index 7ef3a83194..8f92286dd6 100644 --- a/tests/regression/83-callstring_Stmt/07-call_in_call.c +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c index 38e7051736..7c958a63d0 100644 --- a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c +++ b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed #include diff --git a/tests/regression/83-callstring_Stmt/09-thread_creation.c b/tests/regression/83-callstring_Stmt/09-thread_creation.c new file mode 100644 index 0000000000..635327b22b --- /dev/null +++ b/tests/regression/83-callstring_Stmt/09-thread_creation.c @@ -0,0 +1,88 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + int result = procedure(0); + __goblint_check(result == 8); + + result = procedure(8); + __goblint_check(result == 10); + return NULL; +} + +void *t_insens(void *arg) +{ + int result = procedure(9); + __goblint_check(result == 10); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + + // Creat the thread + pthread_create(&id, NULL, t_sens, NULL); + + // Creat the thread + pthread_create(&id2, NULL, t_insens, NULL); + return 0; +} diff --git a/tests/regression/84-callstring_both/01-simple_rec_sens.c b/tests/regression/84-callstring_both/01-simple_rec_sens.c index 210ecfb4d8..88caca0889 100644 --- a/tests/regression/84-callstring_both/01-simple_rec_sens.c +++ b/tests/regression/84-callstring_both/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/84-callstring_both/02-simple_rec_ins.c b/tests/regression/84-callstring_both/02-simple_rec_ins.c index 7be2bedcf7..e0885f702d 100644 --- a/tests/regression/84-callstring_both/02-simple_rec_ins.c +++ b/tests/regression/84-callstring_both/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/84-callstring_both/03-multiple_rec_sens.c b/tests/regression/84-callstring_both/03-multiple_rec_sens.c index 0b7977a28f..8da5325850 100644 --- a/tests/regression/84-callstring_both/03-multiple_rec_sens.c +++ b/tests/regression/84-callstring_both/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/84-callstring_both/04-multiple_rec_ins.c b/tests/regression/84-callstring_both/04-multiple_rec_ins.c index 65903ff22d..e919335ca7 100644 --- a/tests/regression/84-callstring_both/04-multiple_rec_ins.c +++ b/tests/regression/84-callstring_both/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_stmt --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c index d0639cae6a..cbd218713a 100644 --- a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c +++ b/tests/regression/85-callstring_Loc/01-simple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c index 791742154d..9a672986a4 100644 --- a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c +++ b/tests/regression/85-callstring_Loc/02-simple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c index 1ef2a12f89..f684b8e4b6 100644 --- a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c +++ b/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c index b53aa47b32..7c2a0a30ec 100644 --- a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c +++ b/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Interesting if multiple recursions are handled properly #include diff --git a/tests/regression/85-callstring_Loc/05-function_chain_sens.c b/tests/regression/85-callstring_Loc/05-function_chain_sens.c index 18e6605dd3..5d3af4c54b 100644 --- a/tests/regression/85-callstring_Loc/05-function_chain_sens.c +++ b/tests/regression/85-callstring_Loc/05-function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/85-callstring_Loc/06-function_chain_ins.c b/tests/regression/85-callstring_Loc/06-function_chain_ins.c index 4ce249d956..3b1f733a50 100644 --- a/tests/regression/85-callstring_Loc/06-function_chain_ins.c +++ b/tests/regression/85-callstring_Loc/06-function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Checks if function chains are handled properly #include diff --git a/tests/regression/85-callstring_Loc/07-call_in_call.c b/tests/regression/85-callstring_Loc/07-call_in_call.c index 5ddb98235e..def1c9981c 100644 --- a/tests/regression/85-callstring_Loc/07-call_in_call.c +++ b/tests/regression/85-callstring_Loc/07-call_in_call.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Interesting if nested recursions are handled properly #include diff --git a/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c index b730dfd3f8..2c3e7184cf 100644 --- a/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c +++ b/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed #include diff --git a/tests/regression/85-callstring_Loc/09-thread_creation.c b/tests/regression/85-callstring_Loc/09-thread_creation.c new file mode 100644 index 0000000000..2564c9adad --- /dev/null +++ b/tests/regression/85-callstring_Loc/09-thread_creation.c @@ -0,0 +1,88 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 3; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 2; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + int result = procedure(0); + __goblint_check(result == 8); + + result = procedure(8); + __goblint_check(result == 10); + return NULL; +} + +void *t_insens(void *arg) +{ + int result = procedure(9); + __goblint_check(result == 10); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + + // Creat the thread + pthread_create(&id, NULL, t_sens, NULL); + + // Creat the thread + pthread_create(&id2, NULL, t_insens, NULL); + return 0; +} From 834edd96c07f4459e0618dfb68e4babadec3dee2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 12 Jan 2024 12:14:10 +0100 Subject: [PATCH 076/128] added widen context Lifter config --- conf/svcomp81-widenContext.json | 146 ++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 conf/svcomp81-widenContext.json diff --git a/conf/svcomp81-widenContext.json b/conf/svcomp81-widenContext.json new file mode 100644 index 0000000000..b03f608518 --- /dev/null +++ b/conf/svcomp81-widenContext.json @@ -0,0 +1,146 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": true + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + + "ldv_malloc", + + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} From 6459e02dabb3aa1bb85d416430940294939b7a8a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 17 Jan 2024 15:21:24 +0100 Subject: [PATCH 077/128] added contextJoins, added testcases for contextJoins, added json for it --- conf/svcomp81-contextJoins.json | 147 ++++++++++++++++++ src/analyses/contextJoins.ml | 39 +++++ src/analyses/mCP.ml | 5 + src/goblint_lib.ml | 1 + .../81-contextJoins/01-loopCalling.c | 34 ++++ .../81-contextJoins/02-simpleExample.c | 34 ++++ .../81-contextJoins/03-loopCallingSens.c | 34 ++++ .../81-contextJoins/04-endless_loop.c | 24 +++ .../regression/81-contextJoins/05-ackermann.c | 26 ++++ 9 files changed, 344 insertions(+) create mode 100644 conf/svcomp81-contextJoins.json create mode 100644 src/analyses/contextJoins.ml create mode 100644 tests/regression/81-contextJoins/01-loopCalling.c create mode 100644 tests/regression/81-contextJoins/02-simpleExample.c create mode 100644 tests/regression/81-contextJoins/03-loopCallingSens.c create mode 100644 tests/regression/81-contextJoins/04-endless_loop.c create mode 100644 tests/regression/81-contextJoins/05-ackermann.c diff --git a/conf/svcomp81-contextJoins.json b/conf/svcomp81-contextJoins.json new file mode 100644 index 0000000000..5480687d99 --- /dev/null +++ b/conf/svcomp81-contextJoins.json @@ -0,0 +1,147 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "contextJoins" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + + "ldv_malloc", + + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} diff --git a/src/analyses/contextJoins.ml b/src/analyses/contextJoins.ml new file mode 100644 index 0000000000..3389d500a4 --- /dev/null +++ b/src/analyses/contextJoins.ml @@ -0,0 +1,39 @@ +open Analyses + + +module Spec : MCPSpec = +struct + include Analyses.IdentitySpec + + let name () = "contextJoins" + + module FundecSet = SetDomain.Make (CilType.Fundec) + module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) + module D = Lattice.Prod (FundecList) (FundecSet) + module C = D + module G = D + module V = EmptyV + let startstate v = D.bot () + let exitstate v = D.bot () + + let get_list l = match l with + | `Lifted l -> l + | `Bot -> [] + | `Top -> failwith "contextJoins Error: the value of the Flat List shouldn't be top!" + + let enter ctx r f args = + let (l, set) = ctx.local in + let list = get_list l in + let empty_set = FundecSet.is_empty set in + let ele_in_list = List.mem f list in + match empty_set, ele_in_list with + | false, _ -> [ctx.local, (l, FundecSet.add f set)] + | true, true -> [ctx.local, (l, FundecSet.add f set)] + | true, false -> [ctx.local, (`Lifted (f::list), set)] + + let combine_env ctx lval fexp f args fc au f_ask = + ctx.local + +end + +let _ = MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 862e004878..d4ed54768f 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -79,6 +79,8 @@ struct let callstring_list = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"] in let callstring_enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false callstring_list in let cont_callstring = filter (fun x -> not (mem x callstring_list)) xs in (*the contexts that are insensitive due to the callstring approach*) + let contextJoin_enabled = mem "contextJoins" xs in + let cont_contextJoins = filter (fun x -> x <> "contextJoins") xs in (*the contexts that are insensitive due to the contextJoins approach*) let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; @@ -86,6 +88,9 @@ struct if callstring_enabled then cont_inse := map' find_id cont_callstring else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + if contextJoin_enabled + then cont_inse := map' find_id cont_contextJoins + else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; check_deps !activated; activated := topo_sort_an !activated; activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index fe6572154b..2d7ced1107 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -151,6 +151,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination module CallstringAnalysis = CallstringAnalysis +module ContextJoins = ContextJoins module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/81-contextJoins/01-loopCalling.c b/tests/regression/81-contextJoins/01-loopCalling.c new file mode 100644 index 0000000000..9188bf0c0c --- /dev/null +++ b/tests/regression/81-contextJoins/01-loopCalling.c @@ -0,0 +1,34 @@ +// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// Basic example +#include + +int a; + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int f(int i) +{ + if (i > 0) + { + a = --i; + g(i); + } + return 0; +} + +int main(void) +{ + a = 20; + f(10); + __goblint_check(a == 0); // UNKNOWN +} diff --git a/tests/regression/81-contextJoins/02-simpleExample.c b/tests/regression/81-contextJoins/02-simpleExample.c new file mode 100644 index 0000000000..4d22b6c3f4 --- /dev/null +++ b/tests/regression/81-contextJoins/02-simpleExample.c @@ -0,0 +1,34 @@ +// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 10; +int a = 20; + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + a = --i; + g(i); + } + return 0; +} + +int f(int i) +{ + if (i > 0) + { + a = --i; + g(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); //UNKNOWN +} diff --git a/tests/regression/81-contextJoins/03-loopCallingSens.c b/tests/regression/81-contextJoins/03-loopCallingSens.c new file mode 100644 index 0000000000..a1bbe9fa06 --- /dev/null +++ b/tests/regression/81-contextJoins/03-loopCallingSens.c @@ -0,0 +1,34 @@ +// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// Basic example +#include + +int a; + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int f(int i) +{ + if (i > 0) + { + a = --i; + g(i); + } + return 0; +} + +int main(void) +{ + a = 20; + f(3); + __goblint_check(a == 0); +} diff --git a/tests/regression/81-contextJoins/04-endless_loop.c b/tests/regression/81-contextJoins/04-endless_loop.c new file mode 100644 index 0000000000..da763ee161 --- /dev/null +++ b/tests/regression/81-contextJoins/04-endless_loop.c @@ -0,0 +1,24 @@ +// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis +#include + +int num_iterat = 2; + +int main(void) +{ + if (num_iterat > 0) + { + num_iterat ++; + int res = main(); + __goblint_check(res == 5); //UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} diff --git a/tests/regression/81-contextJoins/05-ackermann.c b/tests/regression/81-contextJoins/05-ackermann.c new file mode 100644 index 0000000000..06fe1fcaef --- /dev/null +++ b/tests/regression/81-contextJoins/05-ackermann.c @@ -0,0 +1,26 @@ +// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +#include + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) { + ack (4,1); + __goblint_check(1); // reachable +} \ No newline at end of file From 37150f645b9e3df737b2bb239e2b566ed37b1b60 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 Jan 2024 17:09:27 +0100 Subject: [PATCH 078/128] renamed contextJoins to callstringTracking, improved implementation in mcp, callstringTracking, callstringAna, WEIRD: list1 test (which is unsound with callstringTracking) works out of no reason?! --- ....json => svcomp81-callstringTracking.json} | 2 +- src/analyses/callstringAnalysis.ml | 25 ++++---- src/analyses/callstringTracking.ml | 42 +++++++++++++ src/analyses/contextJoins.ml | 39 ------------ src/analyses/mCP.ml | 18 +++--- src/goblint_lib.ml | 2 +- .../01-loopCalling.c | 2 +- .../02-simpleExample.c | 2 +- .../03-loopCallingSens.c | 2 +- .../04-endless_loop.c | 2 +- .../05-ackermann.c | 2 +- .../81-callstringTracking/06-multipleCalls.c | 61 +++++++++++++++++++ .../81-callstringTracking/07-newCallInSet.c | 40 ++++++++++++ 13 files changed, 169 insertions(+), 70 deletions(-) rename conf/{svcomp81-contextJoins.json => svcomp81-callstringTracking.json} (99%) create mode 100644 src/analyses/callstringTracking.ml delete mode 100644 src/analyses/contextJoins.ml rename tests/regression/{81-contextJoins => 81-callstringTracking}/01-loopCalling.c (79%) rename tests/regression/{81-contextJoins => 81-callstringTracking}/02-simpleExample.c (80%) rename tests/regression/{81-contextJoins => 81-callstringTracking}/03-loopCallingSens.c (78%) rename tests/regression/{81-contextJoins => 81-callstringTracking}/04-endless_loop.c (82%) rename tests/regression/{81-contextJoins => 81-callstringTracking}/05-ackermann.c (80%) create mode 100644 tests/regression/81-callstringTracking/06-multipleCalls.c create mode 100644 tests/regression/81-callstringTracking/07-newCallInSet.c diff --git a/conf/svcomp81-contextJoins.json b/conf/svcomp81-callstringTracking.json similarity index 99% rename from conf/svcomp81-contextJoins.json rename to conf/svcomp81-callstringTracking.json index 5480687d99..ad0fb4acb3 100644 --- a/conf/svcomp81-contextJoins.json +++ b/conf/svcomp81-callstringTracking.json @@ -31,7 +31,7 @@ "region", "thread", "threadJoins", - "contextJoins" + "callstringTracking" ], "path_sens": [ "mutex", diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 8bc0291358..b3a67dfe45 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -42,9 +42,9 @@ struct module V = EmptyV module G = Lattice.Unit - (*let unlift x = match x with + let unlift x = match x with | `Lifted x -> x - | _ -> failwith "Callstring: Unlift error! The domain cannot be derived from Top or Bottom!"*) (* TODO*) + | _ -> failwith "Callstring: Unlift error! The domain cannot be derived from Top or Bottom!" (* TODO*) let name () = "callstring_"^ CT.stackTypeName let startstate v = `Lifted (QueueImmut.create ()) @@ -54,20 +54,17 @@ struct | `Lifted x -> x | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO*) - let enter ctx r f args = - let elem: CT.t option = CT.pushElem f ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack: C.t = CallStack.push (context f ctx.local) elem in - (*CT.printStack f (unlift ctx.local) new_stack;*) (* just for debugging purpose*) - [ctx.local, `Lifted new_stack] + let callee_state ctx f = + let elem = CT.pushElem f ctx in (*should be pushed on stack*) + let new_stack = CallStack.push (unlift ctx.local) elem in + (*CT.printStack f (unlift ctx.local) new_stack; *) (* just for debugging purpose*) + `Lifted new_stack + + let enter ctx r f args = [ctx.local, callee_state ctx f] - let combine_env ctx lval fexp f args fc au f_ask = - ctx.local + let combine_env ctx lval fexp f args fc au f_ask = ctx.local - let threadenter ctx ~multiple lval v args = - let elem: CT.t option = CT.pushElem (Cilfacade.find_varinfo_fundec v) ctx in (* a list of elements that should be pushed onto the stack*) - let new_stack: C.t = CallStack.push (context v ctx.local) elem in - (*CT.printStack (Cilfacade.find_varinfo_fundec v) (unlift ctx.local) new_stack; *)(* just for debugging purpose*) - [`Lifted new_stack] + let threadenter ctx ~multiple lval v args = [callee_state ctx (Cilfacade.find_varinfo_fundec v)] end diff --git a/src/analyses/callstringTracking.ml b/src/analyses/callstringTracking.ml new file mode 100644 index 0000000000..5824520f0e --- /dev/null +++ b/src/analyses/callstringTracking.ml @@ -0,0 +1,42 @@ +open Analyses + + +module Spec : MCPSpec = +struct + include Analyses.IdentitySpec + + let name () = "callstringTracking" + + module FundecSet = SetDomain.Make (CilType.Fundec) + module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) + module D = Lattice.Prod (FundecList) (FundecSet) + module C = D + module G = D + module V = EmptyV + let startstate v = D.bot () + let exitstate v = D.bot () + + let get_list l = match l with + | `Lifted l -> l + | `Bot -> [] + | `Top -> failwith "callstringTracking Error: the value of the Flat List shouldn't be top!" + + let should_add_to_set f list set = + if not (FundecSet.is_empty set) then true + else List.mem f (get_list list) + + let callee_state f ctx = + let (list, set) = ctx.local in + if should_add_to_set f list set + then (list, FundecSet.add f set) + else (`Lifted (f::(get_list list)), set) + + let enter ctx r f args = [ctx.local, callee_state f ctx] + + let threadenter ctx ~multiple lval v args = [callee_state (Cilfacade.find_varinfo_fundec v) ctx] + + let combine_env ctx lval fexp f args fc au f_ask = ctx.local + +end + +let _ = MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/contextJoins.ml b/src/analyses/contextJoins.ml deleted file mode 100644 index 3389d500a4..0000000000 --- a/src/analyses/contextJoins.ml +++ /dev/null @@ -1,39 +0,0 @@ -open Analyses - - -module Spec : MCPSpec = -struct - include Analyses.IdentitySpec - - let name () = "contextJoins" - - module FundecSet = SetDomain.Make (CilType.Fundec) - module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) - module D = Lattice.Prod (FundecList) (FundecSet) - module C = D - module G = D - module V = EmptyV - let startstate v = D.bot () - let exitstate v = D.bot () - - let get_list l = match l with - | `Lifted l -> l - | `Bot -> [] - | `Top -> failwith "contextJoins Error: the value of the Flat List shouldn't be top!" - - let enter ctx r f args = - let (l, set) = ctx.local in - let list = get_list l in - let empty_set = FundecSet.is_empty set in - let ele_in_list = List.mem f list in - match empty_set, ele_in_list with - | false, _ -> [ctx.local, (l, FundecSet.add f set)] - | true, true -> [ctx.local, (l, FundecSet.add f set)] - | true, false -> [ctx.local, (`Lifted (f::list), set)] - - let combine_env ctx lval fexp f args fc au f_ask = - ctx.local - -end - -let _ = MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index d4ed54768f..1a6a4919a6 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -65,6 +65,10 @@ struct let deps (x,_) = iter (check_dep x) @@ (find_spec x).dep in iter deps xs + let secific_cont_sens xs = (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) + let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "callstringTracking"] in (*TODO: what happens if all of them are enabled? Do we want that?*) + let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in + if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None (*returns a list of insensitive analyses*) type marshal = Obj.t list let init marshal = @@ -76,20 +80,14 @@ struct List.map f in let xs = get_string_list "ana.activated" in - let callstring_list = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"] in - let callstring_enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false callstring_list in - let cont_callstring = filter (fun x -> not (mem x callstring_list)) xs in (*the contexts that are insensitive due to the callstring approach*) - let contextJoin_enabled = mem "contextJoins" xs in - let cont_contextJoins = filter (fun x -> x <> "contextJoins") xs in (*the contexts that are insensitive due to the contextJoins approach*) + let special_inse = secific_cont_sens xs in + Printf.printf "activated: %s" (String.concat ";" xs); let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; path_sens := map' find_id @@ get_string_list "ana.path_sens"; - if callstring_enabled - then cont_inse := map' find_id cont_callstring - else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; - if contextJoin_enabled - then cont_inse := map' find_id cont_contextJoins + if Option.is_some special_inse (*checks if an analysis is enabled which requires context sensitivity for multiple analyses*) + then cont_inse := map' find_id (Option.get special_inse) else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; check_deps !activated; activated := topo_sort_an !activated; diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 2d7ced1107..d839c2a79d 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -151,7 +151,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination module CallstringAnalysis = CallstringAnalysis -module ContextJoins = ContextJoins +module CallstringTracking = CallstringTracking module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/81-contextJoins/01-loopCalling.c b/tests/regression/81-callstringTracking/01-loopCalling.c similarity index 79% rename from tests/regression/81-contextJoins/01-loopCalling.c rename to tests/regression/81-callstringTracking/01-loopCalling.c index 9188bf0c0c..fed4669bca 100644 --- a/tests/regression/81-contextJoins/01-loopCalling.c +++ b/tests/regression/81-callstringTracking/01-loopCalling.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-contextJoins/02-simpleExample.c b/tests/regression/81-callstringTracking/02-simpleExample.c similarity index 80% rename from tests/regression/81-contextJoins/02-simpleExample.c rename to tests/regression/81-callstringTracking/02-simpleExample.c index 4d22b6c3f4..7e5a73dc1d 100644 --- a/tests/regression/81-contextJoins/02-simpleExample.c +++ b/tests/regression/81-callstringTracking/02-simpleExample.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-contextJoins/03-loopCallingSens.c b/tests/regression/81-callstringTracking/03-loopCallingSens.c similarity index 78% rename from tests/regression/81-contextJoins/03-loopCallingSens.c rename to tests/regression/81-callstringTracking/03-loopCallingSens.c index a1bbe9fa06..08fa410e60 100644 --- a/tests/regression/81-contextJoins/03-loopCallingSens.c +++ b/tests/regression/81-callstringTracking/03-loopCallingSens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-contextJoins/04-endless_loop.c b/tests/regression/81-callstringTracking/04-endless_loop.c similarity index 82% rename from tests/regression/81-contextJoins/04-endless_loop.c rename to tests/regression/81-callstringTracking/04-endless_loop.c index da763ee161..489df8cee0 100644 --- a/tests/regression/81-contextJoins/04-endless_loop.c +++ b/tests/regression/81-callstringTracking/04-endless_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis #include diff --git a/tests/regression/81-contextJoins/05-ackermann.c b/tests/regression/81-callstringTracking/05-ackermann.c similarity index 80% rename from tests/regression/81-contextJoins/05-ackermann.c rename to tests/regression/81-callstringTracking/05-ackermann.c index 06fe1fcaef..03dffc46d0 100644 --- a/tests/regression/81-contextJoins/05-ackermann.c +++ b/tests/regression/81-callstringTracking/05-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" contextJoins --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set #include int ack(int n, int m) diff --git a/tests/regression/81-callstringTracking/06-multipleCalls.c b/tests/regression/81-callstringTracking/06-multipleCalls.c new file mode 100644 index 0000000000..21cdbb623e --- /dev/null +++ b/tests/regression/81-callstringTracking/06-multipleCalls.c @@ -0,0 +1,61 @@ +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int h(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = g(--i); + } + return res; +} + +int main(void) +{ + int res1 = f(num_iterat); + __goblint_check(res1 == 1); //UNKNOWN + int res2 = f(num_iterat); + __goblint_check(res2 == 1); //UNKNOWN + //int res3 = g(num_iterat); + int res4 = h(num_iterat); + __goblint_check(res4 == 1); + + //int result = res1 + res2 + res3 + res4 + res5; + //__goblint_check(result == 5); +} diff --git a/tests/regression/81-callstringTracking/07-newCallInSet.c b/tests/regression/81-callstringTracking/07-newCallInSet.c new file mode 100644 index 0000000000..d067faf65e --- /dev/null +++ b/tests/regression/81-callstringTracking/07-newCallInSet.c @@ -0,0 +1,40 @@ +// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 3; + +int f(int i) +{ + int res = 0; + if (i == 0) + { + res = 1; + } + if (i > 0) + { + res = f(--i); + } + return res; +} + +int g(int i) +{ + int res = 0; + if (i == 2) + { + res = f(--i); + } + if (i > 0) + { + res = g(--i); + } + return res; +} + + +int main(void) +{ + int res1 = g(num_iterat); + __goblint_check(res1 == 1); //UNKNOWN +} From 7f5c856d3c47078c9bf11063f893ae7e3cee4a33 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 Jan 2024 21:33:44 +0100 Subject: [PATCH 079/128] pulled from master; fixed indentation; deleted print in mcp --- src/analyses/callstringAnalysis.ml | 2 +- src/analyses/mCP.ml | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index b3a67dfe45..dcb3ea9665 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -59,7 +59,7 @@ struct let new_stack = CallStack.push (unlift ctx.local) elem in (*CT.printStack f (unlift ctx.local) new_stack; *) (* just for debugging purpose*) `Lifted new_stack - + let enter ctx r f args = [ctx.local, callee_state ctx f] let combine_env ctx lval fexp f args fc au f_ask = ctx.local diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 1a6a4919a6..e947a0ceaf 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -65,7 +65,7 @@ struct let deps (x,_) = iter (check_dep x) @@ (find_spec x).dep in iter deps xs - let secific_cont_sens xs = (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) + let specific_cont_sens xs = (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "callstringTracking"] in (*TODO: what happens if all of them are enabled? Do we want that?*) let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None (*returns a list of insensitive analyses*) @@ -80,8 +80,7 @@ struct List.map f in let xs = get_string_list "ana.activated" in - let special_inse = secific_cont_sens xs in - Printf.printf "activated: %s" (String.concat ";" xs); + let special_inse = specific_cont_sens xs in let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; From bbe97b5868aebeeabc87917554aa3e9a27e50822 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 25 Jan 2024 07:57:44 +0100 Subject: [PATCH 080/128] fixed error in relationAnalysis: assign in combine_env instead of substitute; deletec dec_ctx gas since it is no longer needed --- src/analyses/apron/relationAnalysis.apron.ml | 2 +- src/framework/constraints.ml | 32 ++++++++------------ 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index e572755930..1afe38ed2c 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -398,7 +398,7 @@ struct let new_fun_rel = List.fold_left (fun new_fun_rel (var, e) -> assign_from_globals_wrapper ask ctx.global {st with rel = new_fun_rel} e (fun rel' e' -> (* not an assign, but still works? *) - RD.substitute_exp rel' var e' (no_overflow ask e) + RD.assign_exp rel' var e' (no_overflow ask e) ) ) new_fun_rel arg_substitutes in diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 174f28aef9..1ebb3c2a61 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -544,38 +544,30 @@ struct if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = - (* D.t -> S.D.t *) - let ctx' = {ctx with local = fst ctx.local - ; split = (fun d es -> ctx.split (d, cg_val ctx) es)} in - (* C.t -> S.C.t *) if (cg_val ctx <= 0) - then {ctx' with context = (fun () -> ctx_failwith "no context (contextGas = 0)")} - else {ctx' with context = (fun () -> Option.get (fst (ctx'.context ())))} - - let dec_context_gas (ctx:(D.t,G.t,C.t,V.t) ctx): (D.t,G.t,C.t,V.t)ctx = - if (cg_val ctx <= 1) - then {ctx with context = (fun () -> (None, 0) ) (* context insensitive *) - ; local = (fst ctx.local, 0)} - else {ctx with context = (fun () -> (fst (ctx.context ()), cg_val ctx - 1)) (* context sensitive *) - ; local = (fst ctx.local, cg_val ctx - 1)} - + then {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, cg_val ctx) es) + ; context = (fun () -> ctx_failwith "no context (contextGas = 0)")} + else {ctx with local = fst ctx.local + ; split = (fun d es -> ctx.split (d, cg_val ctx) es) + ; context = (fun () -> Option.get (fst (ctx.context ())))} + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) let enter ctx r f args = - let ctx_dec = dec_context_gas ctx in (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx_dec)) in + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx - 1)) in liftmap_tup (S.enter (conv ctx) r f args) - let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f - let threadenter ctx ~multiple lval f args = - let ctx_dec = dec_context_gas ctx in (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) - liftmap (S.threadenter (conv ctx) ~multiple lval f args) ctx_dec + let liftmap f = List.map (fun (x) -> (x, cg_val ctx - 1)) f in + liftmap (S.threadenter (conv ctx) ~multiple lval f args) + + let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q From b7a29f8158393eccb72008a1ca9f3080e0e681b6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 10:13:50 +0100 Subject: [PATCH 081/128] restored relationAnalysis (apron), disabled path sensitivity for callstring anas, context gas value is now limited to a minimum of 0 --- src/analyses/apron/relationAnalysis.apron.ml | 2 +- src/analyses/mCP.ml | 7 ++++--- src/framework/constraints.ml | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 1afe38ed2c..e572755930 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -398,7 +398,7 @@ struct let new_fun_rel = List.fold_left (fun new_fun_rel (var, e) -> assign_from_globals_wrapper ask ctx.global {st with rel = new_fun_rel} e (fun rel' e' -> (* not an assign, but still works? *) - RD.assign_exp rel' var e' (no_overflow ask e) + RD.substitute_exp rel' var e' (no_overflow ask e) ) ) new_fun_rel arg_substitutes in diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index e947a0ceaf..87a2fd6d76 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -84,10 +84,11 @@ struct let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; - path_sens := map' find_id @@ get_string_list "ana.path_sens"; if Option.is_some special_inse (*checks if an analysis is enabled which requires context sensitivity for multiple analyses*) - then cont_inse := map' find_id (Option.get special_inse) - else cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + then (cont_inse := map' find_id (Option.get special_inse); + path_sens := []) + else (cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + path_sens := map' find_id @@ get_string_list "ana.path_sens"); check_deps !activated; activated := topo_sort_an !activated; activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1ebb3c2a61..fef833ff75 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -551,7 +551,7 @@ struct else {ctx with local = fst ctx.local ; split = (fun d es -> ctx.split (d, cg_val ctx) es) ; context = (fun () -> Option.get (fst (ctx.context ())))} - + (*let rec showExprList args = (*TODO: delete, just here for printing*) match args with | [] -> " " @@ -559,12 +559,12 @@ struct let enter ctx r f args = (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, cg_val ctx - 1)) in + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in liftmap_tup (S.enter (conv ctx) r f args) let threadenter ctx ~multiple lval f args = (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) - let liftmap f = List.map (fun (x) -> (x, cg_val ctx - 1)) f in + let liftmap f = List.map (fun (x) -> (x, max 0 (cg_val ctx - 1))) f in liftmap (S.threadenter (conv ctx) ~multiple lval f args) let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f From 850e118618a4f9a41db66f73d550079bf068a4ac Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 12:08:55 +0100 Subject: [PATCH 082/128] made everything ready for pull request: deleted prints, deleted unneccessary formatting; renamed svcomp files; probably there will still be some changes in the testcases! --- .devcontainer/devcontainer.json | 4 +- ...ec.json => svcomp24-callstringFundec.json} | 0 ...ngLoc.json => svcomp24-callstringLoc.json} | 0 ...Stmt.json => svcomp24-callstringStmt.json} | 0 ....json => svcomp24-callstringTracking.json} | 0 ...xt_gas.json => svcomp24-contextGas10.json} | 0 ..._val18.json => svcomp24-contextGas18.json} | 0 ..._val30.json => svcomp24-contextGas30.json} | 0 ...ontext.json => svcomp24-widenContext.json} | 0 package.json | 6 - src/analyses/callstringAnalysis.ml | 59 +- src/analyses/callstringTracking.ml | 8 +- src/analyses/mCP.ml | 21 +- src/autoTune.ml | 2 +- src/common/util/queueImmut.ml | 12 +- src/config/options.schema.json | 683 ++++++++---------- src/framework/constraints.ml | 21 +- src/framework/control.ml | 122 ++-- .../80-context_gas/01-basic_tests.c | 8 +- .../02-multiple_function_chain_tests.c | 25 +- .../80-context_gas/03-contextGas0.c | 8 +- .../80-context_gas/04-contextGasNeg.c | 8 +- .../regression/80-context_gas/05-ackermann.c | 5 +- .../80-context_gas/07-loop_unrolling.c | 20 +- ...ursion_sens.c => 08-main_recursion_sens.c} | 0 .../80-context_gas/09-main_recursion_insens.c | 2 +- .../{12-endless_loop.c => 10-endless_loop.c} | 4 +- .../81-callstringTracking/02-simpleExample.c | 2 +- .../81-callstringTracking/04-endless_loop.c | 4 +- .../81-callstringTracking/05-ackermann.c | 5 +- .../81-callstringTracking/06-multipleCalls.c | 10 +- .../81-callstringTracking/07-newCallInSet.c | 3 +- .../82-callstring_Fundec/01-simple_rec_sens.c | 2 +- .../02-multiple_function_chain_tests.c | 21 +- .../03-multiple_rec_sens.c | 2 +- .../04-multiple_rec_ins.c | 4 +- .../05-function_chain_sens.c | 4 +- .../06-function_chain_ins.c | 4 +- .../07-call_in_call_sens.c | 2 +- .../82-callstring_Fundec/08-ackermann.c | 5 +- .../09-circle_call_and_loops.c | 12 +- .../82-callstring_Fundec/12-loop_unrolling.c | 2 +- .../82-callstring_Fundec/13-thread_creation.c | 2 +- .../14-thread_creation_problem.c | 6 +- .../82-callstring_Fundec/15-simple_rec_ins.c | 2 +- .../83-callstring_Stmt/01-simple_rec_sens.c | 2 +- .../83-callstring_Stmt/02-simple_rec_ins.c | 2 +- .../83-callstring_Stmt/03-multiple_rec_sens.c | 2 +- .../83-callstring_Stmt/04-multiple_rec_ins.c | 4 +- .../05-function_chain_sens.c | 4 +- .../06-function_chain_ins.c | 4 +- .../83-callstring_Stmt/07-call_in_call.c | 2 +- .../83-callstring_Stmt/09-thread_creation.c | 2 +- .../01-simple_rec_sens.c | 2 +- .../02-simple_rec_ins.c | 2 +- .../03-multiple_rec_sens.c | 2 +- .../04-multiple_rec_ins.c | 4 +- .../05-function_chain_sens.c | 4 +- .../06-function_chain_ins.c | 4 +- .../07-call_in_call.c | 2 +- .../08-circle_call_and_big_loop.c | 0 .../09-thread_creation.c | 2 +- .../84-callstring_both/01-simple_rec_sens.c | 22 - .../84-callstring_both/02-simple_rec_ins.c | 22 - .../84-callstring_both/03-multiple_rec_sens.c | 59 -- .../84-callstring_both/04-multiple_rec_ins.c | 59 -- 66 files changed, 486 insertions(+), 830 deletions(-) rename conf/{svcomp82-callstringFundec.json => svcomp24-callstringFundec.json} (100%) rename conf/{svcomp85-callstringLoc.json => svcomp24-callstringLoc.json} (100%) rename conf/{svcomp83-callstringStmt.json => svcomp24-callstringStmt.json} (100%) rename conf/{svcomp81-callstringTracking.json => svcomp24-callstringTracking.json} (100%) rename conf/{svcomp80-context_gas.json => svcomp24-contextGas10.json} (100%) rename conf/{svcomp80-context_gas_val18.json => svcomp24-contextGas18.json} (100%) rename conf/{svcomp80-context_gas_val30.json => svcomp24-contextGas30.json} (100%) rename conf/{svcomp81-widenContext.json => svcomp24-widenContext.json} (100%) delete mode 100644 package.json rename tests/regression/80-context_gas/{10-main_recursion_sens.c => 08-main_recursion_sens.c} (100%) rename tests/regression/80-context_gas/{12-endless_loop.c => 10-endless_loop.c} (86%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/01-simple_rec_sens.c (91%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/02-simple_rec_ins.c (88%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/03-multiple_rec_sens.c (99%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/04-multiple_rec_ins.c (94%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/05-function_chain_sens.c (94%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/06-function_chain_ins.c (93%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/07-call_in_call.c (97%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/08-circle_call_and_big_loop.c (100%) rename tests/regression/{85-callstring_Loc => 84-callstring_Loc}/09-thread_creation.c (97%) delete mode 100644 tests/regression/84-callstring_both/01-simple_rec_sens.c delete mode 100644 tests/regression/84-callstring_both/02-simple_rec_ins.c delete mode 100644 tests/regression/84-callstring_both/03-multiple_rec_sens.c delete mode 100644 tests/regression/84-callstring_both/04-multiple_rec_ins.c diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5d0336ccf9..c4fc736697 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,9 +14,7 @@ "extensions": [ "ocamllabs.ocaml-platform", - "hackwaly.ocamlearlybird", - "zepalmer.ocaml-indentation", - "AllanBlanchard.ocp-indent" + "hackwaly.ocamlearlybird" ], "settings": {}, diff --git a/conf/svcomp82-callstringFundec.json b/conf/svcomp24-callstringFundec.json similarity index 100% rename from conf/svcomp82-callstringFundec.json rename to conf/svcomp24-callstringFundec.json diff --git a/conf/svcomp85-callstringLoc.json b/conf/svcomp24-callstringLoc.json similarity index 100% rename from conf/svcomp85-callstringLoc.json rename to conf/svcomp24-callstringLoc.json diff --git a/conf/svcomp83-callstringStmt.json b/conf/svcomp24-callstringStmt.json similarity index 100% rename from conf/svcomp83-callstringStmt.json rename to conf/svcomp24-callstringStmt.json diff --git a/conf/svcomp81-callstringTracking.json b/conf/svcomp24-callstringTracking.json similarity index 100% rename from conf/svcomp81-callstringTracking.json rename to conf/svcomp24-callstringTracking.json diff --git a/conf/svcomp80-context_gas.json b/conf/svcomp24-contextGas10.json similarity index 100% rename from conf/svcomp80-context_gas.json rename to conf/svcomp24-contextGas10.json diff --git a/conf/svcomp80-context_gas_val18.json b/conf/svcomp24-contextGas18.json similarity index 100% rename from conf/svcomp80-context_gas_val18.json rename to conf/svcomp24-contextGas18.json diff --git a/conf/svcomp80-context_gas_val30.json b/conf/svcomp24-contextGas30.json similarity index 100% rename from conf/svcomp80-context_gas_val30.json rename to conf/svcomp24-contextGas30.json diff --git a/conf/svcomp81-widenContext.json b/conf/svcomp24-widenContext.json similarity index 100% rename from conf/svcomp81-widenContext.json rename to conf/svcomp24-widenContext.json diff --git a/package.json b/package.json deleted file mode 100644 index 8d7a4d3861..0000000000 --- a/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dependencies": { - "resolve-url": "^0.2.1", - "urix": "^0.1.0" - } -} diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index dcb3ea9665..cdfeb5f6af 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -1,20 +1,17 @@ open Analyses -open Printf open GoblintCil open GobConfig -(* Specifies the type of the callstack elements for the CallstringLifter*) +(* Specifies the type of the callstack elements for the callstring analysis*) module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns a list of elements that should be pushed to the Callstack *) - val printStack: fundec -> t QueueImmut.t -> t QueueImmut.t -> unit (* a helper function to print the callstack *) + val pushElem: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an elements that should be pushed to the Callstack *) end -(** Lifts a [Spec] to analyse with the k-callsting approach. For this the last k callstack elements are used as context - With the CT argument it is possible to specify the type of the Callstack elements -*) +(** Analysis with the k-callsting approach, which uses the last k callstack elements as context. + With the CT argument it is possible to specify the type of the callstack elements*) module Spec (CT:Callstack_Type) : MCPSpec = struct include Analyses.IdentitySpec @@ -29,12 +26,11 @@ struct | None -> stack | Some e -> let new_stack = QueueImmut.push e stack in (* pushes new element to stack*) - (* remove elements from stack, till the depth k is guaranteed*) + (* removes element from stack, if stack was filled with k elements*) match (QueueImmut.length new_stack - depth) with | x when x <= 0 -> new_stack | 1 -> QueueImmut.dequeue new_stack | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" - end module D = Lattice.Flat (CallStack) @@ -42,22 +38,17 @@ struct module V = EmptyV module G = Lattice.Unit - let unlift x = match x with - | `Lifted x -> x - | _ -> failwith "Callstring: Unlift error! The domain cannot be derived from Top or Bottom!" (* TODO*) - let name () = "callstring_"^ CT.stackTypeName let startstate v = `Lifted (QueueImmut.create ()) - let exitstate v = `Lifted (QueueImmut.create ()) + let exitstate v = `Lifted (QueueImmut.create ()) (*TODO: should I use startstate here? Does this make a difference*) let context fd x = match x with | `Lifted x -> x - | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO*) + | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO: is there a possibility???*) let callee_state ctx f = - let elem = CT.pushElem f ctx in (*should be pushed on stack*) - let new_stack = CallStack.push (unlift ctx.local) elem in - (*CT.printStack f (unlift ctx.local) new_stack; *) (* just for debugging purpose*) + let elem = CT.pushElem f ctx in + let new_stack = CallStack.push (context f ctx.local) elem in (*TODO: is it ok to use context here??? *) `Lifted new_stack let enter ctx r f args = [ctx.local, callee_state ctx f] @@ -67,56 +58,26 @@ struct let threadenter ctx ~multiple lval v args = [callee_state ctx (Cilfacade.find_varinfo_fundec v)] end - module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" let pushElem f ctx = Some f - - let printStack f listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listA; - printf "\nList neu: "; - QueueImmut.iter (fun x -> printf "%s; " (CilType.Fundec.show x)) listB; - printf "\n\n" - end - module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" let pushElem f ctx = - match ctx.prev_node with (* TODO: Why do I need to use prev_node???*) + match ctx.prev_node with | Statement stmt -> Some stmt | _ -> None (* first statement is filtered*) - - let printStack f listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listA; - printf "\nList neu: "; - QueueImmut.iter (fun x -> printf "%s; " (CilType.Stmt.show x)) listB; - printf "\n\n" - end - module Location:Callstack_Type = struct include CilType.Location let stackTypeName = "loc" let pushElem f ctx = Some !Goblint_tracing.current_loc - - let printStack f listA listB = - printf "fundec: %s\n" (CilType.Fundec.show f); - printf "List alt: "; - QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listA; - printf "\nList neu: "; - QueueImmut.iter (fun x -> printf "%s;\n " (CilType.Location.show x)) listB; - printf "\n\n" - end (* Lifters for the Callstring approach with different Callstack element types*) diff --git a/src/analyses/callstringTracking.ml b/src/analyses/callstringTracking.ml index 5824520f0e..a74e9660d3 100644 --- a/src/analyses/callstringTracking.ml +++ b/src/analyses/callstringTracking.ml @@ -1,6 +1,5 @@ open Analyses - module Spec : MCPSpec = struct include Analyses.IdentitySpec @@ -21,13 +20,9 @@ struct | `Bot -> [] | `Top -> failwith "callstringTracking Error: the value of the Flat List shouldn't be top!" - let should_add_to_set f list set = - if not (FundecSet.is_empty set) then true - else List.mem f (get_list list) - let callee_state f ctx = let (list, set) = ctx.local in - if should_add_to_set f list set + if (not(FundecSet.is_empty set)) || List.mem f (get_list list) then (list, FundecSet.add f set) else (`Lifted (f::(get_list list)), set) @@ -36,7 +31,6 @@ struct let threadenter ctx ~multiple lval v args = [callee_state (Cilfacade.find_varinfo_fundec v) ctx] let combine_env ctx lval fexp f args fc au f_ask = ctx.local - end let _ = MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 87a2fd6d76..613677500a 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -65,10 +65,12 @@ struct let deps (x,_) = iter (check_dep x) @@ (find_spec x).dep in iter deps xs - let specific_cont_sens xs = (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) - let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "callstringTracking"] in (*TODO: what happens if all of them are enabled? Do we want that?*) + let specific_cont_sens xs = + (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) + let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "callstringTracking"] in let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in - if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None (*returns a list of insensitive analyses*) + (*returns the edited list of insensitive analyses if enabled*) + if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None type marshal = Obj.t list let init marshal = @@ -84,7 +86,8 @@ struct let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; - if Option.is_some special_inse (*checks if an analysis is enabled which requires context sensitivity for multiple analyses*) + (*checks if an analysis is enabled with special handled context sensitivity*) + if Option.is_some special_inse then (cont_inse := map' find_id (Option.get special_inse); path_sens := []) else (cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; @@ -188,13 +191,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/autoTune.ml b/src/autoTune.ml index b2acac055e..3cda36a302 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -242,7 +242,7 @@ let focusOnMemSafetySpecification () = let focusOnTermination (spec: Svcomp.Specification.t) = match spec with | Termination -> - let terminationAnas = ["termination"; "apron"; "threadflag"] in + let terminationAnas = ["termination"; "threadflag"; "apron"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; set_string "sem.int.signed_overflow" "assume_none"; diff --git a/src/common/util/queueImmut.ml b/src/common/util/queueImmut.ml index de5743ed77..308f3aba77 100644 --- a/src/common/util/queueImmut.ml +++ b/src/common/util/queueImmut.ml @@ -88,17 +88,7 @@ let dequeue = function (* returns the remaining queue after removing one element | x::xs -> Queue(xs, [])) | Queue (x::q_first, q_last) -> Queue (q_first, q_last) -(** [dequeue_tup q] removes the first element in queue [q] - and returns it with the remaining queue in a tuple. - In case of an empty queue it raises {!Empty}.*) -let dequeue_tup = function (* returns the removed element and the remaining queue*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> raise Empty - | x::xs -> (x , Queue(xs, []))) - | Queue (x::q_first, q_last) -> (x, Queue (q_first, q_last)) - -(** [dequeue_tup q] removes the first element in queue [q] +(** [dequeue_tup_opt q] removes the first element in queue [q] and returns it with the remaining queue in a tuple. In case of an empty queue the first element is [None]*) let dequeue_tup_opt = function (* returns the removed element and the remaining queue*) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 0beb7c6ecd..adadd9dcdb 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -31,7 +31,8 @@ }, "verify": { "title": "verify", - "description": "Verify that the solver reached a post-fixpoint. Beware that disabling this also disables output of warnings since post-processing of the results is done in the verification phase!", + "description": + "Verify that the solver reached a post-fixpoint. Beware that disabling this also disables output of warnings since post-processing of the results is done in the verification phase!", "type": "boolean", "default": true }, @@ -39,34 +40,27 @@ "title": "mainfun", "description": "Sets the name of the main functions.", "type": "array", - "items": { - "type": "string" - }, - "default": [ - "main" - ] + "items": { "type": "string" }, + "default": [ "main" ] }, "exitfun": { "title": "exitfun", "description": "Sets the name of the cleanup functions.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "otherfun": { "title": "otherfun", "description": "Sets the name of other functions.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "allglobs": { "title": "allglobs", - "description": "Prints access information about all globals, not just races.", + "description": + "Prints access information about all globals, not just races.", "type": "boolean", "default": false }, @@ -84,16 +78,10 @@ }, "result": { "title": "result", - "description": "Result style: none, fast_xml, json, pretty, json-messages, sarif.", + "description": + "Result style: none, fast_xml, json, pretty, json-messages, sarif.", "type": "string", - "enum": [ - "none", - "fast_xml", - "json", - "pretty", - "json-messages", - "sarif" - ], + "enum": ["none", "fast_xml", "json", "pretty", "json-messages", "sarif"], "default": "none" }, "solver": { @@ -110,7 +98,8 @@ }, "allfuns": { "title": "allfuns", - "description": "Analyzes all the functions (not just beginning from main). This requires exp.earlyglobs!", + "description": + "Analyzes all the functions (not just beginning from main). This requires exp.earlyglobs!", "type": "boolean", "default": false }, @@ -122,13 +111,10 @@ }, "colors": { "title": "colors", - "description": "Colored output (via ANSI escape codes). 'auto': enabled if stdout is a terminal (instead of a pipe); 'always', 'never'.", + "description": + "Colored output (via ANSI escape codes). 'auto': enabled if stdout is a terminal (instead of a pipe); 'always', 'never'.", "type": "string", - "enum": [ - "auto", - "always", - "never" - ], + "enum": ["auto", "always", "never"], "default": "auto" }, "g2html": { @@ -139,7 +125,8 @@ }, "save_run": { "title": "save_run", - "description": "Save the result of the solver, the current configuration and meta-data about the run to this directory (if set). The data can then be loaded (without solving again) to do post-processing like generating output in a different format or comparing results.", + "description": + "Save the result of the solver, the current configuration and meta-data about the run to this directory (if set). The data can then be loaded (without solving again) to do post-processing like generating output in a different format or comparing results.", "type": "string", "default": "" }, @@ -151,27 +138,24 @@ }, "compare_runs": { "title": "compare_runs", - "description": "Load these saved runs and compare the results. Note that currently only two runs can be compared!", + "description": + "Load these saved runs and compare the results. Note that currently only two runs can be compared!", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "warn_at": { "title": "warn_at", - "description": "When to output warnings. Values: 'post' (default): after solving; 'never': no warnings; 'early': for debugging - outputs warnings already while solving (may lead to spurious warnings/asserts that would disappear after narrowing).", + "description": + "When to output warnings. Values: 'post' (default): after solving; 'never': no warnings; 'early': for debugging - outputs warnings already while solving (may lead to spurious warnings/asserts that would disappear after narrowing).", "type": "string", - "enum": [ - "post", - "never", - "early" - ], + "enum": ["post", "never", "early"], "default": "post" }, "gobview": { "title": "gobview", - "description": "Include additional information for GobView (e.g., the Goblint warning messages) in the directory specified by 'save_run'.", + "description": + "Include additional information for GobView (e.g., the Goblint warning messages) in the directory specified by 'save_run'.", "type": "boolean", "default": false }, @@ -200,7 +184,8 @@ }, "keep": { "title": "pre.keep", - "description": "Keep the intermediate output of running the C preprocessor.", + "description": + "Keep the intermediate output of running the C preprocessor.", "type": "boolean", "default": false }, @@ -214,27 +199,21 @@ "title": "pre.includes", "description": "List of directories to include.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "kernel_includes": { "title": "pre.kernel_includes", "description": "List of kernel directories to include.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "custom_includes": { "title": "pre.custom_includes", "description": "List of custom directories to include.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "kernel-root": { @@ -247,9 +226,7 @@ "title": "pre.cppflags", "description": "Pre-processing parameters.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "compdb": { @@ -258,7 +235,8 @@ "properties": { "original-path": { "title": "pre.compdb.original-path", - "description": "Original absolute path of Compilation Database. Used to reroot all absolute paths in there if moved, e.g. in container mounts.", + "description": + "Original absolute path of Compilation Database. Used to reroot all absolute paths in there if moved, e.g. in container mounts.", "type": "string", "default": "" }, @@ -303,11 +281,7 @@ "type": "string", "description": "Specify the c standard used for parsing.", "default": "c99", - "enum": [ - "c90", - "c99", - "c11" - ] + "enum": ["c90", "c99", "c11"] }, "gnu89inline": { "title": "cil.gnu89inline", @@ -339,10 +313,7 @@ "title": "server.mode", "description": "Server transport mode", "type": "string", - "enum": [ - "stdio", - "unix" - ], + "enum": ["stdio", "unix"], "default": "stdio" }, "unix-socket": { @@ -369,22 +340,10 @@ "title": "ana.activated", "description": "Lists of activated analyses.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [ - "expRelation", - "base", - "threadid", - "threadflag", - "threadreturn", - "escape", - "mutexEvents", - "mutex", - "access", - "race", - "mallocWrapper", - "mhp", + "expRelation", "base", "threadid", "threadflag", "threadreturn", + "escape", "mutexEvents", "mutex", "access", "race", "mallocWrapper", "mhp", "assert" ] }, @@ -392,31 +351,17 @@ "title": "ana.path_sens", "description": "List of path-sensitive analyses", "type": "array", - "items": { - "type": "string" - }, - "default": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak" - ] + "items": { "type": "string" }, + "default": [ "mutex", "malloc_null", "uninit", "expsplit","activeSetjmp","memLeak" ] }, "ctx_insens": { "title": "ana.ctx_insens", "description": "List of context-insensitive analyses", "type": "array", - "items": { - "type": "string" - }, - "default": [ - "stack_loc", - "stack_trace_set" - ] + "items": { "type": "string" }, + "default": [ "stack_loc", "stack_trace_set" ] }, - "setjmp": { + "setjmp" : { "title": "ana.setjmp", "description": "Setjmp/Longjmp analysis", "type": "object", @@ -425,11 +370,7 @@ "title": "ana.setjmp.split", "description": "Split returns of setjmp", "type": "string", - "enum": [ - "none", - "coarse", - "precise" - ], + "enum": ["none", "coarse", "precise"], "default": "precise" } }, @@ -441,13 +382,15 @@ "properties": { "def_exc": { "title": "ana.int.def_exc", - "description": "Use IntDomain.DefExc: definite value/exclusion set.", + "description": + "Use IntDomain.DefExc: definite value/exclusion set.", "type": "boolean", "default": true }, "interval": { "title": "ana.int.interval", - "description": "Use IntDomain.Interval32: (Z.t * Z.t) option.", + "description": + "Use IntDomain.Interval32: (Z.t * Z.t) option.", "type": "boolean", "default": false }, @@ -459,30 +402,30 @@ }, "enums": { "title": "ana.int.enums", - "description": "Use IntDomain.Enums: Inclusion/Exclusion sets. Go to top on arithmetic operations (except for some easy cases, e.g. multiplication with 0). Joins on widen, i.e. precise integers as long as not derived from arithmetic expressions.", + "description": + "Use IntDomain.Enums: Inclusion/Exclusion sets. Go to top on arithmetic operations (except for some easy cases, e.g. multiplication with 0). Joins on widen, i.e. precise integers as long as not derived from arithmetic expressions.", "type": "boolean", "default": false }, "congruence": { "title": "ana.int.congruence", - "description": "Use IntDomain.Congruence: (c, m) option, meaning congruent to c modulo m", + "description": + "Use IntDomain.Congruence: (c, m) option, meaning congruent to c modulo m", "type": "boolean", "default": false }, "refinement": { "title": "ana.int.refinement", - "description": "Use mutual refinement of integer domains. Either 'never', 'once' or 'fixpoint'. Counterintuitively, may reduce precision unless ana.int.interval_narrow_by_meet is also enabled.", + "description": + "Use mutual refinement of integer domains. Either 'never', 'once' or 'fixpoint'. Counterintuitively, may reduce precision unless ana.int.interval_narrow_by_meet is also enabled.", "type": "string", - "enum": [ - "never", - "once", - "fixpoint" - ], + "enum": ["never", "once", "fixpoint"], "default": "never" }, "def_exc_widen_by_join": { "title": "ana.int.def_exc_widen_by_join", - "description": "Perform def_exc widening by joins. Gives threshold-widening like behavior, with thresholds given by the ranges of different integer types.", + "description": + "Perform def_exc widening by joins. Gives threshold-widening like behavior, with thresholds given by the ranges of different integer types.", "type": "boolean", "default": false }, @@ -494,18 +437,17 @@ }, "interval_threshold_widening": { "title": "ana.int.interval_threshold_widening", - "description": "Use constants appearing in program as threshold for widening", + "description": + "Use constants appearing in program as threshold for widening", "type": "boolean", "default": false }, "interval_threshold_widening_constants": { "title": "ana.int.interval_threshold_widening_constants", - "description": "Which constants in the program should be considered as threshold constants (all/comparisons)", + "description": + "Which constants in the program should be considered as threshold constants (all/comparisons)", "type": "string", - "enum": [ - "all", - "comparisons" - ], + "enum": ["all", "comparisons"], "default": "all" } }, @@ -517,7 +459,8 @@ "properties": { "interval": { "title": "ana.float.interval", - "description": "Use FloatDomain: (float * float) option.", + "description": + "Use FloatDomain: (float * float) option.", "type": "boolean", "default": false } @@ -530,7 +473,8 @@ "properties": { "debug": { "title": "ana.pml.debug", - "description": "Insert extra assertions into Promela code for debugging.", + "description": + "Insert extra assertions into Promela code for debugging.", "type": "boolean", "default": true } @@ -543,13 +487,15 @@ "properties": { "hashcons": { "title": "ana.opt.hashcons", - "description": "Should we try to save memory and speed up equality by hashconsing?", + "description": + "Should we try to save memory and speed up equality by hashconsing?", "type": "boolean", "default": true }, "equal": { "title": "ana.opt.equal", - "description": "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", + "description": + "First try physical equality (==) before {D,G,C}.equal (only done if hashcons is disabled since it basically does the same via its tags).", "type": "boolean", "default": true } @@ -635,7 +581,8 @@ }, "wp": { "title": "ana.wp", - "description": "Weakest precondition feasibility analysis for SV-COMP violations", + "description": + "Weakest precondition feasibility analysis for SV-COMP violations", "type": "boolean", "default": false }, @@ -667,13 +614,15 @@ }, "interval": { "title": "ana.base.context.interval", - "description": "Integer values of the Interval domain in function contexts.", + "description": + "Integer values of the Interval domain in function contexts.", "type": "boolean", "default": true }, "interval_set": { "title": "ana.base.context.interval_set", - "description": "Integer values of the IntervalSet domain in function contexts.", + "description": + "Integer values of the IntervalSet domain in function contexts.", "type": "boolean", "default": true } @@ -688,11 +637,7 @@ "title": "ana.base.strings.domain", "description": "Domain for string literals.", "type": "string", - "enum": [ - "unit", - "flat", - "disjoint" - ], + "enum": ["unit", "flat", "disjoint"], "default": "flat" } }, @@ -704,42 +649,39 @@ "properties": { "keep-expr": { "title": "ana.base.partition-arrays.keep-expr", - "description": "When using the partitioning which expression should be used for partitioning ('first', 'last')", + "description": + "When using the partitioning which expression should be used for partitioning ('first', 'last')", "type": "string", - "enum": [ - "first", - "last" - ], + "enum": ["first", "last"], "default": "first" }, "partition-by-const-on-return": { "title": "ana.base.partition-arrays.partition-by-const-on-return", - "description": "When using the partitioning should arrays be considered partitioned according to a constant if a var in the expression used for partitioning goes out of scope?", + "description": + "When using the partitioning should arrays be considered partitioned according to a constant if a var in the expression used for partitioning goes out of scope?", "type": "boolean", "default": false }, "smart-join": { "title": "ana.base.partition-arrays.smart-join", - "description": "When using the partitioning should the join of two arrays partitioned according to different expressions be partitioned as well if possible? If keep-expr is 'last' this behavior is enabled regardless of the flag value. Caution: Not always advantageous.", + "description": + "When using the partitioning should the join of two arrays partitioned according to different expressions be partitioned as well if possible? If keep-expr is 'last' this behavior is enabled regardless of the flag value. Caution: Not always advantageous.", "type": "boolean", "default": false } }, "additionalProperties": false }, - "arrays": { + "arrays":{ "title": "ana.base.arrays", "type": "object", "properties": { "domain": { "title": "ana.base.arrays.domain", - "description": "The domain that should be used for arrays. When employing the partition array domain, make sure to enable the expRelation analysis as well. When employing the unrolling array domain, make sure to set the ana.base.arrays.unrolling-factor >0.", + "description": + "The domain that should be used for arrays. When employing the partition array domain, make sure to enable the expRelation analysis as well. When employing the unrolling array domain, make sure to set the ana.base.arrays.unrolling-factor >0.", "type": "string", - "enum": [ - "trivial", - "partitioned", - "unroll" - ], + "enum": ["trivial", "partitioned", "unroll"], "default": "trivial" }, "unrolling-factor": { @@ -763,15 +705,10 @@ "properties": { "domain": { "title": "ana.base.structs.domain", - "description": "The domain that should be used for structs. simple/sets/keyed/combined-all/combined-sk", + "description": + "The domain that should be used for structs. simple/sets/keyed/combined-all/combined-sk", "type": "string", - "enum": [ - "simple", - "sets", - "keyed", - "combined-all", - "combined-sk" - ], + "enum": ["simple", "sets", "keyed", "combined-all", "combined-sk"], "default": "simple" }, "key": { @@ -780,19 +717,22 @@ "properties": { "forward": { "title": "ana.base.structs.key.forward", - "description": "Whether the struct key should be picked going from first field to last.", + "description": + "Whether the struct key should be picked going from first field to last.", "type": "boolean", "default": true }, "avoid-ints": { "title": "ana.base.structs.key.avoid-ints", - "description": "Whether integers should be avoided for key.", + "description": + "Whether integers should be avoided for key.", "type": "boolean", "default": true }, "prefer-ptrs": { "title": "ana.base.structs.key.prefer-ptrs", - "description": "Whether pointers should be preferred for key.", + "description": + "Whether pointers should be preferred for key.", "type": "boolean", "default": true } @@ -804,23 +744,10 @@ }, "privatization": { "title": "ana.base.privatization", - "description": "Which privatization to use? none/mutex-oplus/mutex-meet/mutex-meet-tid/protection/protection-read/mine/mine-nothread/mine-W/mine-W-noinit/lock/write/write+lock", + "description": + "Which privatization to use? none/mutex-oplus/mutex-meet/mutex-meet-tid/protection/protection-read/mine/mine-nothread/mine-W/mine-W-noinit/lock/write/write+lock", "type": "string", - "enum": [ - "none", - "mutex-oplus", - "mutex-meet", - "protection", - "protection-read", - "mine", - "mine-nothread", - "mine-W", - "mine-W-noinit", - "lock", - "write", - "write+lock", - "mutex-meet-tid" - ], + "enum": ["none", "mutex-oplus", "mutex-meet", "protection", "protection-read", "mine", "mine-nothread", "mine-W", "mine-W-noinit", "lock", "write", "write+lock","mutex-meet-tid"], "default": "protection-read" }, "priv": { @@ -829,13 +756,15 @@ "properties": { "not-started": { "title": "ana.base.priv.not-started", - "description": "Exclude writes from threads that may not be started yet", + "description": + "Exclude writes from threads that may not be started yet", "type": "boolean", "default": true }, "must-joined": { "title": "ana.base.priv.must-joined", - "description": "Exclude writes from threads that must have been joined", + "description": + "Exclude writes from threads that must have been joined", "type": "boolean", "default": true } @@ -862,10 +791,7 @@ "title": "ana.base.invariant.unassume", "description": "How many times to unassume an invariant: once or until fixpoint (at least twice as expensive).", "type": "string", - "enum": [ - "once", - "fixpoint" - ], + "enum": ["once", "fixpoint"], "default": "once" } }, @@ -893,24 +819,20 @@ "properties": { "wrappers": { "title": "ana.malloc.wrappers", - "description": "Loads a list of known malloc wrapper functions.", + "description": + "Loads a list of known malloc wrapper functions.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", + "kmalloc", "__kmalloc", "usb_alloc_urb", "__builtin_alloca", "kzalloc" ] }, "unique_address_count": { - "title": "ana.malloc.unique_address_count", - "description": "Number of unique memory addresses allocated for each malloc node.", - "type": "integer", - "default": 0 + "title": "ana.malloc.unique_address_count", + "description": "Number of unique memory addresses allocated for each malloc node.", + "type": "integer", + "default": 0 } }, "additionalProperties": false @@ -927,30 +849,25 @@ }, "domain": { "title": "ana.apron.domain", - "description": "Which domain should be used for the Apron analysis. Can be 'octagon', 'interval' or 'polyhedra'", + "description": + "Which domain should be used for the Apron analysis. Can be 'octagon', 'interval' or 'polyhedra'", "type": "string", - "enum": [ - "octagon", - "interval", - "polyhedra", - "affeq" - ], + "enum": ["octagon", "interval", "polyhedra", "affeq"], "default": "octagon" }, "threshold_widening": { "title": "ana.apron.threshold_widening", - "description": "Use constants appearing in program as threshold for widening", + "description": + "Use constants appearing in program as threshold for widening", "type": "boolean", "default": false }, "threshold_widening_constants": { "title": "ana.apron.threshold_widening_constants", - "description": "Which constants in the programm should be considered as threshold constants", + "description": + "Which constants in the programm should be considered as threshold constants", "type": "string", - "enum": [ - "all", - "comparisons" - ], + "enum": ["all", "comparisons"], "default": "all" }, "invariant": { @@ -981,19 +898,10 @@ }, "privatization": { "title": "ana.relation.privatization", - "description": "Which relation privatization to use? top/protection/protection-path/mutex-meet/mutex-meet-tid/mutex-meet-tid-cluster12/mutex-meet-tid-cluster2/mutex-meet-tid-cluster-max/mutex-meet-tid-cluster-power", + "description": + "Which relation privatization to use? top/protection/protection-path/mutex-meet/mutex-meet-tid/mutex-meet-tid-cluster12/mutex-meet-tid-cluster2/mutex-meet-tid-cluster-max/mutex-meet-tid-cluster-power", "type": "string", - "enum": [ - "top", - "protection", - "protection-path", - "mutex-meet", - "mutex-meet-tid", - "mutex-meet-tid-cluster12", - "mutex-meet-tid-cluster2", - "mutex-meet-tid-cluster-max", - "mutex-meet-tid-cluster-power" - ], + "enum": ["top", "protection", "protection-path", "mutex-meet", "mutex-meet-tid", "mutex-meet-tid-cluster12", "mutex-meet-tid-cluster2", "mutex-meet-tid-cluster-max", "mutex-meet-tid-cluster-power"], "default": "mutex-meet" }, "priv": { @@ -1002,13 +910,15 @@ "properties": { "not-started": { "title": "ana.relation.priv.not-started", - "description": "Exclude writes from threads that may not be started yet", + "description": + "Exclude writes from threads that may not be started yet", "type": "boolean", "default": true }, "must-joined": { "title": "ana.relation.priv.must-joined", - "description": "Exclude writes from threads that must have been joined", + "description": + "Exclude writes from threads that must have been joined", "type": "boolean", "default": true } @@ -1049,27 +959,10 @@ "properties": { "widen": { "title": "ana.context.widen", - "description": "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", - "type": "boolean", - "default": false - }, - "ctx_gas": { - "title": "ana.context.ctx_gas", - "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "description": + "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", "type": "boolean", "default": false - }, - "ctx_gas_value": { - "title": "ana.context.ctx_gas_value", - "description": "Number of calls that are analyzed context sensitive. Used for the ContextGasLifter. Must be >= 0!", - "type": "integer", - "default": 10 - }, - "callStack_height": { - "title": "ana.context.callStack_height", - "description": "Number of elements of the callStack that should be used as context for the callsting analysis. Must be >= 0!", - "type": "integer", - "default": 10 } }, "additionalProperties": false @@ -1080,27 +973,25 @@ "properties": { "domain": { "title": "ana.thread.domain", - "description": "Which domain should be used for the thread ids. Can be 'history' or 'plain'", + "description": + "Which domain should be used for the thread ids. Can be 'history' or 'plain'", "type": "string", - "enum": [ - "history", - "plain" - ], + "enum": ["history", "plain"], "default": "history" }, - "include-node": { + "include-node" : { "title": "ana.thread.include-node", - "description": "Whether the node at which a thread is created is part of its threadid", + "description": + "Whether the node at which a thread is created is part of its threadid", "type": "boolean", - "default": true + "default" : true }, "wrappers": { "title": "ana.thread.wrappers", - "description": "Loads a list of known thread spawn (pthread_create) wrapper functions.", + "description": + "Loads a list of known thread spawn (pthread_create) wrapper functions.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "unique_thread_id_count": { @@ -1147,7 +1038,7 @@ "type": "boolean", "default": false }, - "volatile": { + "volatile" :{ "title": "ana.race.volatile", "description": "Report races for volatile variables.", "type": "boolean", @@ -1156,7 +1047,7 @@ }, "additionalProperties": false }, - "dead-code": { + "dead-code" : { "title": "ana.dead-code", "type": "object", "properties": { @@ -1181,7 +1072,7 @@ }, "additionalProperties": false }, - "extract-pthread": { + "extract-pthread" : { "title": "ana.extract-pthread", "type": "object", "properties": { @@ -1236,7 +1127,8 @@ "properties": { "load": { "title": "incremental.load", - "description": "Load incremental analysis results, in case any exist.", + "description": + "Load incremental analysis results, in case any exist.", "type": "boolean", "default": false }, @@ -1248,7 +1140,8 @@ }, "only-rename": { "title": "incremental.only-rename", - "description": "Only reset IDs of unchanged objects in the AST. Do not reuse solver results. This option is mainly useful for benchmarking purposes.", + "description": + "Only reset IDs of unchanged objects in the AST. Do not reuse solver results. This option is mainly useful for benchmarking purposes.", "type": "boolean", "default": false }, @@ -1266,13 +1159,15 @@ }, "stable": { "title": "incremental.stable", - "description": "Reuse the stable set and selectively destabilize it (recommended).", + "description": + "Reuse the stable set and selectively destabilize it (recommended).", "type": "boolean", "default": true }, "wpoint": { "title": "incremental.wpoint", - "description": "Reuse the wpoint set (not recommended). Reusing the wpoint will combine existing results at previous widening points.", + "description": + "Reuse the wpoint set (not recommended). Reusing the wpoint will combine existing results at previous widening points.", "type": "boolean", "default": false }, @@ -1282,7 +1177,8 @@ "properties": { "enabled": { "title": "incremental.reluctant.enabled", - "description": "Destabilize nodes in changed functions reluctantly", + "description": + "Destabilize nodes in changed functions reluctantly", "type": "boolean", "default": false } @@ -1291,18 +1187,16 @@ }, "compare": { "title": "incremental.compare", - "description": "Which comparison should be used for functions? 'ast'/'cfg' (cfg comparison also differentiates which nodes of a function have changed)", + "description": + "Which comparison should be used for functions? 'ast'/'cfg' (cfg comparison also differentiates which nodes of a function have changed)", "type": "string", - "enum": [ - "ast", - "cfg" - ], + "enum": ["ast", "cfg"], "default": "ast" }, "detect-renames": { "title": "incremental.detect-renames", "description": "If Goblint should try to detect renamed local variables, function parameters, functions and global variables", - "type": "boolean", + "type":"boolean", "default": true }, "force-reanalyze": { @@ -1311,7 +1205,8 @@ "properties": { "funs": { "title": "incremental.force-reanalyze.funs", - "description": "List of functions that are to be re-analayzed from scratch", + "description": + "List of functions that are to be re-analayzed from scratch", "type": "array", "items": { "type": "string" @@ -1339,11 +1234,7 @@ "title": "incremental.restart.sided.vars", "description": "Side-effected variables to restart. Globals are non-function entry nodes. Write-only is a subset of globals.", "type": "string", - "enum": [ - "all", - "global", - "write-only" - ], + "enum": ["all", "global", "write-only"], "default": "all" }, "fuel": { @@ -1381,7 +1272,7 @@ }, "postsolver": { "title": "incremental.postsolver", - "type": "object", + "type" : "object", "properties": { "enabled": { "title": "incremental.postsolver.enabled", @@ -1389,8 +1280,8 @@ "type": "boolean", "default": true }, - "superstable-reached": { - "title": "incremental.postsolver.superstable-reached", + "superstable-reached" : { + "title": "incremental.postsolver.superstable-reached", "description": "Consider superstable set reached, may be faster but can lead to spurious warnings", "type": "boolean", "default": false @@ -1455,13 +1346,15 @@ "properties": { "spawn": { "title": "sem.unknown_function.spawn", - "description": "Unknown function call spawns reachable functions", + "description": + "Unknown function call spawns reachable functions", "type": "boolean", "default": true }, "call": { "title": "sem.unknown_function.call", - "description": "Unknown function call calls reachable functions", + "description": + "Unknown function call calls reachable functions", "type": "boolean", "default": true }, @@ -1471,13 +1364,15 @@ "properties": { "globals": { "title": "sem.unknown_function.invalidate.globals", - "description": "Unknown function call invalidates all globals", + "description": + "Unknown function call invalidates all globals", "type": "boolean", "default": true }, "args": { "title": "sem.unknown_function.invalidate.args", - "description": "Unknown function call invalidates arguments passed to it", + "description": + "Unknown function call invalidates arguments passed to it", "type": "boolean", "default": true } @@ -1490,7 +1385,8 @@ "properties": { "args": { "title": "sem.unknown_function.read.args", - "description": "Unknown function call reads arguments passed to it", + "description": + "Unknown function call reads arguments passed to it", "type": "boolean", "default": true } @@ -1506,7 +1402,8 @@ "properties": { "dead_code": { "title": "sem.builtin_unreachable.dead_code", - "description": "__builtin_unreachable is assumed to be dead code", + "description": + "__builtin_unreachable is assumed to be dead code", "type": "boolean", "default": false } @@ -1520,7 +1417,8 @@ "properties": { "dead_code": { "title": "sem.noreturn.dead_code", - "description": "For the purposes of detecting dead code, assume that functions marked noreturn don't return.", + "description": + "For the purposes of detecting dead code, assume that functions marked noreturn don't return.", "type": "boolean", "default": false } @@ -1533,13 +1431,10 @@ "properties": { "signed_overflow": { "title": "sem.int.signed_overflow", - "description": "How to handle overflows of signed types. Values: 'assume_top' (default): Assume signed overflow results in a top value; 'assume_none': Assume program is free of signed overflows; 'assume_wraparound': Assume signed types wrap-around and two's complement representation of signed integers", + "description": + "How to handle overflows of signed types. Values: 'assume_top' (default): Assume signed overflow results in a top value; 'assume_none': Assume program is free of signed overflows; 'assume_wraparound': Assume signed types wrap-around and two's complement representation of signed integers", "type": "string", - "enum": [ - "assume_top", - "assume_none", - "assume_wraparound" - ], + "enum": ["assume_top", "assume_none", "assume_wraparound"], "default": "assume_top" } }, @@ -1553,10 +1448,7 @@ "title": "sem.null-pointer.dereference", "description": "NULL pointer dereference handling. assume_top: assume it results in a top value, assume_none: assume it doesn't happen", "type": "string", - "enum": [ - "assume_top", - "assume_none" - ], + "enum": ["assume_top", "assume_none"], "default": "assume_none" } }, @@ -1568,7 +1460,8 @@ "properties": { "fail": { "title": "sem.malloc.fail", - "description": "Consider the case where malloc or calloc fails.", + "description": + "Consider the case where malloc or calloc fails.", "type": "boolean", "default": false } @@ -1581,7 +1474,8 @@ "properties": { "fail": { "title": "sem.lock.fail", - "description": "Takes the possible failing of locking operations into account.", + "description": + "Takes the possible failing of locking operations into account.", "type": "boolean", "default": false } @@ -1611,16 +1505,12 @@ "properties": { "activated": { "title": "trans.activated", - "description": "Lists of activated transformations. Transformations happen after analyses.", + "description": + "Lists of activated transformations. Transformations happen after analyses.", "type": "array", "items": { "type": "string", - "enum": [ - "partial", - "expeval", - "assert", - "remove_dead_code" - ] + "enum": ["partial", "expeval", "assert", "remove_dead_code"] }, "default": [] }, @@ -1630,17 +1520,18 @@ "properties": { "query_file_name": { "title": "trans.expeval.query_file_name", - "description": "Path to the JSON file containing an expression evaluation query.", + "description": + "Path to the JSON file containing an expression evaluation query.", "type": "string", "default": "" } }, "additionalProperties": false }, - "output": { + "output" : { "title": "trans.output", "description": "Output filename for transformations that output a transformed file.", - "type": "string", + "type":"string", "default": "transformed.c" } }, @@ -1657,13 +1548,15 @@ "properties": { "enabled": { "title": "annotation.int.enabled", - "description": "Enable manual annotation of functions with desired precision, i.e., the activated IntDomains.", + "description": + "Enable manual annotation of functions with desired precision, i.e., the activated IntDomains.", "type": "boolean", "default": false }, "privglobs": { "title": "annotation.int.privglobs", - "description": "Enables handling of privatized globals, by setting the precision to the heighest value, when annotation.int.enabled is true.", + "description": + "Enables handling of privatized globals, by setting the precision to the heighest value, when annotation.int.enabled is true.", "type": "boolean", "default": true } @@ -1676,7 +1569,8 @@ "properties": { "enabled": { "title": "annotation.float.enabled", - "description": "Enable manual annotation of functions with desired precision, i.e., the activated FloatDomains.", + "description": + "Enable manual annotation of functions with desired precision, i.e., the activated FloatDomains.", "type": "boolean", "default": false } @@ -1690,20 +1584,7 @@ "type": "array", "items": { "type": "string", - "enum": [ - "base.no-non-ptr", - "base.non-ptr", - "base.no-int", - "base.int", - "base.no-interval", - "base.no-interval_set", - "base.interval", - "base.interval_set", - "relation.no-context", - "relation.context", - "no-widen", - "widen" - ] + "enum": ["base.no-non-ptr", "base.non-ptr", "base.no-int", "base.int", "base.no-interval", "base.no-interval_set","base.interval", "base.interval_set","relation.no-context", "relation.context", "no-widen", "widen"] }, "default": [] } @@ -1715,16 +1596,7 @@ "type": "array", "items": { "type": "string", - "enum": [ - "no-def_exc", - "def_exc", - "no-interval", - "interval", - "no-enums", - "enums", - "no-congruence", - "congruence" - ] + "enum": ["no-def_exc", "def_exc", "no-interval", "interval", "no-enums", "enums", "no-congruence", "congruence"] }, "default": [] } @@ -1757,7 +1629,8 @@ }, "priv-distr-init": { "title": "exp.priv-distr-init", - "description": "Distribute global initializations to all global invariants for more consistent widening dynamics.", + "description": + "Distribute global initializations to all global invariants for more consistent widening dynamics.", "type": "boolean", "default": false }, @@ -1788,7 +1661,8 @@ }, "earlyglobs": { "title": "exp.earlyglobs", - "description": "Side-effecting of globals right after initialization.", + "description": + "Side-effecting of globals right after initialization.", "type": "boolean", "default": false }, @@ -1802,20 +1676,20 @@ "title": "exp.unique", "description": "For types that have only one value.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "forward": { "title": "exp.forward", - "description": "Use implicit forward propagation instead of the demand driven approach.", + "description": + "Use implicit forward propagation instead of the demand driven approach.", "type": "boolean", "default": false }, "volatiles_are_top": { "title": "exp.volatiles_are_top", - "description": "volatile and extern keywords set variables permanently to top", + "description": + "volatile and extern keywords set variables permanently to top", "type": "boolean", "default": true }, @@ -1833,20 +1707,18 @@ }, "exclude_from_earlyglobs": { "title": "exp.exclude_from_earlyglobs", - "description": "Global variables that should be handled flow-sensitively when using earlyglobs.", + "description": + "Global variables that should be handled flow-sensitively when using earlyglobs.", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, - "exclude_from_invalidation": { + "exclude_from_invalidation" : { "title": "exp.exclude_from_invalidation", - "description": "Global variables that should not be invalidated. This assures the analysis that such globals are only modified through known code", + "description": + "Global variables that should not be invalidated. This assures the analysis that such globals are only modified through known code", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "g2html_path": { @@ -1857,11 +1729,10 @@ }, "extraspecials": { "title": "exp.extraspecials", - "description": "List of functions that must be analyzed as unknown extern functions", + "description": + "List of functions that must be analyzed as unknown extern functions", "type": "array", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "default": [] }, "no-narrow": { @@ -1872,13 +1743,15 @@ }, "basic-blocks": { "title": "exp.basic-blocks", - "description": "Only keep values for basic blocks instead of for every node. Should take longer but need less space.", + "description": + "Only keep values for basic blocks instead of for every node. Should take longer but need less space.", "type": "boolean", "default": false }, "fast_global_inits": { "title": "exp.fast_global_inits", - "description": "Only generate one 'a[any_index] = x' for all assignments a[...] = x for a global array a[n].", + "description": + "Only generate one 'a[any_index] = x' for all assignments a[...] = x for a global array a[n].", "type": "boolean", "default": true }, @@ -1886,27 +1759,27 @@ "title": "exp.architecture", "description": "Architecture for analysis, currently for witness", "type": "string", - "enum": [ - "64bit", - "32bit" - ], + "enum": ["64bit", "32bit"], "default": "64bit" }, "gcc_path": { "title": "exp.gcc_path", - "description": "Location of gcc. Used to combine source files with cilly. Change to gcc-9 or another version on OS X (with gcc being clang by default cilly will fail otherwise).", + "description": + "Location of gcc. Used to combine source files with cilly. Change to gcc-9 or another version on OS X (with gcc being clang by default cilly will fail otherwise).", "type": "string", "default": "/usr/bin/gcc" }, "cpp-path": { "title": "exp.cpp-path", - "description": "Path to C preprocessor (cpp) to use. If empty, then automatically searched.", + "description": + "Path to C preprocessor (cpp) to use. If empty, then automatically searched.", "type": "string", "default": "" }, "unrolling-factor": { "title": "exp.unrolling-factor", - "description": "Sets the unrolling factor for the loopUnrollingVisitor.", + "description": + "Sets the unrolling factor for the loopUnrollingVisitor.", "type": "integer", "default": 0 }, @@ -1988,37 +1861,43 @@ }, "timeout": { "title": "dbg.timeout", - "description": "Stop solver after this time. 0 means no timeout. Supports optional units h, m, s. E.g. 1m6s = 01m06s = 66; 6h = 6*60*60.", + "description": + "Stop solver after this time. 0 means no timeout. Supports optional units h, m, s. E.g. 1m6s = 01m06s = 66; 6h = 6*60*60.", "type": "string", "default": "0" }, "solver-stats-interval": { "title": "dbg.solver-stats-interval", - "description": "Interval in seconds to print statistics while solving. Set to 0 to deactivate.", + "description": + "Interval in seconds to print statistics while solving. Set to 0 to deactivate.", "type": "integer", "default": 10 }, "solver-signal": { "title": "dbg.solver-signal", - "description": "Signal to print statistics while solving. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", + "description": + "Signal to print statistics while solving. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", "type": "string", "default": "sigusr1" }, "backtrace-signal": { "title": "dbg.backtrace-signal", - "description": "Signal to print a raw backtrace on stderr. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", + "description": + "Signal to print a raw backtrace on stderr. Possible values: sigint (Ctrl+C), sigtstp (Ctrl+Z), sigquit (Ctrl+\\), sigusr1, sigusr2, sigalrm, sigprof etc. (see signal_of_string in gobSys.ml).", "type": "string", "default": "sigusr2" }, "solver-progress": { "title": "dbg.solver-progress", - "description": "Used for debugging. Prints out a symbol on solving a rhs.", + "description": + "Used for debugging. Prints out a symbol on solving a rhs.", "type": "boolean", "default": false }, "print_wpoints": { "title": "dbg.print_wpoints", - "description": "Print the widening points after solving (does not include the removed wpoints during solving by the slr solvers). Currently only implemented in: slr*, td3.", + "description": + "Print the widening points after solving (does not include the removed wpoints during solving by the slr solvers). Currently only implemented in: slr*, td3.", "type": "boolean", "default": false }, @@ -2047,7 +1926,8 @@ "properties": { "widen": { "title": "dbg.limit.widen", - "description": "Limit for number of widenings per node (0 = no limit).", + "description": + "Limit for number of widenings per node (0 = no limit).", "type": "integer", "default": 0 } @@ -2056,13 +1936,15 @@ }, "warn_with_context": { "title": "dbg.warn_with_context", - "description": "Keep warnings for different contexts apart (currently only done for asserts).", + "description": + "Keep warnings for different contexts apart (currently only done for asserts).", "type": "boolean", "default": false }, "regression": { "title": "dbg.regression", - "description": "Only output warnings for assertions that have an unexpected result (no comment, comment FAIL, comment UNKNOWN)", + "description": + "Only output warnings for assertions that have an unexpected result (no comment, comment FAIL, comment UNKNOWN)", "type": "boolean", "default": false }, @@ -2137,19 +2019,22 @@ }, "print_tids": { "title": "dbg.print_tids", - "description": "Should the analysis print information on the encountered TIDs", + "description": + "Should the analysis print information on the encountered TIDs", "type": "boolean", "default": false }, "print_protection": { "title": "dbg.print_protection", - "description": "Should the analysis print information on which globals are protected by which mutex?", + "description": + "Should the analysis print information on which globals are protected by which mutex?", "type": "boolean", "default": false }, - "run_cil_check": { + "run_cil_check" : { "title": "dbg.run_cil_check", - "description": "Should the analysis call Check.checkFile after creating the CFG (helpful to verify that transformations respect CIL's invariants.", + "description": + "Should the analysis call Check.checkFile after creating the CFG (helpful to verify that transformations respect CIL's invariants.", "type": "boolean", "default": false } @@ -2307,7 +2192,7 @@ }, "memleak": { "title": "warn.memleak", - "type": "object", + "type":"object", "properties": { "memcleanup": { "title": "warn.memleak.memcleanup", @@ -2337,29 +2222,23 @@ "properties": { "term": { "title": "solvers.td3.term", - "description": "Should the td3 solver use the phased/terminating strategy?", + "description": + "Should the td3 solver use the phased/terminating strategy?", "type": "boolean", "default": true }, "side_widen": { "title": "solvers.td3.side_widen", - "description": "When to widen in side. never: never widen, always: always widen, sides: widen if there are multiple side-effects from the same var resulting in a new value, cycle: widen if a called or a start var get destabilized, unstable_called: widen if any called var gets destabilized, unstable_self: widen if side-effected var gets destabilized, sides-pp: widen if there are multiple side-effects from the same program point resulting in a new value, sides-local: Widen with contributions from variables from which multiple side-effects leading to a new value originate.", + "description": + "When to widen in side. never: never widen, always: always widen, sides: widen if there are multiple side-effects from the same var resulting in a new value, cycle: widen if a called or a start var get destabilized, unstable_called: widen if any called var gets destabilized, unstable_self: widen if side-effected var gets destabilized, sides-pp: widen if there are multiple side-effects from the same program point resulting in a new value, sides-local: Widen with contributions from variables from which multiple side-effects leading to a new value originate.", "type": "string", - "enum": [ - "never", - "always", - "sides", - "cycle", - "unstable_called", - "unstable_self", - "sides-pp", - "sides-local" - ], + "enum": ["never", "always", "sides", "cycle", "unstable_called", "unstable_self", "sides-pp","sides-local"], "default": "sides" }, "space": { "title": "solvers.td3.space", - "description": "Should the td3 solver only keep values at widening points?", + "description": + "Should the td3 solver only keep values at widening points?", "type": "boolean", "default": false }, @@ -2371,7 +2250,8 @@ }, "space_restore": { "title": "solvers.td3.space_restore", - "description": "Should the td3-space solver restore values for non-widening-points? Not needed for generating warnings, but needed for inspecting output!", + "description": + "Should the td3-space solver restore values for non-widening-points? Not needed for generating warnings, but needed for inspecting output!", "type": "boolean", "default": true }, @@ -2387,10 +2267,10 @@ "type": "boolean", "default": true }, - "skip-unchanged-rhs": { - "title": "solvers.td3.skip-unchanged-rhs", - "description": "Skip evaluation of RHS if all dependencies are unchanged - INCOMPATIBLE WITH RESTARTING", - "type": "boolean", + "skip-unchanged-rhs" : { + "title" : "solvers.td3.skip-unchanged-rhs", + "description" : "Skip evaluation of RHS if all dependencies are unchanged - INCOMPATIBLE WITH RESTARTING", + "type" : "boolean", "default": false }, "restart": { @@ -2434,7 +2314,8 @@ "properties": { "restart_count": { "title": "solvers.slr4.restart_count", - "description": "How many times SLR4 is allowed to switch from restarting iteration to increasing iteration.", + "description": + "How many times SLR4 is allowed to switch from restarting iteration to increasing iteration.", "type": "integer", "default": 1 } @@ -2468,10 +2349,7 @@ "title": "witness.graphml.id", "description": "Which witness node IDs to use? node/enumerate", "type": "string", - "enum": [ - "node", - "enumerate" - ], + "enum": ["node", "enumerate"], "default": "node" }, "minimize": { @@ -2482,7 +2360,8 @@ }, "uncil": { "title": "witness.graphml.uncil", - "description": "Try to undo CIL control flow transformations in witness", + "description": + "Try to undo CIL control flow transformations in witness", "type": "boolean", "default": false }, @@ -2507,19 +2386,22 @@ "properties": { "loop-head": { "title": "witness.invariant.loop-head", - "description": "Emit invariants at loop heads", + "description": + "Emit invariants at loop heads", "type": "boolean", "default": true }, "after-lock": { "title": "witness.invariant.after-lock", - "description": "Emit invariants after mutex locking", + "description": + "Emit invariants after mutex locking", "type": "boolean", "default": true }, "other": { "title": "witness.invariant.other", - "description": "Emit invariants at all other locations", + "description": + "Emit invariants at all other locations", "type": "boolean", "default": true }, @@ -2537,7 +2419,8 @@ }, "full": { "title": "witness.invariant.full", - "description": "Whether to dump assertions about all local variables or limitting it to modified ones where possible.", + "description": + "Whether to dump assertions about all local variables or limitting it to modified ones where possible.", "type": "boolean", "default": true }, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index fef833ff75..e4480a3f5b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -533,7 +533,8 @@ struct (* returns context gas value of the given ctx*) let cg_val ctx = - snd ctx.local (* Note: snd ctx.local = snd (ctx.context ()), due to initialization ctx.local must be used here*) + (* Note: snd ctx.local = snd (ctx.context ()), but ctx.local must be used here due to initialization*) + snd ctx.local let name () = S.name ()^" with context gas" let startstate v = S.startstate v, (get_int "ana.context.ctx_gas_value") @@ -552,18 +553,11 @@ struct ; split = (fun d es -> ctx.split (d, cg_val ctx) es) ; context = (fun () -> Option.get (fst (ctx.context ())))} - (*let rec showExprList args = (*TODO: delete, just here for printing*) - match args with - | [] -> " " - | a::t -> (CilType.Exp.show a) ^ " " ^ (showExprList t)*) - let enter ctx r f args = - (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Fundec.show f) (showExprList args);*) let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in liftmap_tup (S.enter (conv ctx) r f args) - let threadenter ctx ~multiple lval f args = - (*if not !AnalysisState.postsolving && (cg_val ctx) > 0 then Printf.printf "enterThreadCG %i -> %i in %s with %s\n" (cg_val ctx) (cg_val ctx_dec) (CilType.Varinfo.show f) (showExprList args);*) + let threadenter ctx ~multiple lval f args = let liftmap f = List.map (fun (x) -> (x, max 0 (cg_val ctx - 1))) f in liftmap (S.threadenter (conv ctx) ~multiple lval f args) @@ -1112,6 +1106,7 @@ struct {obsolete; delete; reluctant; restart} end + (** Add path sensitivity to a analysis *) module PathSensitive2 (Spec:Spec) : Spec @@ -1846,10 +1841,10 @@ struct in PP.iter f h1; (* let k1 = Set.of_enum @@ PP.keys h1 in - let k2 = Set.of_enum @@ PP.keys h2 in - let o1 = Set.cardinal @@ Set.diff k1 k2 in - let o2 = Set.cardinal @@ Set.diff k2 k1 in - Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) + let k2 = Set.of_enum @@ PP.keys h2 in + let o1 = Set.cardinal @@ Set.diff k1 k2 in + let o2 = Set.cardinal @@ Set.diff k2 k1 in + Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) Printf.printf "locals: \tequal = %d\tleft = %d\tright = %d\tincomparable = %d\n" !eq !le !gr !uk let compare_locals_ctx h1 h2 = diff --git a/src/framework/control.ml b/src/framework/control.ml index def9963fe3..48bf07209f 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -21,26 +21,26 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) in + (module MCP.MCP2 : Spec) + |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) @@ -323,10 +323,10 @@ struct | MyCFG.Assign (lval,exp) -> if M.tracing then M.trace "global_inits" "Assign %a = %a\n" d_lval lval d_exp exp; (match lval, exp with - | (Var v,o), (AddrOf (Var f,NoOffset)) - when v.vstorage <> Static && isFunctionType f.vtype -> - (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) - | _ -> () + | (Var v,o), (AddrOf (Var f,NoOffset)) + when v.vstorage <> Static && isFunctionType f.vtype -> + (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) + | _ -> () ); let res = Spec.assign {ctx with local = st} lval exp in (* Needed for privatizations (e.g. None) that do not side immediately *) @@ -550,9 +550,9 @@ struct GobSys.mkdir_or_exists save_run; GobConfig.write_file config; let module Meta = struct - type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] - let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } - end + type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] + let json = to_yojson { command = GobSys.command_line; version = Goblint_build_info.version; timestamp = Unix.time (); localtime = GobUnix.localtime () } + end in (* Yojson.Safe.to_file meta Meta.json; *) Yojson.Safe.pretty_to_channel (Stdlib.open_out (Fpath.to_string meta)) Meta.json; (* the above is compact, this is pretty-printed *) @@ -604,10 +604,10 @@ struct in let print_and_calculate_uncalled = function | GFun (fn, loc) when is_bad_uncalled fn.svar loc-> - let cnt = Cilfacade.countLoc fn in - uncalled_dead := !uncalled_dead + cnt; - if get_bool "ana.dead-code.functions" then - M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) + let cnt = Cilfacade.countLoc fn in + uncalled_dead := !uncalled_dead + cnt; + if get_bool "ana.dead-code.functions" then + M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) | _ -> () in List.iter print_and_calculate_uncalled file.globals; @@ -639,35 +639,35 @@ struct NodeH.modify_opt node join by_node; ); by_loc, by_node - in - - let ask ?(node = MyCFG.dummy_node) loc = - let f (type a) (q : a Queries.t) : a = - match Hashtbl.find_option joined_by_loc loc with - | None -> Queries.Result.bot q - | Some local -> Query.ask_local_node gh node local q - in - ({ f } : Queries.ask) - in - - (* A node is dead when its abstract value is bottom in all contexts; - it holds that: bottom in all contexts iff. bottom in the join of all contexts. - Therefore, we just answer whether the (stored) join is bottom. *) - let must_be_dead node = - NodeH.find_option joined_by_node node - (* nodes that didn't make it into the result are definitely dead (hence for_all) *) - |> GobOption.for_all Spec.D.is_bot - in - - let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in - - let skipped_statements from_node edge to_node = - CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] - in - - Transform.run_transformations file active_transformations - { ask ; must_be_dead ; must_be_uncalled ; - cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; + in + + let ask ?(node = MyCFG.dummy_node) loc = + let f (type a) (q : a Queries.t) : a = + match Hashtbl.find_option joined_by_loc loc with + | None -> Queries.Result.bot q + | Some local -> Query.ask_local_node gh node local q + in + ({ f } : Queries.ask) + in + + (* A node is dead when its abstract value is bottom in all contexts; + it holds that: bottom in all contexts iff. bottom in the join of all contexts. + Therefore, we just answer whether the (stored) join is bottom. *) + let must_be_dead node = + NodeH.find_option joined_by_node node + (* nodes that didn't make it into the result are definitely dead (hence for_all) *) + |> GobOption.for_all Spec.D.is_bot + in + + let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in + + let skipped_statements from_node edge to_node = + CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] + in + + Transform.run_transformations file active_transformations + { ask ; must_be_dead ; must_be_uncalled ; + cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; ); lh, gh @@ -823,4 +823,4 @@ let analyze change_info (file: file) fs = if (get_bool "dbg.verbose") then print_endline "Generating the control flow graph."; let (module CFG), skippedByEdge = compute_cfg_skips file in MyCFG.current_cfg := (module CFG); - analyze_loop (module CFG) file fs change_info skippedByEdge + analyze_loop (module CFG) file fs change_info skippedByEdge \ No newline at end of file diff --git a/tests/regression/80-context_gas/01-basic_tests.c b/tests/regression/80-context_gas/01-basic_tests.c index 95701185b6..59c9f82981 100644 --- a/tests/regression/80-context_gas/01-basic_tests.c +++ b/tests/regression/80-context_gas/01-basic_tests.c @@ -20,14 +20,14 @@ int main() __goblint_check(y == 0); int y = f(7, 7); - __goblint_check(y == 0); //boundary (included) + __goblint_check(y == 0); // boundary (included) int y = f(8, 8); - __goblint_check(y == 0); //UNKNOWN //boundary (excluded) + __goblint_check(y == 0); // UNKNOWN //boundary (excluded) int y = f(10, 10); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN int y = f(1000, 1000); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/02-multiple_function_chain_tests.c b/tests/regression/80-context_gas/02-multiple_function_chain_tests.c index c3be5cef9a..912425d2fb 100644 --- a/tests/regression/80-context_gas/02-multiple_function_chain_tests.c +++ b/tests/regression/80-context_gas/02-multiple_function_chain_tests.c @@ -44,31 +44,30 @@ int f(int i) return res; } - int main(void) { __goblint_check(f(-5) == 0); __goblint_check(f(0) == 3); __goblint_check(f(1) == 2); - __goblint_check(f(2) == 1); - __goblint_check(f(7) == 1); //boundary (included) - __goblint_check(f(8) == 1); //UNKNOWN //boundary (excluded) - __goblint_check(f(20) == 1); //UNKNOWN + __goblint_check(f(2) == 1); + __goblint_check(f(7) == 1); // boundary (included) + __goblint_check(f(8) == 1); // UNKNOWN //boundary (excluded) + __goblint_check(f(20) == 1); // UNKNOWN - __goblint_check(g(-10) == 0); - __goblint_check(g(0) == 2); - __goblint_check(g(1) == 1); + __goblint_check(g(-10) == 0); + __goblint_check(g(0) == 2); + __goblint_check(g(1) == 1); - __goblint_check(h(-10) == 0); + __goblint_check(h(-10) == 0); __goblint_check(h(0) == 1); - __goblint_check(h(7) == 1); //boundary (included) - __goblint_check(h(8) == 1); //UNKNOWN //boundary (excluded) + __goblint_check(h(7) == 1); // boundary (included) + __goblint_check(h(8) == 1); // UNKNOWN //boundary (excluded) int res1 = h(5); int res2 = h(4); int result = res1 + res2; __goblint_check(result == 2); - __goblint_check(f(g(h(7))) == 2); // h(7) = 1; g(1) = 1; f(1) = 2; - __goblint_check(f(g(h(8))) == 2); //UNKNOWN // h(8) = UNKNOWN + __goblint_check(f(g(h(7))) == 2); // h(7) = 1; g(1) = 1; f(1) = 2; + __goblint_check(f(g(h(8))) == 2); // UNKNOWN // h(8) = UNKNOWN } diff --git a/tests/regression/80-context_gas/03-contextGas0.c b/tests/regression/80-context_gas/03-contextGas0.c index 85fc6ed48e..aadb93628c 100644 --- a/tests/regression/80-context_gas/03-contextGas0.c +++ b/tests/regression/80-context_gas/03-contextGas0.c @@ -13,11 +13,11 @@ int f(int x, int y) int main() { int y = f(0, 0); - __goblint_check(y == 0); //UNKNOWN - + __goblint_check(y == 0); // UNKNOWN + int y = f(5, 5); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN int y = f(1000, 1000); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-contextGasNeg.c b/tests/regression/80-context_gas/04-contextGasNeg.c index d8a5bcb483..0cd41b6199 100644 --- a/tests/regression/80-context_gas/04-contextGasNeg.c +++ b/tests/regression/80-context_gas/04-contextGasNeg.c @@ -13,11 +13,11 @@ int f(int x, int y) int main() { int y = f(0, 0); - __goblint_check(y == 0); //UNKNOWN - + __goblint_check(y == 0); // UNKNOWN + int y = f(5, 5); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN int y = f(1000, 1000); - __goblint_check(y == 0); //UNKNOWN + __goblint_check(y == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-ackermann.c b/tests/regression/80-context_gas/05-ackermann.c index 28f3587521..4b5579f03b 100644 --- a/tests/regression/80-context_gas/05-ackermann.c +++ b/tests/regression/80-context_gas/05-ackermann.c @@ -21,7 +21,8 @@ int ack(int n, int m) } } -int main(void) { - ack (4,1); +int main(void) +{ + ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/80-context_gas/07-loop_unrolling.c b/tests/regression/80-context_gas/07-loop_unrolling.c index d0d5b6accc..4463f0fab3 100644 --- a/tests/regression/80-context_gas/07-loop_unrolling.c +++ b/tests/regression/80-context_gas/07-loop_unrolling.c @@ -21,14 +21,14 @@ int main(void) for (int i = 1; i > 0; i--) { __goblint_check(f(2) == 1); - __goblint_check(f(2000) == 1); //UNKNOWN + __goblint_check(f(2000) == 1); // UNKNOWN } // loop should be completely unrolled for (int i = 3; i > 0; i--) { __goblint_check(f(1) == 1); - __goblint_check(f(20) == 1); //UNKNOWN + __goblint_check(f(20) == 1); // UNKNOWN } int res1 = 0; @@ -41,24 +41,24 @@ int main(void) res1 = f(3); res2 = f(i); __goblint_check(res1 == 1); - __goblint_check(res2 == 1); //TODO + __goblint_check(res2 == 1); // TODO result += res1 + res2; } __goblint_check(res1 == 1); - __goblint_check(res2 == 1); //TODO - __goblint_check(result == 10); //TODO + __goblint_check(res2 == 1); // TODO + __goblint_check(result == 10); // TODO for (int i = 5; i > 0; i--) { - __goblint_check(f(0) == 1); - __goblint_check(f(7) == 1); //boundary (included)) - __goblint_check(f(8) == 1); //UNKNOWN //boundary (excluded) + __goblint_check(f(0) == 1); + __goblint_check(f(7) == 1); // boundary (included)) + __goblint_check(f(8) == 1); // UNKNOWN //boundary (excluded) } // high number of iterations for (int i = 500; i > 0; i--) { - __goblint_check(f(i) == 1); //UNKNOWN - __goblint_check(f(4) == 1); + __goblint_check(f(i) == 1); // UNKNOWN + __goblint_check(f(4) == 1); } } diff --git a/tests/regression/80-context_gas/10-main_recursion_sens.c b/tests/regression/80-context_gas/08-main_recursion_sens.c similarity index 100% rename from tests/regression/80-context_gas/10-main_recursion_sens.c rename to tests/regression/80-context_gas/08-main_recursion_sens.c diff --git a/tests/regression/80-context_gas/09-main_recursion_insens.c b/tests/regression/80-context_gas/09-main_recursion_insens.c index 7cf6a52e74..bd0afdf563 100644 --- a/tests/regression/80-context_gas/09-main_recursion_insens.c +++ b/tests/regression/80-context_gas/09-main_recursion_insens.c @@ -10,7 +10,7 @@ int main(void) { num_iterat--; int res = main(); - __goblint_check(res == 5); //UNKNOWN + __goblint_check(res == 5); // UNKNOWN return res; } else diff --git a/tests/regression/80-context_gas/12-endless_loop.c b/tests/regression/80-context_gas/10-endless_loop.c similarity index 86% rename from tests/regression/80-context_gas/12-endless_loop.c rename to tests/regression/80-context_gas/10-endless_loop.c index e350a8c722..cb52630e3c 100644 --- a/tests/regression/80-context_gas/12-endless_loop.c +++ b/tests/regression/80-context_gas/10-endless_loop.c @@ -8,9 +8,9 @@ int main(void) { if (num_iterat > 0) { - num_iterat ++; + num_iterat++; int res = main(); - __goblint_check(res == 5); //UNKNOWN + __goblint_check(res == 5); // UNKNOWN return res; } else diff --git a/tests/regression/81-callstringTracking/02-simpleExample.c b/tests/regression/81-callstringTracking/02-simpleExample.c index 7e5a73dc1d..3f7374b955 100644 --- a/tests/regression/81-callstringTracking/02-simpleExample.c +++ b/tests/regression/81-callstringTracking/02-simpleExample.c @@ -30,5 +30,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); //UNKNOWN + __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/81-callstringTracking/04-endless_loop.c b/tests/regression/81-callstringTracking/04-endless_loop.c index 489df8cee0..1a95120c70 100644 --- a/tests/regression/81-callstringTracking/04-endless_loop.c +++ b/tests/regression/81-callstringTracking/04-endless_loop.c @@ -8,9 +8,9 @@ int main(void) { if (num_iterat > 0) { - num_iterat ++; + num_iterat++; int res = main(); - __goblint_check(res == 5); //UNKNOWN + __goblint_check(res == 5); // UNKNOWN return res; } else diff --git a/tests/regression/81-callstringTracking/05-ackermann.c b/tests/regression/81-callstringTracking/05-ackermann.c index 03dffc46d0..ae5fd453ad 100644 --- a/tests/regression/81-callstringTracking/05-ackermann.c +++ b/tests/regression/81-callstringTracking/05-ackermann.c @@ -20,7 +20,8 @@ int ack(int n, int m) } } -int main(void) { - ack (4,1); +int main(void) +{ + ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/81-callstringTracking/06-multipleCalls.c b/tests/regression/81-callstringTracking/06-multipleCalls.c index 21cdbb623e..6104124232 100644 --- a/tests/regression/81-callstringTracking/06-multipleCalls.c +++ b/tests/regression/81-callstringTracking/06-multipleCalls.c @@ -49,13 +49,13 @@ int h(int i) int main(void) { int res1 = f(num_iterat); - __goblint_check(res1 == 1); //UNKNOWN + __goblint_check(res1 == 1); // UNKNOWN int res2 = f(num_iterat); - __goblint_check(res2 == 1); //UNKNOWN - //int res3 = g(num_iterat); + __goblint_check(res2 == 1); // UNKNOWN + // int res3 = g(num_iterat); int res4 = h(num_iterat); __goblint_check(res4 == 1); - - //int result = res1 + res2 + res3 + res4 + res5; + + // int result = res1 + res2 + res3 + res4 + res5; //__goblint_check(result == 5); } diff --git a/tests/regression/81-callstringTracking/07-newCallInSet.c b/tests/regression/81-callstringTracking/07-newCallInSet.c index d067faf65e..236d4d23af 100644 --- a/tests/regression/81-callstringTracking/07-newCallInSet.c +++ b/tests/regression/81-callstringTracking/07-newCallInSet.c @@ -32,9 +32,8 @@ int g(int i) return res; } - int main(void) { int res1 = g(num_iterat); - __goblint_check(res1 == 1); //UNKNOWN + __goblint_check(res1 == 1); // UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c index 94e02b5704..5c7f4858b5 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); + __goblint_check(a == 0); } diff --git a/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c b/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c index 66645ce19b..cfebcc4458 100644 --- a/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c +++ b/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c @@ -45,31 +45,30 @@ int f(int i) return res; } - int main(void) { //__goblint_check(f(-5) == 0); - //int res1 = f(0); + // int res1 = f(0); //__goblint_check(res1 == 3); //__goblint_check(f(1) == 2); - //__goblint_check(f(2) == 1); - //int res2 = f(8); + //__goblint_check(f(2) == 1); + // int res2 = f(8); //__goblint_check(res2 == 1); //boundary (included) //__goblint_check(f(9) == 1); //UNKNOWN //boundary (excluded) //__goblint_check(f(20) == 1); //UNKNOWN - //__goblint_check(g(-10) == 0); - //__goblint_check(g(0) == 2); - //__goblint_check(g(1) == 1); + //__goblint_check(g(-10) == 0); + //__goblint_check(g(0) == 2); + //__goblint_check(g(1) == 1); - //__goblint_check(h(-10) == 0); + //__goblint_check(h(-10) == 0); __goblint_check(h(5) == 1); //__goblint_check(h(8) == 1); //boundary (included) ///__goblint_check(h(9) == 1); //UNKNOWN //boundary (excluded) - //int res1 = h(5); - //int res2 = h(4); - //int result = res1 + res2; + // int res1 = h(5); + // int res2 = h(4); + // int result = res1 + res2; //__goblint_check(result == 2); //__goblint_check(f(g(h(9))) == 2); // h(9) = 1; g(1) = 1; f(1) = 2; diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c index 7feca66f22..24dade7342 100644 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c @@ -54,7 +54,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; __goblint_check(result == 5); } diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c index 7f4b7cc686..eb8f4d66ac 100644 --- a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c @@ -53,7 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); //UNKNOWN + __goblint_check(result == 5); // UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c index 521502a45c..7199dd7f84 100644 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); + + __goblint_check(result == 1); } diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c index 2e4b176ea1..cd4a9bd58a 100644 --- a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c +++ b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); //UNKNOWN + + __goblint_check(result == 1); // UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c index 7c0703a437..d3f80414bc 100644 --- a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c +++ b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c @@ -2,7 +2,7 @@ // Interesting if nested recursions are handled properly #include -int num_iterat = 9; +int num_iterat = 9; int f(int i) { diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_Fundec/08-ackermann.c index 08f19aea86..cc1d220a55 100644 --- a/tests/regression/82-callstring_Fundec/08-ackermann.c +++ b/tests/regression/82-callstring_Fundec/08-ackermann.c @@ -21,7 +21,8 @@ int ack(int n, int m) } } -int main(void) { - ack (4,1); +int main(void) +{ + ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c index f5c2da3a35..355a4aeb69 100644 --- a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c +++ b/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c @@ -2,9 +2,9 @@ // Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed #include -int num_iterat = 200; +int num_iterat = 200; -int f(int i); +int f(int i); int g(int i) { @@ -36,13 +36,13 @@ int f(int i) int main(void) { - int res1 = 0; - int res2 = 0; + int res1 = 0; + int res2 = 0; for (int i = 2; i > 0; i--) { res1 = f(num_iterat); res2 = g(num_iterat); - __goblint_check(res1 == 2); //UNKNOWN - __goblint_check(res2 == 1); //UNKNOWN + __goblint_check(res1 == 2); // UNKNOWN + __goblint_check(res2 == 1); // UNKNOWN } } diff --git a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c index 3ce98936e4..2c71062a1c 100644 --- a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c +++ b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c @@ -30,5 +30,5 @@ int main(void) result += res; } __goblint_check(res == 1); - __goblint_check(result == 5); //TODO + __goblint_check(result == 5); // TODO } diff --git a/tests/regression/82-callstring_Fundec/13-thread_creation.c b/tests/regression/82-callstring_Fundec/13-thread_creation.c index 03edf9dd50..12ca0155ac 100644 --- a/tests/regression/82-callstring_Fundec/13-thread_creation.c +++ b/tests/regression/82-callstring_Fundec/13-thread_creation.c @@ -62,7 +62,7 @@ void *t_sens(void *arg) } void *t_sens2(void *arg) -{ +{ int result = procedure(7); __goblint_check(result == 10); return NULL; diff --git a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c index 35cc1adc09..db46283df7 100644 --- a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c +++ b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c @@ -57,10 +57,10 @@ int procedure(int num_iterat) void *t_sens(void *arg) { int result = procedure(0); - __goblint_check(result == 8); //TODO + __goblint_check(result == 8); // TODO result = procedure(3); - __goblint_check(result == 10); //TODO + __goblint_check(result == 10); // TODO return NULL; } @@ -81,7 +81,7 @@ int main() // Creat the thread pthread_create(&id, NULL, t_sens, NULL); - //pthread_join(id, NULL); + // pthread_join(id, NULL); // Creat the thread pthread_create(&id2, NULL, t_insens, NULL); diff --git a/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c b/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c index 0308699acf..3855aa3671 100644 --- a/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c +++ b/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); //UNKNOWN + __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c index 5d1b90b952..aa480aec1c 100644 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); + __goblint_check(a == 0); } diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c index 347b6525a0..6a8d06c849 100644 --- a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); //UNKNOWN + __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c index d13f8004d4..19c43b3089 100644 --- a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c +++ b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c @@ -53,7 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; __goblint_check(result == 5); } diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c index 0a7c6a5966..28901ead13 100644 --- a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c +++ b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c @@ -53,7 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); //UNKNOWN + __goblint_check(result == 5); // UNKNOWN } diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c index 822ae4d41f..d65685cf86 100644 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); + + __goblint_check(result == 1); } diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c index 9ce5d1a5ef..c0db02aeb8 100644 --- a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c +++ b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); //UNKNOWN + + __goblint_check(result == 1); // UNKNOWN } diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c index 8f92286dd6..8abd2bd44d 100644 --- a/tests/regression/83-callstring_Stmt/07-call_in_call.c +++ b/tests/regression/83-callstring_Stmt/07-call_in_call.c @@ -2,7 +2,7 @@ // Interesting if nested recursions are handled properly #include -int num_iterat = 10; +int num_iterat = 10; int f(int i) { diff --git a/tests/regression/83-callstring_Stmt/09-thread_creation.c b/tests/regression/83-callstring_Stmt/09-thread_creation.c index 635327b22b..fdcbdaf5c6 100644 --- a/tests/regression/83-callstring_Stmt/09-thread_creation.c +++ b/tests/regression/83-callstring_Stmt/09-thread_creation.c @@ -60,7 +60,7 @@ void *t_sens(void *arg) __goblint_check(result == 8); result = procedure(8); - __goblint_check(result == 10); + __goblint_check(result == 10); return NULL; } diff --git a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c b/tests/regression/84-callstring_Loc/01-simple_rec_sens.c similarity index 91% rename from tests/regression/85-callstring_Loc/01-simple_rec_sens.c rename to tests/regression/84-callstring_Loc/01-simple_rec_sens.c index cbd218713a..046804d2aa 100644 --- a/tests/regression/85-callstring_Loc/01-simple_rec_sens.c +++ b/tests/regression/84-callstring_Loc/01-simple_rec_sens.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); + __goblint_check(a == 0); } diff --git a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c b/tests/regression/84-callstring_Loc/02-simple_rec_ins.c similarity index 88% rename from tests/regression/85-callstring_Loc/02-simple_rec_ins.c rename to tests/regression/84-callstring_Loc/02-simple_rec_ins.c index 9a672986a4..406ef49f9f 100644 --- a/tests/regression/85-callstring_Loc/02-simple_rec_ins.c +++ b/tests/regression/84-callstring_Loc/02-simple_rec_ins.c @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); //UNKNOWN + __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c b/tests/regression/84-callstring_Loc/03-multiple_rec_sens.c similarity index 99% rename from tests/regression/85-callstring_Loc/03-multiple_rec_sens.c rename to tests/regression/84-callstring_Loc/03-multiple_rec_sens.c index f684b8e4b6..ccdfa680a2 100644 --- a/tests/regression/85-callstring_Loc/03-multiple_rec_sens.c +++ b/tests/regression/84-callstring_Loc/03-multiple_rec_sens.c @@ -53,7 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; __goblint_check(result == 5); } diff --git a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c b/tests/regression/84-callstring_Loc/04-multiple_rec_ins.c similarity index 94% rename from tests/regression/85-callstring_Loc/04-multiple_rec_ins.c rename to tests/regression/84-callstring_Loc/04-multiple_rec_ins.c index 7c2a0a30ec..1c4602474a 100644 --- a/tests/regression/85-callstring_Loc/04-multiple_rec_ins.c +++ b/tests/regression/84-callstring_Loc/04-multiple_rec_ins.c @@ -53,7 +53,7 @@ int main(void) int res3 = h(num_iterat); int res4 = h(num_iterat); int res5 = h(num_iterat); - + int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); //UNKNOWN + __goblint_check(result == 5); // UNKNOWN } diff --git a/tests/regression/85-callstring_Loc/05-function_chain_sens.c b/tests/regression/84-callstring_Loc/05-function_chain_sens.c similarity index 94% rename from tests/regression/85-callstring_Loc/05-function_chain_sens.c rename to tests/regression/84-callstring_Loc/05-function_chain_sens.c index 5d3af4c54b..60edae4f32 100644 --- a/tests/regression/85-callstring_Loc/05-function_chain_sens.c +++ b/tests/regression/84-callstring_Loc/05-function_chain_sens.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); + + __goblint_check(result == 1); } diff --git a/tests/regression/85-callstring_Loc/06-function_chain_ins.c b/tests/regression/84-callstring_Loc/06-function_chain_ins.c similarity index 93% rename from tests/regression/85-callstring_Loc/06-function_chain_ins.c rename to tests/regression/84-callstring_Loc/06-function_chain_ins.c index 3b1f733a50..2330ec02e3 100644 --- a/tests/regression/85-callstring_Loc/06-function_chain_ins.c +++ b/tests/regression/84-callstring_Loc/06-function_chain_ins.c @@ -49,6 +49,6 @@ int f(int i) int main(void) { int result = f(num_iterat); - - __goblint_check(result == 1); //UNKNOWN + + __goblint_check(result == 1); // UNKNOWN } diff --git a/tests/regression/85-callstring_Loc/07-call_in_call.c b/tests/regression/84-callstring_Loc/07-call_in_call.c similarity index 97% rename from tests/regression/85-callstring_Loc/07-call_in_call.c rename to tests/regression/84-callstring_Loc/07-call_in_call.c index def1c9981c..92cba9752e 100644 --- a/tests/regression/85-callstring_Loc/07-call_in_call.c +++ b/tests/regression/84-callstring_Loc/07-call_in_call.c @@ -2,7 +2,7 @@ // Interesting if nested recursions are handled properly #include -int num_iterat = 10; +int num_iterat = 10; int f(int i) { diff --git a/tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c b/tests/regression/84-callstring_Loc/08-circle_call_and_big_loop.c similarity index 100% rename from tests/regression/85-callstring_Loc/08-circle_call_and_big_loop.c rename to tests/regression/84-callstring_Loc/08-circle_call_and_big_loop.c diff --git a/tests/regression/85-callstring_Loc/09-thread_creation.c b/tests/regression/84-callstring_Loc/09-thread_creation.c similarity index 97% rename from tests/regression/85-callstring_Loc/09-thread_creation.c rename to tests/regression/84-callstring_Loc/09-thread_creation.c index 2564c9adad..3464d0fe86 100644 --- a/tests/regression/85-callstring_Loc/09-thread_creation.c +++ b/tests/regression/84-callstring_Loc/09-thread_creation.c @@ -60,7 +60,7 @@ void *t_sens(void *arg) __goblint_check(result == 8); result = procedure(8); - __goblint_check(result == 10); + __goblint_check(result == 10); return NULL; } diff --git a/tests/regression/84-callstring_both/01-simple_rec_sens.c b/tests/regression/84-callstring_both/01-simple_rec_sens.c deleted file mode 100644 index 88caca0889..0000000000 --- a/tests/regression/84-callstring_both/01-simple_rec_sens.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 10; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); -} diff --git a/tests/regression/84-callstring_both/02-simple_rec_ins.c b/tests/regression/84-callstring_both/02-simple_rec_ins.c deleted file mode 100644 index e0885f702d..0000000000 --- a/tests/regression/84-callstring_both/02-simple_rec_ins.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 11; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); //UNKNOWN -} diff --git a/tests/regression/84-callstring_both/03-multiple_rec_sens.c b/tests/regression/84-callstring_both/03-multiple_rec_sens.c deleted file mode 100644 index 8da5325850..0000000000 --- a/tests/regression/84-callstring_both/03-multiple_rec_sens.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); -} diff --git a/tests/regression/84-callstring_both/04-multiple_rec_ins.c b/tests/regression/84-callstring_both/04-multiple_rec_ins.c deleted file mode 100644 index e919335ca7..0000000000 --- a/tests/regression/84-callstring_both/04-multiple_rec_ins.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 11; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); //UNKNOWN -} From d87e541a4bfce255320d9b3343f9c01c27f31dcc Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 12:21:48 +0100 Subject: [PATCH 083/128] renamed svcomp configuration --- ...vcomp24-callstringFundec.json => svcomp-callstringFundec.json} | 0 conf/{svcomp24-callstringLoc.json => svcomp-callstringLoc.json} | 0 conf/{svcomp24-callstringStmt.json => svcomp-callstringStmt.json} | 0 ...p24-callstringTracking.json => svcomp-callstringTracking.json} | 0 conf/{svcomp24-contextGas10.json => svcomp-contextGas10.json} | 0 conf/{svcomp24-contextGas18.json => svcomp-contextGas18.json} | 0 conf/{svcomp24-contextGas30.json => svcomp-contextGas30.json} | 0 conf/{svcomp24-widenContext.json => svcomp-widenContext.json} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename conf/{svcomp24-callstringFundec.json => svcomp-callstringFundec.json} (100%) rename conf/{svcomp24-callstringLoc.json => svcomp-callstringLoc.json} (100%) rename conf/{svcomp24-callstringStmt.json => svcomp-callstringStmt.json} (100%) rename conf/{svcomp24-callstringTracking.json => svcomp-callstringTracking.json} (100%) rename conf/{svcomp24-contextGas10.json => svcomp-contextGas10.json} (100%) rename conf/{svcomp24-contextGas18.json => svcomp-contextGas18.json} (100%) rename conf/{svcomp24-contextGas30.json => svcomp-contextGas30.json} (100%) rename conf/{svcomp24-widenContext.json => svcomp-widenContext.json} (100%) diff --git a/conf/svcomp24-callstringFundec.json b/conf/svcomp-callstringFundec.json similarity index 100% rename from conf/svcomp24-callstringFundec.json rename to conf/svcomp-callstringFundec.json diff --git a/conf/svcomp24-callstringLoc.json b/conf/svcomp-callstringLoc.json similarity index 100% rename from conf/svcomp24-callstringLoc.json rename to conf/svcomp-callstringLoc.json diff --git a/conf/svcomp24-callstringStmt.json b/conf/svcomp-callstringStmt.json similarity index 100% rename from conf/svcomp24-callstringStmt.json rename to conf/svcomp-callstringStmt.json diff --git a/conf/svcomp24-callstringTracking.json b/conf/svcomp-callstringTracking.json similarity index 100% rename from conf/svcomp24-callstringTracking.json rename to conf/svcomp-callstringTracking.json diff --git a/conf/svcomp24-contextGas10.json b/conf/svcomp-contextGas10.json similarity index 100% rename from conf/svcomp24-contextGas10.json rename to conf/svcomp-contextGas10.json diff --git a/conf/svcomp24-contextGas18.json b/conf/svcomp-contextGas18.json similarity index 100% rename from conf/svcomp24-contextGas18.json rename to conf/svcomp-contextGas18.json diff --git a/conf/svcomp24-contextGas30.json b/conf/svcomp-contextGas30.json similarity index 100% rename from conf/svcomp24-contextGas30.json rename to conf/svcomp-contextGas30.json diff --git a/conf/svcomp24-widenContext.json b/conf/svcomp-widenContext.json similarity index 100% rename from conf/svcomp24-widenContext.json rename to conf/svcomp-widenContext.json From a3d019e5fa55fda4039525bf52a1f5966dbbdea8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 12:36:42 +0100 Subject: [PATCH 084/128] renamed svcomp configs; restore some entries in options.schema.json which were accidentially deleted --- ...stringFundec.json => callstringFundec.json} | 0 ...p-callstringLoc.json => callstringLoc.json} | 0 ...callstringStmt.json => callstringStmt.json} | 0 ...ngTracking.json => callstringTracking.json} | 0 ...omp-contextGas10.json => contextGas10.json} | 0 ...omp-contextGas18.json => contextGas18.json} | 0 ...omp-contextGas30.json => contextGas30.json} | 0 ...-widenContext.json => contextWidening.json} | 0 src/config/options.schema.json | 18 ++++++++++++++++++ 9 files changed, 18 insertions(+) rename conf/{svcomp-callstringFundec.json => callstringFundec.json} (100%) rename conf/{svcomp-callstringLoc.json => callstringLoc.json} (100%) rename conf/{svcomp-callstringStmt.json => callstringStmt.json} (100%) rename conf/{svcomp-callstringTracking.json => callstringTracking.json} (100%) rename conf/{svcomp-contextGas10.json => contextGas10.json} (100%) rename conf/{svcomp-contextGas18.json => contextGas18.json} (100%) rename conf/{svcomp-contextGas30.json => contextGas30.json} (100%) rename conf/{svcomp-widenContext.json => contextWidening.json} (100%) diff --git a/conf/svcomp-callstringFundec.json b/conf/callstringFundec.json similarity index 100% rename from conf/svcomp-callstringFundec.json rename to conf/callstringFundec.json diff --git a/conf/svcomp-callstringLoc.json b/conf/callstringLoc.json similarity index 100% rename from conf/svcomp-callstringLoc.json rename to conf/callstringLoc.json diff --git a/conf/svcomp-callstringStmt.json b/conf/callstringStmt.json similarity index 100% rename from conf/svcomp-callstringStmt.json rename to conf/callstringStmt.json diff --git a/conf/svcomp-callstringTracking.json b/conf/callstringTracking.json similarity index 100% rename from conf/svcomp-callstringTracking.json rename to conf/callstringTracking.json diff --git a/conf/svcomp-contextGas10.json b/conf/contextGas10.json similarity index 100% rename from conf/svcomp-contextGas10.json rename to conf/contextGas10.json diff --git a/conf/svcomp-contextGas18.json b/conf/contextGas18.json similarity index 100% rename from conf/svcomp-contextGas18.json rename to conf/contextGas18.json diff --git a/conf/svcomp-contextGas30.json b/conf/contextGas30.json similarity index 100% rename from conf/svcomp-contextGas30.json rename to conf/contextGas30.json diff --git a/conf/svcomp-widenContext.json b/conf/contextWidening.json similarity index 100% rename from conf/svcomp-widenContext.json rename to conf/contextWidening.json diff --git a/src/config/options.schema.json b/src/config/options.schema.json index adadd9dcdb..c71a80bc7e 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -963,6 +963,24 @@ "Do widening on contexts. Keeps a map of function to call state; enter will then return the widened local state for recursive calls.", "type": "boolean", "default": false + }, + "ctx_gas": { + "title": "ana.context.ctx_gas", + "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "type": "boolean", + "default": false + }, + "ctx_gas_value": { + "title": "ana.context.ctx_gas_value", + "description": "Number of calls that are analyzed context sensitive. Used for the ContextGasLifter. Must be >= 0!", + "type": "integer", + "default": 10 + }, + "callStack_height": { + "title": "ana.context.callStack_height", + "description": "Number of elements of the callStack that should be used as context for the callsting analysis. Must be >= 0!", + "type": "integer", + "default": 10 } }, "additionalProperties": false From 15d4e8cbf518804ababa20b1b201062394af3e6e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 13:46:15 +0100 Subject: [PATCH 085/128] adapt indentation to master --- .devcontainer/devcontainer.json | 8 ++++---- src/config/options.schema.json | 2 +- src/domain/lattice.ml | 3 ++- src/framework/control.ml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c4fc736697..e00754dfd8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,9 +13,9 @@ "runArgs": ["--init", "--env-file", ".devcontainer/devcontainer.env"], // TODO: why --init added by default? "extensions": [ - "ocamllabs.ocaml-platform", - "hackwaly.ocamlearlybird" - ], + "ocamllabs.ocaml-platform", + "hackwaly.ocamlearlybird" + ], "settings": {}, -} +} \ No newline at end of file diff --git a/src/config/options.schema.json b/src/config/options.schema.json index c71a80bc7e..55728b7b9f 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -2575,4 +2575,4 @@ } }, "additionalProperties": false -} \ No newline at end of file +} diff --git a/src/domain/lattice.ml b/src/domain/lattice.ml index b4ad59aa72..264d8be0aa 100644 --- a/src/domain/lattice.ml +++ b/src/domain/lattice.ml @@ -650,4 +650,5 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y -end \ No newline at end of file +end + \ No newline at end of file diff --git a/src/framework/control.ml b/src/framework/control.ml index 48bf07209f..57feaebb4a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -823,4 +823,4 @@ let analyze change_info (file: file) fs = if (get_bool "dbg.verbose") then print_endline "Generating the control flow graph."; let (module CFG), skippedByEdge = compute_cfg_skips file in MyCFG.current_cfg := (module CFG); - analyze_loop (module CFG) file fs change_info skippedByEdge \ No newline at end of file + analyze_loop (module CFG) file fs change_info skippedByEdge From 550bbbcd58b35ef0bd22169a758331d113793f6e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 13:56:30 +0100 Subject: [PATCH 086/128] rephrased ctx_gas and callstack description --- src/config/options.schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 55728b7b9f..ad4fa9b86c 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -966,19 +966,19 @@ }, "ctx_gas": { "title": "ana.context.ctx_gas", - "description": "If enabled, the first x recursions are analyzed context sensitively, the remaining context insensitively. x is refered to as the context gas", + "description": "If enabled, the first x recursions of each path are analyzed context-sensitive, the remaining context-insensitive. x denotes the context gas, which is defined in ana.context.ctx_gas_value.", "type": "boolean", "default": false }, "ctx_gas_value": { "title": "ana.context.ctx_gas_value", - "description": "Number of calls that are analyzed context sensitive. Used for the ContextGasLifter. Must be >= 0!", + "description": "Number of calls that are analyzed context-sensitive. Used for the ContextGasLifter, which is enabled with ana.context.ctx_gas. Must be >= 0!", "type": "integer", "default": 10 }, "callStack_height": { "title": "ana.context.callStack_height", - "description": "Number of elements of the callStack that should be used as context for the callsting analysis. Must be >= 0!", + "description": "Height of the CallStack that should be used as context for the callsting analysis. Must be >= 0!", "type": "integer", "default": 10 } From 59f2258cc854a23bde525e4849182b17d8109d30 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 26 Jan 2024 14:54:39 +0100 Subject: [PATCH 087/128] fixed indentation to match master --- .devcontainer/devcontainer.json | 2 +- src/common/domains/printable.ml | 2 +- src/domain/lattice.ml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e00754dfd8..2bf28b3c6f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -18,4 +18,4 @@ ], "settings": {}, -} \ No newline at end of file +} diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index dc397d776e..84003bd794 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -832,4 +832,4 @@ struct ) let to_yojson x = x (* override SimplePretty *) -end \ No newline at end of file +end diff --git a/src/domain/lattice.ml b/src/domain/lattice.ml index 264d8be0aa..99322c09d8 100644 --- a/src/domain/lattice.ml +++ b/src/domain/lattice.ml @@ -651,4 +651,3 @@ struct let pretty_diff () ((x:t),(y:t)): Pretty.doc = Pretty.dprintf "%a not leq %a" pretty x pretty y end - \ No newline at end of file From 8967b1022b09a0ffb36d4843174a26ffb4ad36bd Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 30 Jan 2024 09:57:47 +0100 Subject: [PATCH 088/128] replaced queueImmut with BatDeque --- src/analyses/callstringAnalysis.ml | 10 +-- src/common/domains/printable.ml | 27 ++++--- src/common/util/queueImmut.ml | 126 ----------------------------- src/util/std/goblint_std.ml | 1 - 4 files changed, 22 insertions(+), 142 deletions(-) delete mode 100644 src/common/util/queueImmut.ml diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index cdfeb5f6af..6b7d9841f9 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -25,11 +25,11 @@ struct match elem with | None -> stack | Some e -> - let new_stack = QueueImmut.push e stack in (* pushes new element to stack*) + let new_stack = BatDeque.cons e stack in (* pushes new element to stack*) (* removes element from stack, if stack was filled with k elements*) - match (QueueImmut.length new_stack - depth) with + match (BatDeque.size new_stack - depth) with | x when x <= 0 -> new_stack - | 1 -> QueueImmut.dequeue new_stack + | 1 -> fst @@ Option.get (BatDeque.rear new_stack) | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" end @@ -39,8 +39,8 @@ struct module G = Lattice.Unit let name () = "callstring_"^ CT.stackTypeName - let startstate v = `Lifted (QueueImmut.create ()) - let exitstate v = `Lifted (QueueImmut.create ()) (*TODO: should I use startstate here? Does this make a difference*) + let startstate v = `Lifted (BatDeque.empty) + let exitstate v = `Lifted (BatDeque.empty) (*TODO: should I use startstate here? Does this make a difference*) let context fd x = match x with | `Lifted x -> x diff --git a/src/common/domains/printable.ml b/src/common/domains/printable.ml index 84003bd794..e1d6ccaeb7 100644 --- a/src/common/domains/printable.ml +++ b/src/common/domains/printable.ml @@ -590,32 +590,39 @@ end module PQueue (Base: S) = struct - type t = Base.t QueueImmut.t [@@deriving eq, ord] + type t = Base.t BatDeque.dq include Std - let show x = - let elem = QueueImmut.map_to_list Base.show x in - "[" ^ (String.concat ", " elem) ^ "]" + let show x = "[" ^ (BatDeque.fold_right (fun a acc -> Base.show a ^ ", " ^ acc) x "]") let pretty () x = text (show x) let name () = Base.name () ^ "queue" - let relift x = QueueImmut.map Base.relift x + let relift x = BatDeque.map Base.relift x let printXml f xs = let rec loop n q = - let (x, xs) = QueueImmut.dequeue_tup_opt q in - match x with + match BatDeque.front q with | None -> () - | Some x -> (BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; + | Some (x, xs) -> (BatPrintf.fprintf f "%d\n%a\n" n Base.printXml x; loop (n+1) (xs)) in BatPrintf.fprintf f "\n\n"; loop 0 xs; BatPrintf.fprintf f "\n\n" - let to_yojson q = `List (QueueImmut.map_to_list (Base.to_yojson) q) - let hash (q: Base.t QueueImmut.t) = QueueImmut.fold_left (fun acc x -> (acc + 71) * (Base.hash x)) 11 q + let to_yojson q = `List (BatDeque.to_list @@ BatDeque.map (Base.to_yojson) q) + let hash q = BatDeque.fold_left (fun acc x -> (acc + 71) * (Base.hash x)) 11 q + let equal q1 q2 = BatDeque.eq ~eq:Base.equal q1 q2 + let compare q1 q2 = + match BatDeque.front q1, BatDeque.front q2 with + | None, None -> 0 + | None, Some(_, _) -> -1 + | Some(_, _), None -> 1 + | Some(a1, q1'), Some(a2, q2') -> + let c = Base.compare a1 a2 in + if c <> 0 then c + else compare q1' q2' end module Liszt (Base: S) = diff --git a/src/common/util/queueImmut.ml b/src/common/util/queueImmut.ml deleted file mode 100644 index 308f3aba77..0000000000 --- a/src/common/util/queueImmut.ml +++ /dev/null @@ -1,126 +0,0 @@ -(* A Queue (FIFO, imutable) implementation, using two Lists for efficient push and pop handling. - - Example Queue: remove here, 1, 2, 3, 4, add here - Representation as Queue: Queue([1,2], [4,3]) or Queue([1], [4,3,2]) or Queue([1,2,3,4], []) or ... -*) - -exception Empty - -type 'a t = Queue of 'a list * 'a list - -(** Return a new queue, initially empty. *) -let create () = Queue ([], []) -let length (Queue (q_first, q_last)) = List.length q_first + List.length q_last - -(** Return [true] if the given queue is empty, [false] otherwise. *) -let is_empty = function - | Queue ([], []) -> true - | _ -> false - -(** Discard all elements from a queue. *) -let clear (Queue (q_first, q_last)) = Queue ([], []) - -(** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_first]*) -let get_first_list (Queue (q_first, q_last)) = q_first - -(** The queue is internally stored as two lists. [get_first_list q] with [q] equal to [Queue (q_first, q_last)] returns [q_last]*) -let get_last_list (Queue (q_first, q_last)) = q_last - -(** Converts a queue into a list. *) -let list_of_queue = function - | Queue (q_first, []) -> q_first - | Queue (q_first, q_last) -> q_first @ List.rev q_last - -(** Converts a list into a queue. *) -let queue_of_list list = Queue (list,[]) - -let rec equal eq q1 q2 = - match q1, q2 with - | Queue ([], []), Queue ([], []) -> true - | Queue ([], []), Queue ([], x) | Queue ([], []), Queue (x, []) - | Queue (x, []), Queue ([], []) | Queue ([], x), Queue ([], []) -> false - | Queue ([], q1_last), Queue (q2_first, q2_last) -> equal eq (Queue (List.rev q1_last, [])) (Queue (q2_first, q2_last)) - | Queue (q1_first, q1_last), Queue ([], q2_last) -> equal eq (Queue (q1_first, q1_last)) (Queue (List.rev q2_last, [])) - | Queue (x1::q1_first, q1_last), Queue (x2::q2_first, q2_last) -> eq x1 x2 && equal eq (Queue (q1_first, q1_last)) (Queue (q2_first, q2_last)) - -let rec compare cmp q1 q2 = - match q1, q2 with - | Queue ([], []), Queue ([], []) -> 0 - | Queue ([], []), Queue ([], x) | Queue ([], []), Queue (x, []) -> -1 - | Queue (x, []), Queue ([], []) | Queue ([], x), Queue ([], []) -> 1 - | Queue ([], q1_last), Queue (q2_first, q2_last) -> compare cmp (Queue (List.rev q1_last, [])) (Queue (q2_first, q2_last)) - | Queue (q1_first, q1_last), Queue ([], q2_last) -> compare cmp (Queue (q1_first, q1_last)) (Queue (List.rev q2_last, [])) - | Queue (x1::q1_first, q1_last), Queue (x2::q2_first, q2_last) -> - let c = cmp x1 x2 in - if c <> 0 then c - else compare cmp (Queue (q1_first, q1_last)) (Queue (q2_first, q2_last)) - -(** [add x q] adds the element [x] at the end of the queue [q] and returns the resulting queue*) -let add ele (Queue (q_first, q_last)) = Queue (q_first, ele :: q_last) -(** [push] is a synonym for [add]. *) -let push = add - -(** [enqueue] is a synonym for [add]. *) -let enqueue = add - -(** [peek q] returns the first element in queue [q], or raises {!Empty} if the queue is empty. *) -let peek = function (* returns the removed element*) - | Queue ([], q_last) -> ( - match List.rev q_last with - | [] -> raise Empty - | x::xs -> x) - | Queue (x::q_first, q_last) -> x - -(** [peek_opt q] returns the first element in queue [q] as option, or returns [None] if the queue is empty.*) -let peek_opt = function (* returns the removed element as option*) - | Queue ([], q_last) -> ( - match List.rev q_last with - | [] -> None - | x::xs -> Some x) - | Queue (x::q_first, q_last) -> Some x - -(** [dequeue q] removes the first element in queue [q] - and returns the remaining queue.*) -let dequeue = function (* returns the remaining queue after removing one element*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> Queue ([], []) - | x::xs -> Queue(xs, [])) - | Queue (x::q_first, q_last) -> Queue (q_first, q_last) - -(** [dequeue_tup_opt q] removes the first element in queue [q] - and returns it with the remaining queue in a tuple. - In case of an empty queue the first element is [None]*) -let dequeue_tup_opt = function (* returns the removed element and the remaining queue*) - | Queue ([], q_last) -> ( - match List.rev q_last with (*List.rev q_last is moved to the first list*) - | [] -> (None, Queue ([], [])) - | x::xs -> (Some x , Queue(xs, []))) - | Queue (x::q_first, q_last) -> (Some x, Queue (q_first, q_last)) - -(** [iter f q] applies [f] in turn to all elements of [q], - from the least recently entered to the most recently entered.*) -let iter f (Queue (q_first, q_last)) = - List.iter f q_first; - List.iter f (List.rev q_last) - -(** [map f [a1; ...; an]] applies function [f] to [a1, ..., an], - and builds the queue [[f a1; ...; f an]] - with the results returned by [f]. Not tail-recursive.*) -let map f (Queue (q_first, q_last)) = - Queue (List.map f q_first, List.map f q_last) - -(** [map_to_list f q] is equivalent to [map f l], but returns a list instead of a queue*) -let map_to_list f (Queue (q_first, q_last)) = - List.map f q_first @ List.rev_map f q_last - -(** [fold_left f accu [b1; ...; bn]] is - [f (... (f (f accu b1) b2) ...) bn].*) -let fold_left f accu (Queue (q_first, q_last)) = - let res = List.fold_left f accu q_first in - List.fold_left f res (List.rev q_last) - -(** [fold_right f [a1; ...; an] accu] is - [f a1 (f a2 (... (f an accu) ...))]. Not tail-recursive.*) -let fold_right f (Queue (q_first, q_last)) accu = - List.fold_right f (List.rev q_last) accu |> List.fold_right f q_first \ No newline at end of file diff --git a/src/util/std/goblint_std.ml b/src/util/std/goblint_std.ml index da13343468..0d548cac08 100644 --- a/src/util/std/goblint_std.ml +++ b/src/util/std/goblint_std.ml @@ -23,4 +23,3 @@ module GobQCheck = GobQCheck module GobYaml = GobYaml module GobYojson = GobYojson module GobZ = GobZ -module QueueImmut = QueueImmut From 5c8a860ed959fce1682d9c267165cb9ff9673296 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Feb 2024 12:39:53 +0100 Subject: [PATCH 089/128] renamed callstringTracking to loopfreeCallstring; loopfreeCallstring: module G got Unit domain, renamed list -> stack; mCP: replaced if condition with match; added space to comments --- ...gTracking.json => loopfreeCallstring.json} | 2 +- ...tringTracking.ml => loopfreeCallstring.ml} | 17 +++++++++------- src/analyses/mCP.ml | 20 ++++++++++--------- src/goblint_lib.ml | 2 +- .../81-callstringTracking/01-loopCalling.c | 2 +- .../81-callstringTracking/02-simpleExample.c | 2 +- .../03-loopCallingSens.c | 2 +- .../81-callstringTracking/04-endless_loop.c | 2 +- .../81-callstringTracking/05-ackermann.c | 2 +- .../81-callstringTracking/06-multipleCalls.c | 2 +- .../81-callstringTracking/07-newCallInSet.c | 2 +- 11 files changed, 30 insertions(+), 25 deletions(-) rename conf/{callstringTracking.json => loopfreeCallstring.json} (99%) rename src/analyses/{callstringTracking.ml => loopfreeCallstring.ml} (58%) diff --git a/conf/callstringTracking.json b/conf/loopfreeCallstring.json similarity index 99% rename from conf/callstringTracking.json rename to conf/loopfreeCallstring.json index ad0fb4acb3..518fb913e9 100644 --- a/conf/callstringTracking.json +++ b/conf/loopfreeCallstring.json @@ -31,7 +31,7 @@ "region", "thread", "threadJoins", - "callstringTracking" + "loopfreeCallstring" ], "path_sens": [ "mutex", diff --git a/src/analyses/callstringTracking.ml b/src/analyses/loopfreeCallstring.ml similarity index 58% rename from src/analyses/callstringTracking.ml rename to src/analyses/loopfreeCallstring.ml index a74e9660d3..a86a11f34d 100644 --- a/src/analyses/callstringTracking.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -1,30 +1,33 @@ +(** This approach is inspired by + @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. *) + open Analyses module Spec : MCPSpec = struct include Analyses.IdentitySpec - let name () = "callstringTracking" + let name () = "loopfreeCallstring" module FundecSet = SetDomain.Make (CilType.Fundec) module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) module D = Lattice.Prod (FundecList) (FundecSet) module C = D - module G = D module V = EmptyV + module G = Lattice.Unit let startstate v = D.bot () let exitstate v = D.bot () let get_list l = match l with | `Lifted l -> l | `Bot -> [] - | `Top -> failwith "callstringTracking Error: the value of the Flat List shouldn't be top!" + | `Top -> failwith "loopfreeCallstring Error: the value of the Flat List shouldn't be top!" let callee_state f ctx = - let (list, set) = ctx.local in - if (not(FundecSet.is_empty set)) || List.mem f (get_list list) - then (list, FundecSet.add f set) - else (`Lifted (f::(get_list list)), set) + let (stack, set) = ctx.local in + if (not(FundecSet.is_empty set)) || List.mem f (get_list stack) + then (stack, FundecSet.add f set) + else (`Lifted (f::(get_list stack)), set) let enter ctx r f args = [ctx.local, callee_state f ctx] diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 613677500a..dd9e139113 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -66,10 +66,10 @@ struct iter deps xs let specific_cont_sens xs = - (*most analysis must be set to context insensitive, because we only want to analyse context sensitively for a specific analysis*) - let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "callstringTracking"] in + (* most analysis must be set to context-insensitive, because we only want to analyse context-sensitive for one specific analysis *) + let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "loopfreeCallstring"] in let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in - (*returns the edited list of insensitive analyses if enabled*) + (* returns the edited list of insensitive analyses if enabled *) if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None type marshal = Obj.t list @@ -86,12 +86,14 @@ struct let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; - (*checks if an analysis is enabled with special handled context sensitivity*) - if Option.is_some special_inse - then (cont_inse := map' find_id (Option.get special_inse); - path_sens := []) - else (cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; - path_sens := map' find_id @@ get_string_list "ana.path_sens"); + (* checks if an analysis is enabled which requires special handling of context-sensitivity *) + begin + match special_inse with + | Some ins -> cont_inse := map' find_id ins; + path_sens := []; + | None -> cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + path_sens := map' find_id @@ get_string_list "ana.path_sens"; + end; check_deps !activated; activated := topo_sort_an !activated; activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 971e096a55..6d1750f62e 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -151,7 +151,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination module CallstringAnalysis = CallstringAnalysis -module CallstringTracking = CallstringTracking +module LoopfreeCallstring = LoopfreeCallstring module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace diff --git a/tests/regression/81-callstringTracking/01-loopCalling.c b/tests/regression/81-callstringTracking/01-loopCalling.c index fed4669bca..6eb7797938 100644 --- a/tests/regression/81-callstringTracking/01-loopCalling.c +++ b/tests/regression/81-callstringTracking/01-loopCalling.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-callstringTracking/02-simpleExample.c b/tests/regression/81-callstringTracking/02-simpleExample.c index 3f7374b955..d7e60ccbe8 100644 --- a/tests/regression/81-callstringTracking/02-simpleExample.c +++ b/tests/regression/81-callstringTracking/02-simpleExample.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-callstringTracking/03-loopCallingSens.c b/tests/regression/81-callstringTracking/03-loopCallingSens.c index 08fa410e60..234fbf7e8c 100644 --- a/tests/regression/81-callstringTracking/03-loopCallingSens.c +++ b/tests/regression/81-callstringTracking/03-loopCallingSens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-callstringTracking/04-endless_loop.c b/tests/regression/81-callstringTracking/04-endless_loop.c index 1a95120c70..5f77269d50 100644 --- a/tests/regression/81-callstringTracking/04-endless_loop.c +++ b/tests/regression/81-callstringTracking/04-endless_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis #include diff --git a/tests/regression/81-callstringTracking/05-ackermann.c b/tests/regression/81-callstringTracking/05-ackermann.c index ae5fd453ad..1307aad1f3 100644 --- a/tests/regression/81-callstringTracking/05-ackermann.c +++ b/tests/regression/81-callstringTracking/05-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set #include int ack(int n, int m) diff --git a/tests/regression/81-callstringTracking/06-multipleCalls.c b/tests/regression/81-callstringTracking/06-multipleCalls.c index 6104124232..8c3279655e 100644 --- a/tests/regression/81-callstringTracking/06-multipleCalls.c +++ b/tests/regression/81-callstringTracking/06-multipleCalls.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-callstringTracking/07-newCallInSet.c b/tests/regression/81-callstringTracking/07-newCallInSet.c index 236d4d23af..c2cbc86c0d 100644 --- a/tests/regression/81-callstringTracking/07-newCallInSet.c +++ b/tests/regression/81-callstringTracking/07-newCallInSet.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" callstringTracking --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set // Basic example #include From ae643cda7d32da5b7776d0effdcc922a7885c0da Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Feb 2024 12:42:53 +0100 Subject: [PATCH 090/128] callstringAnalysis: renamed pushElem to stackElem; inlined the depth computation; adjusted comments --- src/analyses/callstringAnalysis.ml | 43 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 6b7d9841f9..294fad6b35 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -2,38 +2,37 @@ open Analyses open GoblintCil open GobConfig -(* Specifies the type of the callstack elements for the callstring analysis*) +(* Specifies the type of the call-stack elements for the call-string analysis *) module type Callstack_Type = sig include CilType.S val stackTypeName: string - val pushElem: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an elements that should be pushed to the Callstack *) + val stackEle: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call-stack *) end -(** Analysis with the k-callsting approach, which uses the last k callstack elements as context. - With the CT argument it is possible to specify the type of the callstack elements*) +(** Analysis with the k-call-string approach, which uses the last k call-stack elements as context. + With the CT argument it is possible to specify the type of the call-stack elements *) module Spec (CT:Callstack_Type) : MCPSpec = struct include Analyses.IdentitySpec - (* simulates a call stack of depth k*) + (* simulates a call-stack of depth k *) module CallStack = struct include Printable.PQueue (CT) - let depth = get_int "ana.context.callStack_height" (* must be >= 0 *) - let push stack elem = (* pushes elem to the stack, guarantees stack depth of k*) + let push stack elem = (* pushes elem to the call-stack, guarantees a depth of k *) match elem with | None -> stack | Some e -> - let new_stack = BatDeque.cons e stack in (* pushes new element to stack*) - (* removes element from stack, if stack was filled with k elements*) - match (BatDeque.size new_stack - depth) with + let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) + (* removes element from stack, if stack was filled with k elements *) + match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with | x when x <= 0 -> new_stack | 1 -> fst @@ Option.get (BatDeque.rear new_stack) | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" end - module D = Lattice.Flat (CallStack) + module D = Lattice.Flat (CallStack) (* should be the CallStack (C=D). Since a Lattice is required, Lattice.Flat is used to fulfill the type *) module C = CallStack module V = EmptyV module G = Lattice.Unit @@ -44,11 +43,11 @@ struct let context fd x = match x with | `Lifted x -> x - | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" (* TODO: is there a possibility???*) + | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" let callee_state ctx f = - let elem = CT.pushElem f ctx in - let new_stack = CallStack.push (context f ctx.local) elem in (*TODO: is it ok to use context here??? *) + let elem = CT.stackEle f ctx in + let new_stack = CallStack.push (context f ctx.local) elem in `Lifted new_stack let enter ctx r f args = [ctx.local, callee_state ctx f] @@ -61,27 +60,27 @@ end module Fundec:Callstack_Type = struct include CilType.Fundec let stackTypeName = "fundec" - let pushElem f ctx = Some f + let stackEle f ctx = Some f end module Stmt:Callstack_Type = struct include CilType.Stmt let stackTypeName = "stmt" - let pushElem f ctx = + let stackEle f ctx = match ctx.prev_node with | Statement stmt -> Some stmt - | _ -> None (* first statement is filtered*) + | _ -> None (* first statement is filtered *) end module Location:Callstack_Type = struct include CilType.Location let stackTypeName = "loc" - let pushElem f ctx = + let stackEle f ctx = Some !Goblint_tracing.current_loc end -(* Lifters for the Callstring approach with different Callstack element types*) +(* Lifters for the call-string approach with different call-stack element types *) let _ = - MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec*) - MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt*) - MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc*) \ No newline at end of file + MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec *) + MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt *) + MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc *) \ No newline at end of file From 23b8b5bb00371bed4891e091f3e9672724179871 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Feb 2024 14:20:36 +0100 Subject: [PATCH 091/128] fixed typo --- src/config/options.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index ad4fa9b86c..64bd6ee2e4 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -978,7 +978,7 @@ }, "callStack_height": { "title": "ana.context.callStack_height", - "description": "Height of the CallStack that should be used as context for the callsting analysis. Must be >= 0!", + "description": "Height of the CallStack that should be used as context for the callstring analysis. Must be >= 0!", "type": "integer", "default": 10 } From 5516b778d11372be477522c373bab2bbaf10b25c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Feb 2024 14:48:04 +0100 Subject: [PATCH 092/128] deleted noRecursiveIntervals from context configurations --- conf/callstringFundec.json | 1 - conf/callstringLoc.json | 1 - conf/callstringStmt.json | 1 - conf/contextGas10.json | 1 - conf/contextGas18.json | 1 - conf/contextGas30.json | 1 - conf/contextWidening.json | 1 - conf/loopfreeCallstring.json | 5 ++--- 8 files changed, 2 insertions(+), 10 deletions(-) diff --git a/conf/callstringFundec.json b/conf/callstringFundec.json index 5c53cc5597..028bf06a25 100644 --- a/conf/callstringFundec.json +++ b/conf/callstringFundec.json @@ -79,7 +79,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/callstringLoc.json b/conf/callstringLoc.json index 0bb6632525..9fec56d477 100644 --- a/conf/callstringLoc.json +++ b/conf/callstringLoc.json @@ -79,7 +79,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/callstringStmt.json b/conf/callstringStmt.json index dbc750c49b..79dec715aa 100644 --- a/conf/callstringStmt.json +++ b/conf/callstringStmt.json @@ -79,7 +79,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/contextGas10.json b/conf/contextGas10.json index dcf9c6b630..acd09dffe3 100644 --- a/conf/contextGas10.json +++ b/conf/contextGas10.json @@ -78,7 +78,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/contextGas18.json b/conf/contextGas18.json index cdcf813363..3762413122 100644 --- a/conf/contextGas18.json +++ b/conf/contextGas18.json @@ -78,7 +78,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/contextGas30.json b/conf/contextGas30.json index 1337059ac2..d42013d626 100644 --- a/conf/contextGas30.json +++ b/conf/contextGas30.json @@ -78,7 +78,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/contextWidening.json b/conf/contextWidening.json index b03f608518..537c1a26ff 100644 --- a/conf/contextWidening.json +++ b/conf/contextWidening.json @@ -79,7 +79,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", diff --git a/conf/loopfreeCallstring.json b/conf/loopfreeCallstring.json index 518fb913e9..8a28076830 100644 --- a/conf/loopfreeCallstring.json +++ b/conf/loopfreeCallstring.json @@ -1,7 +1,7 @@ { "ana": { "sv-comp": { - "enabled": true, + "enabled": false, "functions": true }, "int": { @@ -80,7 +80,6 @@ "activated": [ "singleThreaded", "mallocWrappers", - "noRecursiveIntervals", "enums", "congruence", "octagon", @@ -109,7 +108,7 @@ }, "witness": { "graphml": { - "enabled": true, + "enabled": false, "id": "enumerate", "unknown": false }, From abecc7ae77bece1fa02a9e41096a574a95142126 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Feb 2024 15:25:07 +0100 Subject: [PATCH 093/128] renamed repository and updated path in test-gobview to pass gobview test --- scripts/test-gobview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test-gobview.py b/scripts/test-gobview.py index cac3ab824c..1ac8f6a76c 100644 --- a/scripts/test-gobview.py +++ b/scripts/test-gobview.py @@ -26,8 +26,8 @@ def serve(): global p goblint_http_path = '_build/default/gobview/goblint-http-server/goblint_http.exe' p = subprocess.Popen(['./' + goblint_http_path, - '-with-goblint', '../GobContextGas/goblint', - '-goblint', '--set', 'files[+]', '"../GobContextGas/tests/regression/00-sanity/01-assert.c"']) + '-with-goblint', '../analyzer/goblint', + '-goblint', '--set', 'files[+]', '"../analyzer/tests/regression/00-sanity/01-assert.c"']) print("serving at port", PORT) thread = Thread(target=serve, args=()) From f9e774a2f0fa538f5cb901a228981dc4f8d1ac84 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 5 Feb 2024 09:16:19 +0100 Subject: [PATCH 094/128] fixed loopfreeCallstring configuration --- conf/loopfreeCallstring.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/loopfreeCallstring.json b/conf/loopfreeCallstring.json index 8a28076830..b88c35bbfb 100644 --- a/conf/loopfreeCallstring.json +++ b/conf/loopfreeCallstring.json @@ -1,7 +1,7 @@ { "ana": { "sv-comp": { - "enabled": false, + "enabled": true, "functions": true }, "int": { @@ -108,7 +108,7 @@ }, "witness": { "graphml": { - "enabled": false, + "enabled": true, "id": "enumerate", "unknown": false }, From b2f7543d4d4ba3de92828e6a269329f99e053108 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 5 Feb 2024 17:15:58 +0100 Subject: [PATCH 095/128] uploaded list_search-1.i test: problems with soundness --- .../81-callstringTracking/list_search-1.i | 567 ++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 tests/regression/81-callstringTracking/list_search-1.i diff --git a/tests/regression/81-callstringTracking/list_search-1.i b/tests/regression/81-callstringTracking/list_search-1.i new file mode 100644 index 0000000000..0261ea61bc --- /dev/null +++ b/tests/regression/81-callstringTracking/list_search-1.i @@ -0,0 +1,567 @@ +extern void abort(void); + +extern void __assert_fail (const char *__assertion, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern void __assert_perror_fail (int __errnum, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern void __assert (const char *__assertion, const char *__file, int __line) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); + +void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "list_search-1.c", 3, __extension__ __PRETTY_FUNCTION__); })); } +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: {reach_error();abort();} + } + return; +} +typedef unsigned int size_t; +typedef long int wchar_t; + +typedef enum +{ + P_ALL, + P_PID, + P_PGID +} idtype_t; +typedef struct + { + int quot; + int rem; + } div_t; +typedef struct + { + long int quot; + long int rem; + } ldiv_t; +__extension__ typedef struct + { + long long int quot; + long long int rem; + } lldiv_t; +extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ , __leaf__)) ; +extern double atof (const char *__nptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; +extern int atoi (const char *__nptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; +extern long int atol (const char *__nptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; +__extension__ extern long long int atoll (const char *__nptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; +extern double strtod (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern float strtof (const char *__restrict __nptr, + char **__restrict __endptr) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern long double strtold (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern long int strtol (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern unsigned long int strtoul (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +__extension__ +extern long long int strtoq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +__extension__ +extern unsigned long long int strtouq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +__extension__ +extern long long int strtoll (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +__extension__ +extern unsigned long long int strtoull (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern char *l64a (long int __n) __attribute__ ((__nothrow__ , __leaf__)) ; +extern long int a64l (const char *__s) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; +__extension__ typedef signed long long int __int64_t; +__extension__ typedef unsigned long long int __uint64_t; +__extension__ typedef long long int __quad_t; +__extension__ typedef unsigned long long int __u_quad_t; +__extension__ typedef long long int __intmax_t; +__extension__ typedef unsigned long long int __uintmax_t; +__extension__ typedef __u_quad_t __dev_t; +__extension__ typedef unsigned int __uid_t; +__extension__ typedef unsigned int __gid_t; +__extension__ typedef unsigned long int __ino_t; +__extension__ typedef __u_quad_t __ino64_t; +__extension__ typedef unsigned int __mode_t; +__extension__ typedef unsigned int __nlink_t; +__extension__ typedef long int __off_t; +__extension__ typedef __quad_t __off64_t; +__extension__ typedef int __pid_t; +__extension__ typedef struct { int __val[2]; } __fsid_t; +__extension__ typedef long int __clock_t; +__extension__ typedef unsigned long int __rlim_t; +__extension__ typedef __u_quad_t __rlim64_t; +__extension__ typedef unsigned int __id_t; +__extension__ typedef long int __time_t; +__extension__ typedef unsigned int __useconds_t; +__extension__ typedef long int __suseconds_t; +__extension__ typedef int __daddr_t; +__extension__ typedef int __key_t; +__extension__ typedef int __clockid_t; +__extension__ typedef void * __timer_t; +__extension__ typedef long int __blksize_t; +__extension__ typedef long int __blkcnt_t; +__extension__ typedef __quad_t __blkcnt64_t; +__extension__ typedef unsigned long int __fsblkcnt_t; +__extension__ typedef __u_quad_t __fsblkcnt64_t; +__extension__ typedef unsigned long int __fsfilcnt_t; +__extension__ typedef __u_quad_t __fsfilcnt64_t; +__extension__ typedef int __fsword_t; +__extension__ typedef int __ssize_t; +__extension__ typedef long int __syscall_slong_t; +__extension__ typedef unsigned long int __syscall_ulong_t; +typedef __off64_t __loff_t; +typedef char *__caddr_t; +__extension__ typedef int __intptr_t; +__extension__ typedef unsigned int __socklen_t; +typedef int __sig_atomic_t; +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +typedef __loff_t loff_t; +typedef __ino_t ino_t; +typedef __dev_t dev_t; +typedef __gid_t gid_t; +typedef __mode_t mode_t; +typedef __nlink_t nlink_t; +typedef __uid_t uid_t; +typedef __off_t off_t; +typedef __pid_t pid_t; +typedef __id_t id_t; +typedef __ssize_t ssize_t; +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +typedef __key_t key_t; +typedef __clock_t clock_t; +typedef __clockid_t clockid_t; +typedef __time_t time_t; +typedef __timer_t timer_t; +typedef unsigned long int ulong; +typedef unsigned short int ushort; +typedef unsigned int uint; +typedef __int8_t int8_t; +typedef __int16_t int16_t; +typedef __int32_t int32_t; +typedef __int64_t int64_t; +typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__))); +typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__))); +typedef int register_t __attribute__ ((__mode__ (__word__))); +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __builtin_bswap32 (__bsx); +} +static __inline __uint64_t +__bswap_64 (__uint64_t __bsx) +{ + return __builtin_bswap64 (__bsx); +} +static __inline __uint16_t +__uint16_identity (__uint16_t __x) +{ + return __x; +} +static __inline __uint32_t +__uint32_identity (__uint32_t __x) +{ + return __x; +} +static __inline __uint64_t +__uint64_identity (__uint64_t __x) +{ + return __x; +} +typedef struct +{ + unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; +} __sigset_t; +typedef __sigset_t sigset_t; +struct timeval +{ + __time_t tv_sec; + __suseconds_t tv_usec; +}; +struct timespec +{ + __time_t tv_sec; + __syscall_slong_t tv_nsec; +}; +typedef __suseconds_t suseconds_t; +typedef long int __fd_mask; +typedef struct + { + __fd_mask __fds_bits[1024 / (8 * (int) sizeof (__fd_mask))]; + } fd_set; +typedef __fd_mask fd_mask; + +extern int select (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + struct timeval *__restrict __timeout); +extern int pselect (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t *__restrict __sigmask); + + +extern unsigned int gnu_dev_major (__dev_t __dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); +extern unsigned int gnu_dev_minor (__dev_t __dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); +extern __dev_t gnu_dev_makedev (unsigned int __major, unsigned int __minor) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); + +typedef __blksize_t blksize_t; +typedef __blkcnt_t blkcnt_t; +typedef __fsblkcnt_t fsblkcnt_t; +typedef __fsfilcnt_t fsfilcnt_t; +struct __pthread_rwlock_arch_t +{ + unsigned int __readers; + unsigned int __writers; + unsigned int __wrphase_futex; + unsigned int __writers_futex; + unsigned int __pad3; + unsigned int __pad4; + unsigned char __flags; + unsigned char __shared; + signed char __rwelision; + unsigned char __pad2; + int __cur_writer; +}; +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +struct __pthread_mutex_s +{ + int __lock ; + unsigned int __count; + int __owner; + int __kind; + + unsigned int __nusers; + __extension__ union + { + struct { short __espins; short __eelision; } __elision_data; + __pthread_slist_t __list; + }; + +}; +struct __pthread_cond_s +{ + __extension__ union + { + __extension__ unsigned long long int __wseq; + struct + { + unsigned int __low; + unsigned int __high; + } __wseq32; + }; + __extension__ union + { + __extension__ unsigned long long int __g1_start; + struct + { + unsigned int __low; + unsigned int __high; + } __g1_start32; + }; + unsigned int __g_refs[2] ; + unsigned int __g_size[2]; + unsigned int __g1_orig_size; + unsigned int __wrefs; + unsigned int __g_signals[2]; +}; +typedef unsigned long int pthread_t; +typedef union +{ + char __size[4]; + int __align; +} pthread_mutexattr_t; +typedef union +{ + char __size[4]; + int __align; +} pthread_condattr_t; +typedef unsigned int pthread_key_t; +typedef int pthread_once_t; +union pthread_attr_t +{ + char __size[36]; + long int __align; +}; +typedef union pthread_attr_t pthread_attr_t; +typedef union +{ + struct __pthread_mutex_s __data; + char __size[24]; + long int __align; +} pthread_mutex_t; +typedef union +{ + struct __pthread_cond_s __data; + char __size[48]; + __extension__ long long int __align; +} pthread_cond_t; +typedef union +{ + struct __pthread_rwlock_arch_t __data; + char __size[32]; + long int __align; +} pthread_rwlock_t; +typedef union +{ + char __size[8]; + long int __align; +} pthread_rwlockattr_t; +typedef volatile int pthread_spinlock_t; +typedef union +{ + char __size[20]; + long int __align; +} pthread_barrier_t; +typedef union +{ + char __size[4]; + int __align; +} pthread_barrierattr_t; + +extern long int random (void) __attribute__ ((__nothrow__ , __leaf__)); +extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__)); +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); +extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +struct random_data + { + int32_t *fptr; + int32_t *rptr; + int32_t *state; + int rand_type; + int rand_deg; + int rand_sep; + int32_t *end_ptr; + }; +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int srandom_r (unsigned int __seed, struct random_data *__buf) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4))); +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int rand (void) __attribute__ ((__nothrow__ , __leaf__)); +extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__)); +extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ , __leaf__)); +extern double drand48 (void) __attribute__ ((__nothrow__ , __leaf__)); +extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern long int lrand48 (void) __attribute__ ((__nothrow__ , __leaf__)); +extern long int nrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern long int mrand48 (void) __attribute__ ((__nothrow__ , __leaf__)); +extern long int jrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ , __leaf__)); +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +struct drand48_data + { + unsigned short int __x[3]; + unsigned short int __old_x[3]; + unsigned short int __c; + unsigned short int __init; + __extension__ unsigned long long int __a; + }; +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); +extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; +extern void *calloc (size_t __nmemb, size_t __size) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; +extern void *realloc (void *__ptr, size_t __size) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__warn_unused_result__)); +extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__)); + +extern void *alloca (size_t __size) __attribute__ ((__nothrow__ , __leaf__)); + +extern void *valloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; +extern void *aligned_alloc (size_t __alignment, size_t __size) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__alloc_size__ (2))) ; +extern void abort (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern int at_quick_exit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern void exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern void quick_exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern void _Exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern char *getenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; +extern int putenv (char *__string) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern int setenv (const char *__name, const char *__value, int __replace) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); +extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern int clearenv (void) __attribute__ ((__nothrow__ , __leaf__)); +extern char *mktemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); +extern int mkstemp (char *__template) __attribute__ ((__nonnull__ (1))) ; +extern int mkstemps (char *__template, int __suffixlen) __attribute__ ((__nonnull__ (1))) ; +extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; +extern int system (const char *__command) ; +extern char *realpath (const char *__restrict __name, + char *__restrict __resolved) __attribute__ ((__nothrow__ , __leaf__)) ; +typedef int (*__compar_fn_t) (const void *, const void *); +extern void *bsearch (const void *__key, const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar) + __attribute__ ((__nonnull__ (1, 2, 5))) ; +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __attribute__ ((__nonnull__ (1, 4))); +extern int abs (int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +extern long int labs (long int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +__extension__ extern long long int llabs (long long int __x) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +extern div_t div (int __numer, int __denom) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +extern ldiv_t ldiv (long int __numer, long int __denom) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *gcvt (double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ; +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ; +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); +extern int mbtowc (wchar_t *__restrict __pwc, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); +extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ , __leaf__)); +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); +extern size_t wcstombs (char *__restrict __s, + const wchar_t *__restrict __pwcs, size_t __n) + __attribute__ ((__nothrow__ , __leaf__)); +extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; +extern int getsubopt (char **__restrict __optionp, + char *const *__restrict __tokens, + char **__restrict __valuep) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2, 3))) ; +extern int getloadavg (double __loadavg[], int __nelem) + __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); + +typedef struct list { + int key; + struct list *next; +} mlist; +mlist *head; +mlist* search_list(mlist *l, int k){ + l = head; + while(l!=((void *)0) && l->key!=k) { + l = l->next; + } + return l; +} +int insert_list(mlist *l, int k){ + l = (mlist*)malloc(sizeof(mlist)); + l->key = k; + if (head==((void *)0)) { + l->next = ((void *)0); + } else { + l->key = k; + l->next = head; + } + head = l; + return 0; +} +int main(void){ + int i; + mlist *mylist, *temp; + insert_list(mylist,2); + insert_list(mylist,5); + insert_list(mylist,1); + insert_list(mylist,3); + temp = search_list(head,2); + __VERIFIER_assert(temp->key==1); + while(head!=0) { + mlist *tmp = head->next; + free(head); + head = tmp; + } +} \ No newline at end of file From 465b5c1307db6ef469a3b4c8fb971f8cbeef0e6d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Feb 2024 10:19:56 +0100 Subject: [PATCH 096/128] fixed join error in apron domain: replaced is_bot with is_bot_env (otherwise top is recognized as bottom and leads to wrong joining); with this fix the path sensitivity can be enabled for context insensitive program --- src/analyses/mCP.ml | 3 +-- src/cdomains/apron/apronDomain.apron.ml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index dd9e139113..9e987a2033 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -86,13 +86,12 @@ struct let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; + path_sens := map' find_id @@ get_string_list "ana.path_sens"; (* checks if an analysis is enabled which requires special handling of context-sensitivity *) begin match special_inse with | Some ins -> cont_inse := map' find_id ins; - path_sens := []; | None -> cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; - path_sens := map' find_id @@ get_string_list "ana.path_sens"; end; check_deps !activated; activated := topo_sort_an !activated; diff --git a/src/cdomains/apron/apronDomain.apron.ml b/src/cdomains/apron/apronDomain.apron.ml index 2b8f360bc5..33850f7525 100644 --- a/src/cdomains/apron/apronDomain.apron.ml +++ b/src/cdomains/apron/apronDomain.apron.ml @@ -672,9 +672,9 @@ struct let join x y = (* just to optimize joining folds, which start with bot *) - if is_bot x then (* TODO: also for non-empty env *) + if is_bot_env x then (* TODO: also for non-empty env *) y - else if is_bot y then (* TODO: also for non-empty env *) + else if is_bot_env y then (* TODO: also for non-empty env *) x else ( if M.tracing then M.traceli "apron" "join %a %a\n" pretty x pretty y; From 899b67b93bce1f9cf303491f6d34786828ce4b19 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Feb 2024 17:39:30 +0100 Subject: [PATCH 097/128] updated configurations for paper: renamed, deleted octagon in autotune, added taintPartialContexts; also added a new standard config (context-paper-24) which is like svcomp-24 but with the named changes and deleted noRecursiveIntervals --- ...ringFundec.json => callstring-fundec.json} | 2 +- ...callstringLoc.json => callstring-loc.json} | 2 +- ...llstringStmt.json => callstring-stmt.json} | 2 +- ...{contextGas10.json => context-gas-10.json} | 4 +- ...{contextGas18.json => context-gas-20.json} | 6 +- ...{contextGas30.json => context-gas-30.json} | 4 +- conf/context-paper-24.json | 145 ++++++++++++++++++ ...extWidening.json => context-widening.json} | 4 +- ...llstring.json => loopfree-callstring.json} | 2 +- 9 files changed, 158 insertions(+), 13 deletions(-) rename conf/{callstringFundec.json => callstring-fundec.json} (98%) rename conf/{callstringLoc.json => callstring-loc.json} (98%) rename conf/{callstringStmt.json => callstring-stmt.json} (98%) rename conf/{contextGas10.json => context-gas-10.json} (98%) rename conf/{contextGas18.json => context-gas-20.json} (97%) rename conf/{contextGas30.json => context-gas-30.json} (98%) create mode 100644 conf/context-paper-24.json rename conf/{contextWidening.json => context-widening.json} (98%) rename conf/{loopfreeCallstring.json => loopfree-callstring.json} (98%) diff --git a/conf/callstringFundec.json b/conf/callstring-fundec.json similarity index 98% rename from conf/callstringFundec.json rename to conf/callstring-fundec.json index 028bf06a25..cc0489e310 100644 --- a/conf/callstringFundec.json +++ b/conf/callstring-fundec.json @@ -31,6 +31,7 @@ "region", "thread", "threadJoins", + "taintPartialContexts", "callstring_fundec" ], "path_sens": [ @@ -81,7 +82,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/callstringLoc.json b/conf/callstring-loc.json similarity index 98% rename from conf/callstringLoc.json rename to conf/callstring-loc.json index 9fec56d477..de08c4dee2 100644 --- a/conf/callstringLoc.json +++ b/conf/callstring-loc.json @@ -31,6 +31,7 @@ "region", "thread", "threadJoins", + "taintPartialContexts", "callstring_loc" ], "path_sens": [ @@ -81,7 +82,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/callstringStmt.json b/conf/callstring-stmt.json similarity index 98% rename from conf/callstringStmt.json rename to conf/callstring-stmt.json index 79dec715aa..165a726e0b 100644 --- a/conf/callstringStmt.json +++ b/conf/callstring-stmt.json @@ -31,6 +31,7 @@ "region", "thread", "threadJoins", + "taintPartialContexts", "callstring_stmt" ], "path_sens": [ @@ -81,7 +82,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/contextGas10.json b/conf/context-gas-10.json similarity index 98% rename from conf/contextGas10.json rename to conf/context-gas-10.json index acd09dffe3..fb335ba475 100644 --- a/conf/contextGas10.json +++ b/conf/context-gas-10.json @@ -30,7 +30,8 @@ "symb_locks", "region", "thread", - "threadJoins" + "threadJoins", + "taintPartialContexts" ], "path_sens": [ "mutex", @@ -80,7 +81,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/contextGas18.json b/conf/context-gas-20.json similarity index 97% rename from conf/contextGas18.json rename to conf/context-gas-20.json index 3762413122..95530e7eab 100644 --- a/conf/contextGas18.json +++ b/conf/context-gas-20.json @@ -30,7 +30,8 @@ "symb_locks", "region", "thread", - "threadJoins" + "threadJoins", + "taintPartialContexts" ], "path_sens": [ "mutex", @@ -44,7 +45,7 @@ "context": { "widen": false, "ctx_gas": true, - "ctx_gas_value": 18 + "ctx_gas_value": 20 }, "malloc": { "wrappers": [ @@ -80,7 +81,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/contextGas30.json b/conf/context-gas-30.json similarity index 98% rename from conf/contextGas30.json rename to conf/context-gas-30.json index d42013d626..7fea39d8ac 100644 --- a/conf/contextGas30.json +++ b/conf/context-gas-30.json @@ -30,7 +30,8 @@ "symb_locks", "region", "thread", - "threadJoins" + "threadJoins", + "taintPartialContexts" ], "path_sens": [ "mutex", @@ -80,7 +81,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/context-paper-24.json b/conf/context-paper-24.json new file mode 100644 index 0000000000..8789ed68f3 --- /dev/null +++ b/conf/context-paper-24.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + + "ldv_malloc", + + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} diff --git a/conf/contextWidening.json b/conf/context-widening.json similarity index 98% rename from conf/contextWidening.json rename to conf/context-widening.json index 537c1a26ff..05284b2d20 100644 --- a/conf/contextWidening.json +++ b/conf/context-widening.json @@ -30,7 +30,8 @@ "symb_locks", "region", "thread", - "threadJoins" + "threadJoins", + "taintPartialContexts" ], "path_sens": [ "mutex", @@ -81,7 +82,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", diff --git a/conf/loopfreeCallstring.json b/conf/loopfree-callstring.json similarity index 98% rename from conf/loopfreeCallstring.json rename to conf/loopfree-callstring.json index b88c35bbfb..e835b47116 100644 --- a/conf/loopfreeCallstring.json +++ b/conf/loopfree-callstring.json @@ -31,6 +31,7 @@ "region", "thread", "threadJoins", + "taintPartialContexts", "loopfreeCallstring" ], "path_sens": [ @@ -82,7 +83,6 @@ "mallocWrappers", "enums", "congruence", - "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", From e99d03e41342419d47e28f3e81efdcc1291df3ff Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Feb 2024 17:41:14 +0100 Subject: [PATCH 098/128] renamed tests for loopfreeCallstring; small comments; reverted apronDomain-join fix (separate pull request created) --- src/analyses/loopfreeCallstring.ml | 2 +- src/cdomains/apron/apronDomain.apron.ml | 4 +- src/framework/constraints.ml | 6 +- .../81-callstringTracking/list_search-1.i | 567 ------------------ .../01-loopCalling.c | 0 .../02-simpleExample.c | 0 .../03-loopCallingSens.c | 0 .../04-endless_loop.c | 0 .../05-ackermann.c | 0 .../06-multipleCalls.c | 0 .../07-newCallInSet.c | 0 11 files changed, 6 insertions(+), 573 deletions(-) delete mode 100644 tests/regression/81-callstringTracking/list_search-1.i rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/01-loopCalling.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/02-simpleExample.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/03-loopCallingSens.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/04-endless_loop.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/05-ackermann.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/06-multipleCalls.c (100%) rename tests/regression/{81-callstringTracking => 81-loopfree_callstring}/07-newCallInSet.c (100%) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index a86a11f34d..7982b089ba 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -10,7 +10,7 @@ struct let name () = "loopfreeCallstring" module FundecSet = SetDomain.Make (CilType.Fundec) - module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) + module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) module D = Lattice.Prod (FundecList) (FundecSet) module C = D module V = EmptyV diff --git a/src/cdomains/apron/apronDomain.apron.ml b/src/cdomains/apron/apronDomain.apron.ml index 33850f7525..2b8f360bc5 100644 --- a/src/cdomains/apron/apronDomain.apron.ml +++ b/src/cdomains/apron/apronDomain.apron.ml @@ -672,9 +672,9 @@ struct let join x y = (* just to optimize joining folds, which start with bot *) - if is_bot_env x then (* TODO: also for non-empty env *) + if is_bot x then (* TODO: also for non-empty env *) y - else if is_bot_env y then (* TODO: also for non-empty env *) + else if is_bot y then (* TODO: also for non-empty env *) x else ( if M.tracing then M.traceli "apron" "join %a %a\n" pretty x pretty y; diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 47e5a2e52a..56ac2ea654 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -505,7 +505,7 @@ struct end (** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. - If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive)*) + If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive) *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) and module C = Printable.Prod (Printable.Option (S.C) (NoContext)) (Printable.Chain (IntConf)) @@ -531,9 +531,9 @@ struct let of_elt (x, _) = of_elt x end - (* returns context gas value of the given ctx*) + (* returns context gas value of the given ctx *) let cg_val ctx = - (* Note: snd ctx.local = snd (ctx.context ()), but ctx.local must be used here due to initialization*) + (* snd ctx.local = snd (ctx.context ()), but ctx.local must be used here due to initialization *) snd ctx.local let name () = S.name ()^" with context gas" diff --git a/tests/regression/81-callstringTracking/list_search-1.i b/tests/regression/81-callstringTracking/list_search-1.i deleted file mode 100644 index 0261ea61bc..0000000000 --- a/tests/regression/81-callstringTracking/list_search-1.i +++ /dev/null @@ -1,567 +0,0 @@ -extern void abort(void); - -extern void __assert_fail (const char *__assertion, const char *__file, - unsigned int __line, const char *__function) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern void __assert_perror_fail (int __errnum, const char *__file, - unsigned int __line, const char *__function) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern void __assert (const char *__assertion, const char *__file, int __line) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); - -void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "list_search-1.c", 3, __extension__ __PRETTY_FUNCTION__); })); } -void __VERIFIER_assert(int cond) { - if (!(cond)) { - ERROR: {reach_error();abort();} - } - return; -} -typedef unsigned int size_t; -typedef long int wchar_t; - -typedef enum -{ - P_ALL, - P_PID, - P_PGID -} idtype_t; -typedef struct - { - int quot; - int rem; - } div_t; -typedef struct - { - long int quot; - long int rem; - } ldiv_t; -__extension__ typedef struct - { - long long int quot; - long long int rem; - } lldiv_t; -extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ , __leaf__)) ; -extern double atof (const char *__nptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; -extern int atoi (const char *__nptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; -extern long int atol (const char *__nptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; -__extension__ extern long long int atoll (const char *__nptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; -extern double strtod (const char *__restrict __nptr, - char **__restrict __endptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern float strtof (const char *__restrict __nptr, - char **__restrict __endptr) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern long double strtold (const char *__restrict __nptr, - char **__restrict __endptr) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern long int strtol (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern unsigned long int strtoul (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -__extension__ -extern long long int strtoq (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -__extension__ -extern unsigned long long int strtouq (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -__extension__ -extern long long int strtoll (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -__extension__ -extern unsigned long long int strtoull (const char *__restrict __nptr, - char **__restrict __endptr, int __base) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern char *l64a (long int __n) __attribute__ ((__nothrow__ , __leaf__)) ; -extern long int a64l (const char *__s) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; - -typedef unsigned char __u_char; -typedef unsigned short int __u_short; -typedef unsigned int __u_int; -typedef unsigned long int __u_long; -typedef signed char __int8_t; -typedef unsigned char __uint8_t; -typedef signed short int __int16_t; -typedef unsigned short int __uint16_t; -typedef signed int __int32_t; -typedef unsigned int __uint32_t; -__extension__ typedef signed long long int __int64_t; -__extension__ typedef unsigned long long int __uint64_t; -__extension__ typedef long long int __quad_t; -__extension__ typedef unsigned long long int __u_quad_t; -__extension__ typedef long long int __intmax_t; -__extension__ typedef unsigned long long int __uintmax_t; -__extension__ typedef __u_quad_t __dev_t; -__extension__ typedef unsigned int __uid_t; -__extension__ typedef unsigned int __gid_t; -__extension__ typedef unsigned long int __ino_t; -__extension__ typedef __u_quad_t __ino64_t; -__extension__ typedef unsigned int __mode_t; -__extension__ typedef unsigned int __nlink_t; -__extension__ typedef long int __off_t; -__extension__ typedef __quad_t __off64_t; -__extension__ typedef int __pid_t; -__extension__ typedef struct { int __val[2]; } __fsid_t; -__extension__ typedef long int __clock_t; -__extension__ typedef unsigned long int __rlim_t; -__extension__ typedef __u_quad_t __rlim64_t; -__extension__ typedef unsigned int __id_t; -__extension__ typedef long int __time_t; -__extension__ typedef unsigned int __useconds_t; -__extension__ typedef long int __suseconds_t; -__extension__ typedef int __daddr_t; -__extension__ typedef int __key_t; -__extension__ typedef int __clockid_t; -__extension__ typedef void * __timer_t; -__extension__ typedef long int __blksize_t; -__extension__ typedef long int __blkcnt_t; -__extension__ typedef __quad_t __blkcnt64_t; -__extension__ typedef unsigned long int __fsblkcnt_t; -__extension__ typedef __u_quad_t __fsblkcnt64_t; -__extension__ typedef unsigned long int __fsfilcnt_t; -__extension__ typedef __u_quad_t __fsfilcnt64_t; -__extension__ typedef int __fsword_t; -__extension__ typedef int __ssize_t; -__extension__ typedef long int __syscall_slong_t; -__extension__ typedef unsigned long int __syscall_ulong_t; -typedef __off64_t __loff_t; -typedef char *__caddr_t; -__extension__ typedef int __intptr_t; -__extension__ typedef unsigned int __socklen_t; -typedef int __sig_atomic_t; -typedef __u_char u_char; -typedef __u_short u_short; -typedef __u_int u_int; -typedef __u_long u_long; -typedef __quad_t quad_t; -typedef __u_quad_t u_quad_t; -typedef __fsid_t fsid_t; -typedef __loff_t loff_t; -typedef __ino_t ino_t; -typedef __dev_t dev_t; -typedef __gid_t gid_t; -typedef __mode_t mode_t; -typedef __nlink_t nlink_t; -typedef __uid_t uid_t; -typedef __off_t off_t; -typedef __pid_t pid_t; -typedef __id_t id_t; -typedef __ssize_t ssize_t; -typedef __daddr_t daddr_t; -typedef __caddr_t caddr_t; -typedef __key_t key_t; -typedef __clock_t clock_t; -typedef __clockid_t clockid_t; -typedef __time_t time_t; -typedef __timer_t timer_t; -typedef unsigned long int ulong; -typedef unsigned short int ushort; -typedef unsigned int uint; -typedef __int8_t int8_t; -typedef __int16_t int16_t; -typedef __int32_t int32_t; -typedef __int64_t int64_t; -typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__))); -typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__))); -typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__))); -typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__))); -typedef int register_t __attribute__ ((__mode__ (__word__))); -static __inline unsigned int -__bswap_32 (unsigned int __bsx) -{ - return __builtin_bswap32 (__bsx); -} -static __inline __uint64_t -__bswap_64 (__uint64_t __bsx) -{ - return __builtin_bswap64 (__bsx); -} -static __inline __uint16_t -__uint16_identity (__uint16_t __x) -{ - return __x; -} -static __inline __uint32_t -__uint32_identity (__uint32_t __x) -{ - return __x; -} -static __inline __uint64_t -__uint64_identity (__uint64_t __x) -{ - return __x; -} -typedef struct -{ - unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; -} __sigset_t; -typedef __sigset_t sigset_t; -struct timeval -{ - __time_t tv_sec; - __suseconds_t tv_usec; -}; -struct timespec -{ - __time_t tv_sec; - __syscall_slong_t tv_nsec; -}; -typedef __suseconds_t suseconds_t; -typedef long int __fd_mask; -typedef struct - { - __fd_mask __fds_bits[1024 / (8 * (int) sizeof (__fd_mask))]; - } fd_set; -typedef __fd_mask fd_mask; - -extern int select (int __nfds, fd_set *__restrict __readfds, - fd_set *__restrict __writefds, - fd_set *__restrict __exceptfds, - struct timeval *__restrict __timeout); -extern int pselect (int __nfds, fd_set *__restrict __readfds, - fd_set *__restrict __writefds, - fd_set *__restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t *__restrict __sigmask); - - -extern unsigned int gnu_dev_major (__dev_t __dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); -extern unsigned int gnu_dev_minor (__dev_t __dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); -extern __dev_t gnu_dev_makedev (unsigned int __major, unsigned int __minor) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); - -typedef __blksize_t blksize_t; -typedef __blkcnt_t blkcnt_t; -typedef __fsblkcnt_t fsblkcnt_t; -typedef __fsfilcnt_t fsfilcnt_t; -struct __pthread_rwlock_arch_t -{ - unsigned int __readers; - unsigned int __writers; - unsigned int __wrphase_futex; - unsigned int __writers_futex; - unsigned int __pad3; - unsigned int __pad4; - unsigned char __flags; - unsigned char __shared; - signed char __rwelision; - unsigned char __pad2; - int __cur_writer; -}; -typedef struct __pthread_internal_slist -{ - struct __pthread_internal_slist *__next; -} __pthread_slist_t; -struct __pthread_mutex_s -{ - int __lock ; - unsigned int __count; - int __owner; - int __kind; - - unsigned int __nusers; - __extension__ union - { - struct { short __espins; short __eelision; } __elision_data; - __pthread_slist_t __list; - }; - -}; -struct __pthread_cond_s -{ - __extension__ union - { - __extension__ unsigned long long int __wseq; - struct - { - unsigned int __low; - unsigned int __high; - } __wseq32; - }; - __extension__ union - { - __extension__ unsigned long long int __g1_start; - struct - { - unsigned int __low; - unsigned int __high; - } __g1_start32; - }; - unsigned int __g_refs[2] ; - unsigned int __g_size[2]; - unsigned int __g1_orig_size; - unsigned int __wrefs; - unsigned int __g_signals[2]; -}; -typedef unsigned long int pthread_t; -typedef union -{ - char __size[4]; - int __align; -} pthread_mutexattr_t; -typedef union -{ - char __size[4]; - int __align; -} pthread_condattr_t; -typedef unsigned int pthread_key_t; -typedef int pthread_once_t; -union pthread_attr_t -{ - char __size[36]; - long int __align; -}; -typedef union pthread_attr_t pthread_attr_t; -typedef union -{ - struct __pthread_mutex_s __data; - char __size[24]; - long int __align; -} pthread_mutex_t; -typedef union -{ - struct __pthread_cond_s __data; - char __size[48]; - __extension__ long long int __align; -} pthread_cond_t; -typedef union -{ - struct __pthread_rwlock_arch_t __data; - char __size[32]; - long int __align; -} pthread_rwlock_t; -typedef union -{ - char __size[8]; - long int __align; -} pthread_rwlockattr_t; -typedef volatile int pthread_spinlock_t; -typedef union -{ - char __size[20]; - long int __align; -} pthread_barrier_t; -typedef union -{ - char __size[4]; - int __align; -} pthread_barrierattr_t; - -extern long int random (void) __attribute__ ((__nothrow__ , __leaf__)); -extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__)); -extern char *initstate (unsigned int __seed, char *__statebuf, - size_t __statelen) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); -extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -struct random_data - { - int32_t *fptr; - int32_t *rptr; - int32_t *state; - int rand_type; - int rand_deg; - int rand_sep; - int32_t *end_ptr; - }; -extern int random_r (struct random_data *__restrict __buf, - int32_t *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int srandom_r (unsigned int __seed, struct random_data *__buf) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); -extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, - size_t __statelen, - struct random_data *__restrict __buf) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4))); -extern int setstate_r (char *__restrict __statebuf, - struct random_data *__restrict __buf) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int rand (void) __attribute__ ((__nothrow__ , __leaf__)); -extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__)); -extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ , __leaf__)); -extern double drand48 (void) __attribute__ ((__nothrow__ , __leaf__)); -extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern long int lrand48 (void) __attribute__ ((__nothrow__ , __leaf__)); -extern long int nrand48 (unsigned short int __xsubi[3]) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern long int mrand48 (void) __attribute__ ((__nothrow__ , __leaf__)); -extern long int jrand48 (unsigned short int __xsubi[3]) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ , __leaf__)); -extern unsigned short int *seed48 (unsigned short int __seed16v[3]) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -struct drand48_data - { - unsigned short int __x[3]; - unsigned short int __old_x[3]; - unsigned short int __c; - unsigned short int __init; - __extension__ unsigned long long int __a; - }; -extern int drand48_r (struct drand48_data *__restrict __buffer, - double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int erand48_r (unsigned short int __xsubi[3], - struct drand48_data *__restrict __buffer, - double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int lrand48_r (struct drand48_data *__restrict __buffer, - long int *__restrict __result) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int nrand48_r (unsigned short int __xsubi[3], - struct drand48_data *__restrict __buffer, - long int *__restrict __result) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int mrand48_r (struct drand48_data *__restrict __buffer, - long int *__restrict __result) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int jrand48_r (unsigned short int __xsubi[3], - struct drand48_data *__restrict __buffer, - long int *__restrict __result) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int srand48_r (long int __seedval, struct drand48_data *__buffer) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); -extern int seed48_r (unsigned short int __seed16v[3], - struct drand48_data *__buffer) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern int lcong48_r (unsigned short int __param[7], - struct drand48_data *__buffer) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; -extern void *calloc (size_t __nmemb, size_t __size) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; -extern void *realloc (void *__ptr, size_t __size) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__warn_unused_result__)); -extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__)); - -extern void *alloca (size_t __size) __attribute__ ((__nothrow__ , __leaf__)); - -extern void *valloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; -extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; -extern void *aligned_alloc (size_t __alignment, size_t __size) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__alloc_size__ (2))) ; -extern void abort (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern int at_quick_exit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern void exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern void quick_exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern void _Exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -extern char *getenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; -extern int putenv (char *__string) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern int setenv (const char *__name, const char *__value, int __replace) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); -extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern int clearenv (void) __attribute__ ((__nothrow__ , __leaf__)); -extern char *mktemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -extern int mkstemp (char *__template) __attribute__ ((__nonnull__ (1))) ; -extern int mkstemps (char *__template, int __suffixlen) __attribute__ ((__nonnull__ (1))) ; -extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; -extern int system (const char *__command) ; -extern char *realpath (const char *__restrict __name, - char *__restrict __resolved) __attribute__ ((__nothrow__ , __leaf__)) ; -typedef int (*__compar_fn_t) (const void *, const void *); -extern void *bsearch (const void *__key, const void *__base, - size_t __nmemb, size_t __size, __compar_fn_t __compar) - __attribute__ ((__nonnull__ (1, 2, 5))) ; -extern void qsort (void *__base, size_t __nmemb, size_t __size, - __compar_fn_t __compar) __attribute__ ((__nonnull__ (1, 4))); -extern int abs (int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -extern long int labs (long int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -__extension__ extern long long int llabs (long long int __x) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -extern div_t div (int __numer, int __denom) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -extern ldiv_t ldiv (long int __numer, long int __denom) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -__extension__ extern lldiv_t lldiv (long long int __numer, - long long int __denom) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ; -extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, - int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; -extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, - int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; -extern char *gcvt (double __value, int __ndigit, char *__buf) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ; -extern char *qecvt (long double __value, int __ndigit, - int *__restrict __decpt, int *__restrict __sign) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; -extern char *qfcvt (long double __value, int __ndigit, - int *__restrict __decpt, int *__restrict __sign) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ; -extern char *qgcvt (long double __value, int __ndigit, char *__buf) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ; -extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, - int *__restrict __sign, char *__restrict __buf, - size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); -extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, - int *__restrict __sign, char *__restrict __buf, - size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); -extern int qecvt_r (long double __value, int __ndigit, - int *__restrict __decpt, int *__restrict __sign, - char *__restrict __buf, size_t __len) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); -extern int qfcvt_r (long double __value, int __ndigit, - int *__restrict __decpt, int *__restrict __sign, - char *__restrict __buf, size_t __len) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5))); -extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); -extern int mbtowc (wchar_t *__restrict __pwc, - const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); -extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ , __leaf__)); -extern size_t mbstowcs (wchar_t *__restrict __pwcs, - const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); -extern size_t wcstombs (char *__restrict __s, - const wchar_t *__restrict __pwcs, size_t __n) - __attribute__ ((__nothrow__ , __leaf__)); -extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ; -extern int getsubopt (char **__restrict __optionp, - char *const *__restrict __tokens, - char **__restrict __valuep) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2, 3))) ; -extern int getloadavg (double __loadavg[], int __nelem) - __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); - -typedef struct list { - int key; - struct list *next; -} mlist; -mlist *head; -mlist* search_list(mlist *l, int k){ - l = head; - while(l!=((void *)0) && l->key!=k) { - l = l->next; - } - return l; -} -int insert_list(mlist *l, int k){ - l = (mlist*)malloc(sizeof(mlist)); - l->key = k; - if (head==((void *)0)) { - l->next = ((void *)0); - } else { - l->key = k; - l->next = head; - } - head = l; - return 0; -} -int main(void){ - int i; - mlist *mylist, *temp; - insert_list(mylist,2); - insert_list(mylist,5); - insert_list(mylist,1); - insert_list(mylist,3); - temp = search_list(head,2); - __VERIFIER_assert(temp->key==1); - while(head!=0) { - mlist *tmp = head->next; - free(head); - head = tmp; - } -} \ No newline at end of file diff --git a/tests/regression/81-callstringTracking/01-loopCalling.c b/tests/regression/81-loopfree_callstring/01-loopCalling.c similarity index 100% rename from tests/regression/81-callstringTracking/01-loopCalling.c rename to tests/regression/81-loopfree_callstring/01-loopCalling.c diff --git a/tests/regression/81-callstringTracking/02-simpleExample.c b/tests/regression/81-loopfree_callstring/02-simpleExample.c similarity index 100% rename from tests/regression/81-callstringTracking/02-simpleExample.c rename to tests/regression/81-loopfree_callstring/02-simpleExample.c diff --git a/tests/regression/81-callstringTracking/03-loopCallingSens.c b/tests/regression/81-loopfree_callstring/03-loopCallingSens.c similarity index 100% rename from tests/regression/81-callstringTracking/03-loopCallingSens.c rename to tests/regression/81-loopfree_callstring/03-loopCallingSens.c diff --git a/tests/regression/81-callstringTracking/04-endless_loop.c b/tests/regression/81-loopfree_callstring/04-endless_loop.c similarity index 100% rename from tests/regression/81-callstringTracking/04-endless_loop.c rename to tests/regression/81-loopfree_callstring/04-endless_loop.c diff --git a/tests/regression/81-callstringTracking/05-ackermann.c b/tests/regression/81-loopfree_callstring/05-ackermann.c similarity index 100% rename from tests/regression/81-callstringTracking/05-ackermann.c rename to tests/regression/81-loopfree_callstring/05-ackermann.c diff --git a/tests/regression/81-callstringTracking/06-multipleCalls.c b/tests/regression/81-loopfree_callstring/06-multipleCalls.c similarity index 100% rename from tests/regression/81-callstringTracking/06-multipleCalls.c rename to tests/regression/81-loopfree_callstring/06-multipleCalls.c diff --git a/tests/regression/81-callstringTracking/07-newCallInSet.c b/tests/regression/81-loopfree_callstring/07-newCallInSet.c similarity index 100% rename from tests/regression/81-callstringTracking/07-newCallInSet.c rename to tests/regression/81-loopfree_callstring/07-newCallInSet.c From 6c5e2f631aadcbd0c4bb9b49b938b3620bc05273 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Feb 2024 11:58:16 +0100 Subject: [PATCH 099/128] callstack can be infinite --- src/analyses/callstringAnalysis.ml | 17 ++++++++------ src/config/options.schema.json | 8 ++++++- ...-simple_rec_sens.c => 01-simple_rec_ins.c} | 4 ++-- .../82-callstring_Fundec/13-thread_creation.c | 2 +- .../14-thread_creation_problem.c | 4 ++-- .../16-simple_rec_inf_callstack.c} | 4 ++-- .../01-simple_rec_inf_callstack.c | 22 +++++++++++++++++++ .../83-callstring_Stmt/09-thread_creation.c | 4 ++-- .../01-simple_rec_inf_callstack.c} | 4 ++-- .../84-callstring_Loc/09-thread_creation.c | 4 ++-- 10 files changed, 52 insertions(+), 21 deletions(-) rename tests/regression/82-callstring_Fundec/{01-simple_rec_sens.c => 01-simple_rec_ins.c} (83%) rename tests/regression/{84-callstring_Loc/01-simple_rec_sens.c => 82-callstring_Fundec/16-simple_rec_inf_callstack.c} (59%) create mode 100644 tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c rename tests/regression/{83-callstring_Stmt/01-simple_rec_sens.c => 84-callstring_Loc/01-simple_rec_inf_callstack.c} (59%) diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstringAnalysis.ml index 294fad6b35..a7d4dc0922 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstringAnalysis.ml @@ -20,16 +20,19 @@ struct module CallStack = struct include Printable.PQueue (CT) - let push stack elem = (* pushes elem to the call-stack, guarantees a depth of k *) + let push stack elem = (* pushes elem to the call-stack, guarantees a depth of k if inf_callStack = false*) match elem with | None -> stack | Some e -> - let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) - (* removes element from stack, if stack was filled with k elements *) - match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with - | x when x <= 0 -> new_stack - | 1 -> fst @@ Option.get (BatDeque.rear new_stack) - | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" + let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) + if get_bool "ana.context.inf_callStack" + then new_stack (* infinite call-stack*) + else + (* removes element from stack, if stack was filled with k elements *) + match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with + | x when x <= 0 -> new_stack + | 1 -> fst @@ Option.get (BatDeque.rear new_stack) + | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" end module D = Lattice.Flat (CallStack) (* should be the CallStack (C=D). Since a Lattice is required, Lattice.Flat is used to fulfill the type *) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 64bd6ee2e4..e77cd36b89 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -976,9 +976,15 @@ "type": "integer", "default": 10 }, + "inf_callStack": { + "title": "ana.context.inf_callStack", + "description": "If true, the call-stack of the call.string analysis is infinite.", + "type": "boolean", + "default": false + }, "callStack_height": { "title": "ana.context.callStack_height", - "description": "Height of the CallStack that should be used as context for the callstring analysis. Must be >= 0!", + "description": "Height of the call-stack that should be used as context for the call-string analysis. Must be >= 0!", "type": "integer", "default": 10 } diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/01-simple_rec_ins.c similarity index 83% rename from tests/regression/82-callstring_Fundec/01-simple_rec_sens.c rename to tests/regression/82-callstring_Fundec/01-simple_rec_ins.c index 5c7f4858b5..eb821ccbd6 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/01-simple_rec_ins.c @@ -2,7 +2,7 @@ // Basic example #include -int num_iterat = 9; +int num_iterat = 10; int a = 20; int f(int i) @@ -18,5 +18,5 @@ int f(int i) int main(void) { f(num_iterat); - __goblint_check(a == 0); + __goblint_check(a == 0); //UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/13-thread_creation.c b/tests/regression/82-callstring_Fundec/13-thread_creation.c index 12ca0155ac..7c4ef3960b 100644 --- a/tests/regression/82-callstring_Fundec/13-thread_creation.c +++ b/tests/regression/82-callstring_Fundec/13-thread_creation.c @@ -84,7 +84,7 @@ int main() pthread_t id2; pthread_t id3; - // Creat the thread + // Create the thread pthread_create(&id, NULL, t_sens, NULL); pthread_create(&id2, NULL, t_sens2, NULL); pthread_create(&id3, NULL, t_insens, NULL); diff --git a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c index db46283df7..eaaebb4b21 100644 --- a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c +++ b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c @@ -79,11 +79,11 @@ int main() pthread_t id; pthread_t id2; - // Creat the thread + // Create the thread pthread_create(&id, NULL, t_sens, NULL); // pthread_join(id, NULL); - // Creat the thread + // Create the thread pthread_create(&id2, NULL, t_insens, NULL); return 0; } diff --git a/tests/regression/84-callstring_Loc/01-simple_rec_sens.c b/tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c similarity index 59% rename from tests/regression/84-callstring_Loc/01-simple_rec_sens.c rename to tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c index 046804d2aa..c2aee8e701 100644 --- a/tests/regression/84-callstring_Loc/01-simple_rec_sens.c +++ b/tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c @@ -1,8 +1,8 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --enable ana.context.inf_callStack // Basic example #include -int num_iterat = 10; +int num_iterat = 25; int a = 20; int f(int i) diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c b/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c new file mode 100644 index 0000000000..13cf70be57 --- /dev/null +++ b/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.context.inf_callStack --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// Basic example +#include + +int num_iterat = 15; +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(num_iterat); + __goblint_check(a == 0); +} diff --git a/tests/regression/83-callstring_Stmt/09-thread_creation.c b/tests/regression/83-callstring_Stmt/09-thread_creation.c index fdcbdaf5c6..a80aab4386 100644 --- a/tests/regression/83-callstring_Stmt/09-thread_creation.c +++ b/tests/regression/83-callstring_Stmt/09-thread_creation.c @@ -79,10 +79,10 @@ int main() pthread_t id; pthread_t id2; - // Creat the thread + // Create the thread pthread_create(&id, NULL, t_sens, NULL); - // Creat the thread + // Create the thread pthread_create(&id2, NULL, t_insens, NULL); return 0; } diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c b/tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c similarity index 59% rename from tests/regression/83-callstring_Stmt/01-simple_rec_sens.c rename to tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c index aa480aec1c..02f2bdb78f 100644 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_sens.c +++ b/tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c @@ -1,8 +1,8 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set +// PARAM: --enable ana.context.inf_callStack --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set // Basic example #include -int num_iterat = 10; +int num_iterat = 15; int a = 20; int f(int i) diff --git a/tests/regression/84-callstring_Loc/09-thread_creation.c b/tests/regression/84-callstring_Loc/09-thread_creation.c index 3464d0fe86..1367e19374 100644 --- a/tests/regression/84-callstring_Loc/09-thread_creation.c +++ b/tests/regression/84-callstring_Loc/09-thread_creation.c @@ -79,10 +79,10 @@ int main() pthread_t id; pthread_t id2; - // Creat the thread + // Create the thread pthread_create(&id, NULL, t_sens, NULL); - // Creat the thread + // Create the thread pthread_create(&id2, NULL, t_insens, NULL); return 0; } From e92d803a784147b5683e0d4ccd6e797fa659020c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Feb 2024 12:06:53 +0100 Subject: [PATCH 100/128] added configs for inf callstack --- conf/callstring-fundec.json | 1 + conf/callstring-fundec_inf.json | 145 ++++++++++++++++++++++++++++++++ conf/callstring-loc.json | 1 + conf/callstring-loc_inf.json | 145 ++++++++++++++++++++++++++++++++ conf/callstring-stmt.json | 1 + conf/callstring-stmt_inf.json | 145 ++++++++++++++++++++++++++++++++ 6 files changed, 438 insertions(+) create mode 100644 conf/callstring-fundec_inf.json create mode 100644 conf/callstring-loc_inf.json create mode 100644 conf/callstring-stmt_inf.json diff --git a/conf/callstring-fundec.json b/conf/callstring-fundec.json index cc0489e310..dc05393683 100644 --- a/conf/callstring-fundec.json +++ b/conf/callstring-fundec.json @@ -46,6 +46,7 @@ "context": { "widen": false, "ctx_gas": false, + "inf_callStack": false, "callStack_height": 10 }, "malloc": { diff --git a/conf/callstring-fundec_inf.json b/conf/callstring-fundec_inf.json new file mode 100644 index 0000000000..823e886eec --- /dev/null +++ b/conf/callstring-fundec_inf.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "callstring_fundec" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "inf_callStack": true + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-loc.json b/conf/callstring-loc.json index de08c4dee2..4a1ffdb7ff 100644 --- a/conf/callstring-loc.json +++ b/conf/callstring-loc.json @@ -46,6 +46,7 @@ "context": { "widen": false, "ctx_gas": false, + "inf_callStack": false, "callStack_height": 10 }, "malloc": { diff --git a/conf/callstring-loc_inf.json b/conf/callstring-loc_inf.json new file mode 100644 index 0000000000..e51aa10db8 --- /dev/null +++ b/conf/callstring-loc_inf.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "callstring_loc" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "inf_callStack": true + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-stmt.json b/conf/callstring-stmt.json index 165a726e0b..2c2ee553bf 100644 --- a/conf/callstring-stmt.json +++ b/conf/callstring-stmt.json @@ -46,6 +46,7 @@ "context": { "widen": false, "ctx_gas": false, + "inf_callStack": false, "callStack_height": 10 }, "malloc": { diff --git a/conf/callstring-stmt_inf.json b/conf/callstring-stmt_inf.json new file mode 100644 index 0000000000..63b15b4a12 --- /dev/null +++ b/conf/callstring-stmt_inf.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "callstring_stmt" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "ctx_gas": false, + "inf_callStack": true + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file From b851dedaf51022acf40d5d5f7762cc656d8d4793 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 11 Feb 2024 10:48:09 +0100 Subject: [PATCH 101/128] changed loopfreeCallstring analysis to have multiple lists and sets, adapted testcases; renamed to loopfree_callstring --- conf/loopfree-callstring.json | 2 +- src/analyses/loopfreeCallstring.ml | 81 +++++++++++++++---- src/analyses/mCP.ml | 2 +- .../81-loopfree_callstring/01-loopCalling.c | 34 -------- .../01-loop_calling_sens.c | 25 ++++++ .../02-loop_calling_ins.c | 30 +++++++ .../81-loopfree_callstring/02-simpleExample.c | 34 -------- .../{05-ackermann.c => 03-ackermann.c} | 3 +- .../03-loopCallingSens.c | 34 -------- .../81-loopfree_callstring/04-endless_loop.c | 6 +- .../05-multiple_calls_base_sens.c | 57 +++++++++++++ .../81-loopfree_callstring/06-multipleCalls.c | 61 -------------- .../06-multiple_calls_sens.c | 57 +++++++++++++ .../07-multiple_calls_ins.c | 57 +++++++++++++ .../81-loopfree_callstring/07-newCallInSet.c | 39 --------- .../08-new_calling_set.c | 36 +++++++++ .../09-many_nested_loops.c | 78 ++++++++++++++++++ .../81-loopfree_callstring/10-nested_loops.c | 32 ++++++++ 18 files changed, 445 insertions(+), 223 deletions(-) delete mode 100644 tests/regression/81-loopfree_callstring/01-loopCalling.c create mode 100644 tests/regression/81-loopfree_callstring/01-loop_calling_sens.c create mode 100644 tests/regression/81-loopfree_callstring/02-loop_calling_ins.c delete mode 100644 tests/regression/81-loopfree_callstring/02-simpleExample.c rename tests/regression/81-loopfree_callstring/{05-ackermann.c => 03-ackermann.c} (74%) delete mode 100644 tests/regression/81-loopfree_callstring/03-loopCallingSens.c create mode 100644 tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c delete mode 100644 tests/regression/81-loopfree_callstring/06-multipleCalls.c create mode 100644 tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c create mode 100644 tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c delete mode 100644 tests/regression/81-loopfree_callstring/07-newCallInSet.c create mode 100644 tests/regression/81-loopfree_callstring/08-new_calling_set.c create mode 100644 tests/regression/81-loopfree_callstring/09-many_nested_loops.c create mode 100644 tests/regression/81-loopfree_callstring/10-nested_loops.c diff --git a/conf/loopfree-callstring.json b/conf/loopfree-callstring.json index e835b47116..226ebd841d 100644 --- a/conf/loopfree-callstring.json +++ b/conf/loopfree-callstring.json @@ -32,7 +32,7 @@ "thread", "threadJoins", "taintPartialContexts", - "loopfreeCallstring" + "loopfree_callstring" ], "path_sens": [ "mutex", diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 7982b089ba..188262d48c 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -7,27 +7,76 @@ module Spec : MCPSpec = struct include Analyses.IdentitySpec - let name () = "loopfreeCallstring" + let name () = "loopfree_callstring" module FundecSet = SetDomain.Make (CilType.Fundec) - module FundecList = Lattice.Flat(Printable.Liszt(CilType.Fundec)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) - module D = Lattice.Prod (FundecList) (FundecSet) + module FundecList = Printable.Liszt (CilType.Fundec) + module Either = struct + include Lattice.Flat (Printable.Either (FundecList) (FundecSet)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) + + let printXml f = function + | `Lifted x -> + begin + match x with + | `Left x -> BatPrintf.fprintf f "stack:\n%a" FundecList.printXml x + | `Right x -> BatPrintf.fprintf f "set:\n%a" FundecSet.printXml x + end; + | _ -> failwith "Error loopfreeCallstring (printXml): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" + end + module D = Lattice.Liszt (Either) module C = D module V = EmptyV module G = Lattice.Unit - let startstate v = D.bot () - let exitstate v = D.bot () - - let get_list l = match l with - | `Lifted l -> l - | `Bot -> [] - | `Top -> failwith "loopfreeCallstring Error: the value of the Flat List shouldn't be top!" - - let callee_state f ctx = - let (stack, set) = ctx.local in - if (not(FundecSet.is_empty set)) || List.mem f (get_list stack) - then (stack, FundecSet.add f set) - else (`Lifted (f::(get_list stack)), set) + let startstate v = [] + let exitstate v = [] + + let get_either either = match either with + | `Lifted e -> e + | _ -> failwith "Error loopfreeCallstring (get_either): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" + + let list_after_split f stack rem_list = + let rec stack_split set (hd::rest) = + if CilType.Fundec.equal hd f + then (FundecSet.add hd set), (rest) + else stack_split (FundecSet.add hd set) rest + in + let set, new_stack = stack_split (FundecSet.empty ()) stack in + set, `Lifted(`Left new_stack)::rem_list + + let append_elem_at_end new_list f = + match new_list with + | [] -> [(`Lifted(`Left [f]))] + | x::xs -> + begin + match get_either x with + | `Left stack -> (`Lifted(`Left (f::stack)))::xs + | `Right set -> (`Lifted(`Left [f]))::new_list + end + + let rec callee_state f prev_set prev_list cur_list = + match cur_list with + | [] -> append_elem_at_end (List.rev prev_list) f + | e::rem_list -> + begin + match get_either e with + | `Left stack -> + if List.mem f stack + then (let set, new_stack = list_after_split f stack rem_list in + let new_set = FundecSet.join prev_set set in + (`Lifted(`Right new_set))::new_stack) + else + (let new_prev_set = FundecSet.join prev_set (FundecSet.of_list stack) in + let new_prev_list = `Lifted(`Left stack)::prev_list in + callee_state f new_prev_set new_prev_list rem_list) + | `Right set -> + let new_set = FundecSet.join prev_set set in + if FundecSet.mem f set + then (`Lifted(`Right new_set))::rem_list + else (let new_prev_list = `Lifted(`Right set)::prev_list in + callee_state f new_set new_prev_list rem_list) + end + + let callee_state f ctx = callee_state f (FundecSet.empty ()) [] ctx.local let enter ctx r f args = [ctx.local, callee_state f ctx] diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 9e987a2033..15ba5e7570 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -67,7 +67,7 @@ struct let specific_cont_sens xs = (* most analysis must be set to context-insensitive, because we only want to analyse context-sensitive for one specific analysis *) - let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "loopfreeCallstring"] in + let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "loopfree_callstring"] in let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in (* returns the edited list of insensitive analyses if enabled *) if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None diff --git a/tests/regression/81-loopfree_callstring/01-loopCalling.c b/tests/regression/81-loopfree_callstring/01-loopCalling.c deleted file mode 100644 index 6eb7797938..0000000000 --- a/tests/regression/81-loopfree_callstring/01-loopCalling.c +++ /dev/null @@ -1,34 +0,0 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set -// Basic example -#include - -int a; - -int f(int i); - -int g(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int f(int i) -{ - if (i > 0) - { - a = --i; - g(i); - } - return 0; -} - -int main(void) -{ - a = 20; - f(10); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c new file mode 100644 index 0000000000..1c8086732f --- /dev/null +++ b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c @@ -0,0 +1,25 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int f(int i) +{ + return g(i - 1); +} + +int main() +{ + // main -> f(7) -> g(6) -> f(5) -> ... -> f(1) -> g(0) -> return 2 + // [main, f, g] and [main] {f, g} + __goblint_check(f(7) == 2); + return 0; +} diff --git a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c new file mode 100644 index 0000000000..1612742461 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c @@ -0,0 +1,30 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int f(int i) +{ + if (i > 0) + { + return g(i - 1); + } + return 1; +} + +int main(void) +{ + // main -> f(9) -> g(8) -> f(7) -> ... -> g(2) -> f(1) -> g(0) -> return 2 + // [main, f, g] and [main] {f, g} + __goblint_check(f(9) == 2); // UNKNOWN +} diff --git a/tests/regression/81-loopfree_callstring/02-simpleExample.c b/tests/regression/81-loopfree_callstring/02-simpleExample.c deleted file mode 100644 index d7e60ccbe8..0000000000 --- a/tests/regression/81-loopfree_callstring/02-simpleExample.c +++ /dev/null @@ -1,34 +0,0 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 10; -int a = 20; - -int f(int i); - -int g(int i) -{ - if (i > 0) - { - a = --i; - g(i); - } - return 0; -} - -int f(int i) -{ - if (i > 0) - { - a = --i; - g(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/81-loopfree_callstring/05-ackermann.c b/tests/regression/81-loopfree_callstring/03-ackermann.c similarity index 74% rename from tests/regression/81-loopfree_callstring/05-ackermann.c rename to tests/regression/81-loopfree_callstring/03-ackermann.c index 1307aad1f3..c91428e362 100644 --- a/tests/regression/81-loopfree_callstring/05-ackermann.c +++ b/tests/regression/81-loopfree_callstring/03-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set #include int ack(int n, int m) @@ -22,6 +22,7 @@ int ack(int n, int m) int main(void) { + // main -> ack -> ack -> ... ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/81-loopfree_callstring/03-loopCallingSens.c b/tests/regression/81-loopfree_callstring/03-loopCallingSens.c deleted file mode 100644 index 234fbf7e8c..0000000000 --- a/tests/regression/81-loopfree_callstring/03-loopCallingSens.c +++ /dev/null @@ -1,34 +0,0 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set -// Basic example -#include - -int a; - -int f(int i); - -int g(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int f(int i) -{ - if (i > 0) - { - a = --i; - g(i); - } - return 0; -} - -int main(void) -{ - a = 20; - f(3); - __goblint_check(a == 0); -} diff --git a/tests/regression/81-loopfree_callstring/04-endless_loop.c b/tests/regression/81-loopfree_callstring/04-endless_loop.c index 5f77269d50..ecb521038c 100644 --- a/tests/regression/81-loopfree_callstring/04-endless_loop.c +++ b/tests/regression/81-loopfree_callstring/04-endless_loop.c @@ -1,9 +1,11 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis #include int num_iterat = 2; +// main -> main -> ... +// {main} int main(void) { if (num_iterat > 0) @@ -21,4 +23,4 @@ int main(void) } return 2; } -} +} \ No newline at end of file diff --git a/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c new file mode 100644 index 0000000000..68d57d56d9 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c @@ -0,0 +1,57 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(0) -> return 11 + // [main, f] + __goblint_check(f(0) == 11); + + // main -> g(0) -> return 12 + // [main, g] + __goblint_check(g(0) == 12); + + // main -> h(0) -> return 13 + // [main, h] + __goblint_check(h(0) == 13); +} diff --git a/tests/regression/81-loopfree_callstring/06-multipleCalls.c b/tests/regression/81-loopfree_callstring/06-multipleCalls.c deleted file mode 100644 index 8c3279655e..0000000000 --- a/tests/regression/81-loopfree_callstring/06-multipleCalls.c +++ /dev/null @@ -1,61 +0,0 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 3; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - __goblint_check(res1 == 1); // UNKNOWN - int res2 = f(num_iterat); - __goblint_check(res2 == 1); // UNKNOWN - // int res3 = g(num_iterat); - int res4 = h(num_iterat); - __goblint_check(res4 == 1); - - // int result = res1 + res2 + res3 + res4 + res5; - //__goblint_check(result == 5); -} diff --git a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c new file mode 100644 index 0000000000..f8e31c7acc --- /dev/null +++ b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c @@ -0,0 +1,57 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(3) -> ... -> f(0) -> return 11 + // [main, f] and [main] {f} + __goblint_check(f(3) == 11); + + // main -> g(3) -> f(2) -> f(1) -> f(0) -> return 11 + // [main, g, f] and [main, g] {f} + __goblint_check(g(3) == 11); + + // main -> h(5) -> g(4) -> f(3) -> ... -> f(0) -> return 11 + // [main, h, g, f] and [main, h, g] {f} + __goblint_check(h(5) == 11); +} diff --git a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c new file mode 100644 index 0000000000..7e260961af --- /dev/null +++ b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c @@ -0,0 +1,57 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(4) -> f(3) -> f(2) -> f(1) -> f(0) -> return 11 + // [main, f] and [main] {f} + __goblint_check(f(4) == 11); // UNKNOWN + + // main -> g(20) -> f(19) -> ... -> f(0) -> return 11 + // [main, g, f] and [main, g] {f} + __goblint_check(g(20) == 11); // UNKNOWN + + // main -> h(10) -> g(9) -> f(8) -> ... -> f(1) -> f(0) -> return 11 + // [main, h, g, f] and [main, h, g] {f} + __goblint_check(h(10) == 11); // UNKNOWN +} diff --git a/tests/regression/81-loopfree_callstring/07-newCallInSet.c b/tests/regression/81-loopfree_callstring/07-newCallInSet.c deleted file mode 100644 index c2cbc86c0d..0000000000 --- a/tests/regression/81-loopfree_callstring/07-newCallInSet.c +++ /dev/null @@ -1,39 +0,0 @@ -// PARAM: --set "ana.activated[+]" loopfreeCallstring --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 3; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 2) - { - res = f(--i); - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = g(num_iterat); - __goblint_check(res1 == 1); // UNKNOWN -} diff --git a/tests/regression/81-loopfree_callstring/08-new_calling_set.c b/tests/regression/81-loopfree_callstring/08-new_calling_set.c new file mode 100644 index 0000000000..40997e99ce --- /dev/null +++ b/tests/regression/81-loopfree_callstring/08-new_calling_set.c @@ -0,0 +1,36 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 0; +} + +int g(int i) +{ + if (i == 5) + { + return f(i - 1); + } + if (i > 0) + { + return g(i - 1); + } + return 1; +} + +int main(void) +{ + // main -> g(20) -> ... -> g(5) -> f(4) -> ... -> f(0) -> return 1 + // [main] {g, f} + __goblint_check(g(20) == 1); // UNKNOWN +} diff --git a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c new file mode 100644 index 0000000000..fba400e14d --- /dev/null +++ b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c @@ -0,0 +1,78 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int g(int i); + +int c(int i) +{ + if (i == 0) + { + return g(2); + } + else + { + return 4; + } +} + +int b(int i) +{ + return c(i - 1); +} + +int a(int i) +{ + return b(i - 1); +} + +int h(int i) +{ + return g(i - 1); +} + +int f(int i) +{ + if (i <= 0) + { + return h(4); + } + else + { + return f(i - 1); + } +} + +int g(int i) +{ + if (i == 4) + { + return f(3); + } + if (i == 3) + { + return a(2); + } + return b(20); +} + +int m(int i) +{ + return g(i); +} + +int main(void) +{ + // main -> m(4) -> g(4) -> f(3) -> f(2) -> f(1) -> f(0) -> h(4) -> g(3) -> a(2) -> b(1) -> c(0) -> g(2) -> b(20) -> c(19) -> return 4 + // m: [main, m] + // g: [main, m, g] + // f: [main, m, g, f] + // f: [main, m, g] {f} + // h: [main, m, g] {f} [h] + // g: [main, m] {g, f, h} + // a: [main, m] {g, f, h} [a] + // b: [main, m] {g, f, h} [a, b] + // c: [main, m] {g, f, h} [a, b, c] + // g, b, c: [main, m] {g, f, h, a, b, c} + __goblint_check(m(4) == 4); +} diff --git a/tests/regression/81-loopfree_callstring/10-nested_loops.c b/tests/regression/81-loopfree_callstring/10-nested_loops.c new file mode 100644 index 0000000000..23866b3f99 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/10-nested_loops.c @@ -0,0 +1,32 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int h(int i) +{ + return 3; +} + +int g(int i) +{ + return h(i); +} + +int f(int i) +{ + if (i == 0) + { + return g(2); + } + if (i > 0) + { + return f(i - 1); + } +} + +int main(void) +{ + // main -> f(4) -> f(3) -> ... -> f(0) -> g(2) -> h(2) -> return 3 + // [main] {f} [g,h] + __goblint_check(f(4) == 3); // UNKNOWN +} From a7bf70efa4eddfa5f40a6175cc0fe72fceff401b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 11 Feb 2024 15:47:47 +0100 Subject: [PATCH 102/128] deleted context gas from C, is just tracked in ctx.local; updated testcases --- src/framework/constraints.ml | 33 ++++----- .../80-context_gas/01-basic_tests.c | 33 --------- .../01-basic_tests_bound_sens.c | 16 ++++ .../80-context_gas/02-basic_tests_bound_ins.c | 16 ++++ .../02-multiple_function_chain_tests.c | 73 ------------------- .../80-context_gas/03-contextGas0.c | 12 +-- .../80-context_gas/04-contextGasNeg.c | 12 +-- .../80-context_gas/05-circle_call_sens.c | 44 +++++++++++ .../80-context_gas/06-circle_call.c | 51 ------------- .../80-context_gas/06-circle_call_ins.c | 41 +++++++++++ .../80-context_gas/07-loop_unrolling.c | 64 ---------------- ...ursion_sens.c => 07-main_recursion_sens.c} | 0 ...rsion_insens.c => 08-main_recursion_ins.c} | 2 +- .../{10-endless_loop.c => 09-endless_loop.c} | 0 ...d_handling.c => 10-thread_handling_sens.c} | 41 +++++------ .../80-context_gas/11-thread_handling_ins.c | 67 +++++++++++++++++ .../12-multiple_function_chain_sens.c | 51 +++++++++++++ .../13-multiple_function_chain_ins.c | 50 +++++++++++++ .../{05-ackermann.c => 14-ackermann.c} | 0 .../80-context_gas/15-compl_loop_unrolling.c | 32 ++++++++ .../80-context_gas/16-loop_unrolling_sens.c | 33 +++++++++ .../80-context_gas/17-loop_unrolling_ins.c | 25 +++++++ .../18-loop_unrolling_big_loop.c | 26 +++++++ 23 files changed, 438 insertions(+), 284 deletions(-) delete mode 100644 tests/regression/80-context_gas/01-basic_tests.c create mode 100644 tests/regression/80-context_gas/01-basic_tests_bound_sens.c create mode 100644 tests/regression/80-context_gas/02-basic_tests_bound_ins.c delete mode 100644 tests/regression/80-context_gas/02-multiple_function_chain_tests.c create mode 100644 tests/regression/80-context_gas/05-circle_call_sens.c delete mode 100644 tests/regression/80-context_gas/06-circle_call.c create mode 100644 tests/regression/80-context_gas/06-circle_call_ins.c delete mode 100644 tests/regression/80-context_gas/07-loop_unrolling.c rename tests/regression/80-context_gas/{08-main_recursion_sens.c => 07-main_recursion_sens.c} (100%) rename tests/regression/80-context_gas/{09-main_recursion_insens.c => 08-main_recursion_ins.c} (91%) rename tests/regression/80-context_gas/{10-endless_loop.c => 09-endless_loop.c} (100%) rename tests/regression/80-context_gas/{11-thread_handling.c => 10-thread_handling_sens.c} (56%) create mode 100644 tests/regression/80-context_gas/11-thread_handling_ins.c create mode 100644 tests/regression/80-context_gas/12-multiple_function_chain_sens.c create mode 100644 tests/regression/80-context_gas/13-multiple_function_chain_ins.c rename tests/regression/80-context_gas/{05-ackermann.c => 14-ackermann.c} (100%) create mode 100644 tests/regression/80-context_gas/15-compl_loop_unrolling.c create mode 100644 tests/regression/80-context_gas/16-loop_unrolling_sens.c create mode 100644 tests/regression/80-context_gas/17-loop_unrolling_ins.c create mode 100644 tests/regression/80-context_gas/18-loop_unrolling_big_loop.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 56ac2ea654..65ce60f897 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -500,7 +500,7 @@ end module NoContext = struct let name = "no context" end module IntConf = struct - let n () = get_int "ana.context.ctx_gas_value" + 1 + let n () = max_int let names x = Format.asprintf "%d" x end @@ -508,21 +508,20 @@ end If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive) *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) - and module C = Printable.Prod (Printable.Option (S.C) (NoContext)) (Printable.Chain (IntConf)) + and module C = Printable.Option (S.C) (NoContext) and module G = S.G = struct include S - module Context_Gas_Prod (Base1: Printable.S) (Base2: Printable.S) = + module Context_Gas_Prod (Base1: Lattice.S) (Base2: Lattice.S) = struct - include Printable.Prod (Base1) (Base2) + include Lattice.Prod (Base1) (Base2) let printXml f (x,y) = BatPrintf.fprintf f "\n\n\n%s\n\n%a\nContext Gas Value\n\n%a\n\n" (XmlUtil.escape (Base1.name ())) Base1.printXml x Base2.printXml y end - - module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) - module C = Context_Gas_Prod (Printable.Option (S.C) (NoContext)) (Printable.Chain (IntConf)) + module D = Context_Gas_Prod (S.D) (Lattice.Chain (IntConf)) + module C = Printable.Option (S.C) (NoContext) module G = S.G module V = S.V module P = @@ -532,17 +531,15 @@ struct end (* returns context gas value of the given ctx *) - let cg_val ctx = - (* snd ctx.local = snd (ctx.context ()), but ctx.local must be used here due to initialization *) - snd ctx.local + let cg_val ctx = snd ctx.local let name () = S.name ()^" with context gas" - let startstate v = S.startstate v, (get_int "ana.context.ctx_gas_value") - let exitstate v = S.exitstate v, (get_int "ana.context.ctx_gas_value") (* TODO: probably doesn't matter*) + let startstate v = S.startstate v, get_int "ana.context.ctx_gas_value" + let exitstate v = S.exitstate v, get_int "ana.context.ctx_gas_value" (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = - if i <= 0 then (None, 0) else ((Some (S.context fd d)), i) + if i <= 0 then None else Some (S.context fd d) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = if (cg_val ctx <= 0) @@ -551,7 +548,7 @@ struct ; context = (fun () -> ctx_failwith "no context (contextGas = 0)")} else {ctx with local = fst ctx.local ; split = (fun d es -> ctx.split (d, cg_val ctx) es) - ; context = (fun () -> Option.get (fst (ctx.context ())))} + ; context = (fun () -> Option.get (ctx.context ()))} let enter ctx r f args = let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in @@ -561,8 +558,6 @@ struct let liftmap f = List.map (fun (x) -> (x, max 0 (cg_val ctx - 1))) f in liftmap (S.threadenter (conv ctx) ~multiple lval f args) - let liftmap f ctx = List.map (fun (x) -> (x, cg_val ctx)) f - let sync ctx reason = S.sync (conv ctx) reason, cg_val ctx let query ctx q = S.query (conv ctx) q let assign ctx lval expr = S.assign (conv ctx) lval expr, cg_val ctx @@ -573,9 +568,9 @@ struct let asm ctx = S.asm (conv ctx), cg_val ctx let skip ctx = S.skip (conv ctx), cg_val ctx let special ctx r f args = S.special (conv ctx) r f args, cg_val ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> fst x)) (fst es) f_ask, cg_val ctx - let paths_as_set ctx = liftmap (S.paths_as_set (conv ctx)) ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) (fst es) f_ask, cg_val ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) (fst es) f_ask, cg_val ctx + let paths_as_set ctx = List.map (fun (x) -> (x, cg_val ctx)) @@ S.paths_as_set (conv ctx) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx end diff --git a/tests/regression/80-context_gas/01-basic_tests.c b/tests/regression/80-context_gas/01-basic_tests.c deleted file mode 100644 index 59c9f82981..0000000000 --- a/tests/regression/80-context_gas/01-basic_tests.c +++ /dev/null @@ -1,33 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 -// Basic examples - -int f(int x, int y) -{ - if (x == 0) - { - - return y; - } - return f(--x, --y); -} - -int main() -{ - int y = f(0, 0); - __goblint_check(y == 0); - - int y = f(5, 5); - __goblint_check(y == 0); - - int y = f(7, 7); - __goblint_check(y == 0); // boundary (included) - - int y = f(8, 8); - __goblint_check(y == 0); // UNKNOWN //boundary (excluded) - - int y = f(10, 10); - __goblint_check(y == 0); // UNKNOWN - - int y = f(1000, 1000); - __goblint_check(y == 0); // UNKNOWN -} \ No newline at end of file diff --git a/tests/regression/80-context_gas/01-basic_tests_bound_sens.c b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c new file mode 100644 index 0000000000..dcc48381fb --- /dev/null +++ b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c @@ -0,0 +1,16 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// Basic examples + +int f(int x, int y) +{ + if (x == 0) + { + return y; + } + return f(x - 1, y - 1); +} + +int main() +{ + __goblint_check(f(8, 8) == 0); // boundary (included) +} \ No newline at end of file diff --git a/tests/regression/80-context_gas/02-basic_tests_bound_ins.c b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c new file mode 100644 index 0000000000..0cfa24f5c1 --- /dev/null +++ b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c @@ -0,0 +1,16 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// Basic examples + +int f(int x, int y) +{ + if (x == 0) + { + return y; + } + return f(x - 1, y - 1); +} + +int main() +{ + __goblint_check(f(9, 9) == 0); // UNKNOWN //boundary (excluded) +} \ No newline at end of file diff --git a/tests/regression/80-context_gas/02-multiple_function_chain_tests.c b/tests/regression/80-context_gas/02-multiple_function_chain_tests.c deleted file mode 100644 index 912425d2fb..0000000000 --- a/tests/regression/80-context_gas/02-multiple_function_chain_tests.c +++ /dev/null @@ -1,73 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 -// Tests multiple recursive function calls -#include - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - __goblint_check(f(-5) == 0); - __goblint_check(f(0) == 3); - __goblint_check(f(1) == 2); - __goblint_check(f(2) == 1); - __goblint_check(f(7) == 1); // boundary (included) - __goblint_check(f(8) == 1); // UNKNOWN //boundary (excluded) - __goblint_check(f(20) == 1); // UNKNOWN - - __goblint_check(g(-10) == 0); - __goblint_check(g(0) == 2); - __goblint_check(g(1) == 1); - - __goblint_check(h(-10) == 0); - __goblint_check(h(0) == 1); - __goblint_check(h(7) == 1); // boundary (included) - __goblint_check(h(8) == 1); // UNKNOWN //boundary (excluded) - - int res1 = h(5); - int res2 = h(4); - int result = res1 + res2; - __goblint_check(result == 2); - - __goblint_check(f(g(h(7))) == 2); // h(7) = 1; g(1) = 1; f(1) = 2; - __goblint_check(f(g(h(8))) == 2); // UNKNOWN // h(8) = UNKNOWN -} diff --git a/tests/regression/80-context_gas/03-contextGas0.c b/tests/regression/80-context_gas/03-contextGas0.c index aadb93628c..dc445ba371 100644 --- a/tests/regression/80-context_gas/03-contextGas0.c +++ b/tests/regression/80-context_gas/03-contextGas0.c @@ -4,20 +4,12 @@ int f(int x, int y) { if (x == 0) { - return y; } - return f(--x, --y); + return f(x - 1, y - 1); } int main() { - int y = f(0, 0); - __goblint_check(y == 0); // UNKNOWN - - int y = f(5, 5); - __goblint_check(y == 0); // UNKNOWN - - int y = f(1000, 1000); - __goblint_check(y == 0); // UNKNOWN + __goblint_check(f(1000, 1000) == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-contextGasNeg.c b/tests/regression/80-context_gas/04-contextGasNeg.c index 0cd41b6199..30d2d4f9b2 100644 --- a/tests/regression/80-context_gas/04-contextGasNeg.c +++ b/tests/regression/80-context_gas/04-contextGasNeg.c @@ -4,20 +4,12 @@ int f(int x, int y) { if (x == 0) { - return y; } - return f(--x, --y); + return f(x - 1, y - 1); } int main() { - int y = f(0, 0); - __goblint_check(y == 0); // UNKNOWN - - int y = f(5, 5); - __goblint_check(y == 0); // UNKNOWN - - int y = f(1000, 1000); - __goblint_check(y == 0); // UNKNOWN + __goblint_check(f(5, 5) == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-circle_call_sens.c b/tests/regression/80-context_gas/05-circle_call_sens.c new file mode 100644 index 0000000000..b9a20432a9 --- /dev/null +++ b/tests/regression/80-context_gas/05-circle_call_sens.c @@ -0,0 +1,44 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 +// Checks if recursion in loops is handled properly +#include + +int f(int i); + +int g(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i + 1); + } + return 11; +} + +int f(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 2) + g(i - 3); + } + return 12; +} + +int main(void) +{ + __goblint_check(f(0) == 2); + __goblint_check(f(7) == 101); + __goblint_check(f(9) == 265); + __goblint_check(f(10) == 429); + + __goblint_check(g(0) == 1); + __goblint_check(g(3) == 25); + __goblint_check(g(6) == 101); + __goblint_check(g(8) == 265); +} diff --git a/tests/regression/80-context_gas/06-circle_call.c b/tests/regression/80-context_gas/06-circle_call.c deleted file mode 100644 index 2347ef0b70..0000000000 --- a/tests/regression/80-context_gas/06-circle_call.c +++ /dev/null @@ -1,51 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 -// Checks if recursion in loops is handled properly -#include - -int f(int i); - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(i + 1); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(i - 2) + g(i - 3); - } - return res; -} - -int main(void) -{ - printf("%i, %i\n", f(200), g(10)); - - __goblint_check(f(0) == 2); - __goblint_check(f(3) == 2); - __goblint_check(f(7) == 13); - __goblint_check(f(8) == 21); // UNKNOWN //boundary (excluded) - __goblint_check(f(9) == 34); // UNKNOWN - __goblint_check(f(20) == 6765); // UNKNOWN - - __goblint_check(g(3) == 3); - __goblint_check(g(6) == 13); // boundary (included) - __goblint_check(g(7) == 21); // UNKNOWN - __goblint_check(g(8) == 34); // UNKNOWN - __goblint_check(g(20) == 10946); // UNKNOWN -} diff --git a/tests/regression/80-context_gas/06-circle_call_ins.c b/tests/regression/80-context_gas/06-circle_call_ins.c new file mode 100644 index 0000000000..feb97c1e2c --- /dev/null +++ b/tests/regression/80-context_gas/06-circle_call_ins.c @@ -0,0 +1,41 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 +// Checks if recursion in loops is handled properly +#include + +int f(int i); + +int g(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i + 1); + } + return 11; +} + +int f(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 2) + g(i - 3); + } + return 12; +} + +int main(void) +{ + + __goblint_check(f(13) == 233); // UNKNOWN + __goblint_check(f(20) == 6765); // UNKNOWN + + __goblint_check(g(13) == 377); // UNKNOWN + __goblint_check(g(20) == 10946); // UNKNOWN +} diff --git a/tests/regression/80-context_gas/07-loop_unrolling.c b/tests/regression/80-context_gas/07-loop_unrolling.c deleted file mode 100644 index 4463f0fab3..0000000000 --- a/tests/regression/80-context_gas/07-loop_unrolling.c +++ /dev/null @@ -1,64 +0,0 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 -// TODO -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - for (int i = 1; i > 0; i--) - { - __goblint_check(f(2) == 1); - __goblint_check(f(2000) == 1); // UNKNOWN - } - - // loop should be completely unrolled - for (int i = 3; i > 0; i--) - { - __goblint_check(f(1) == 1); - __goblint_check(f(20) == 1); // UNKNOWN - } - - int res1 = 0; - int res2 = 0; - int result = 0; - - // context sensitive analysis - for (int i = 5; i > 0; i--) - { - res1 = f(3); - res2 = f(i); - __goblint_check(res1 == 1); - __goblint_check(res2 == 1); // TODO - result += res1 + res2; - } - __goblint_check(res1 == 1); - __goblint_check(res2 == 1); // TODO - __goblint_check(result == 10); // TODO - - for (int i = 5; i > 0; i--) - { - __goblint_check(f(0) == 1); - __goblint_check(f(7) == 1); // boundary (included)) - __goblint_check(f(8) == 1); // UNKNOWN //boundary (excluded) - } - - // high number of iterations - for (int i = 500; i > 0; i--) - { - __goblint_check(f(i) == 1); // UNKNOWN - __goblint_check(f(4) == 1); - } -} diff --git a/tests/regression/80-context_gas/08-main_recursion_sens.c b/tests/regression/80-context_gas/07-main_recursion_sens.c similarity index 100% rename from tests/regression/80-context_gas/08-main_recursion_sens.c rename to tests/regression/80-context_gas/07-main_recursion_sens.c diff --git a/tests/regression/80-context_gas/09-main_recursion_insens.c b/tests/regression/80-context_gas/08-main_recursion_ins.c similarity index 91% rename from tests/regression/80-context_gas/09-main_recursion_insens.c rename to tests/regression/80-context_gas/08-main_recursion_ins.c index bd0afdf563..f28ef0cd95 100644 --- a/tests/regression/80-context_gas/09-main_recursion_insens.c +++ b/tests/regression/80-context_gas/08-main_recursion_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 // Without context insensitive analysis: Stack Overflow #include diff --git a/tests/regression/80-context_gas/10-endless_loop.c b/tests/regression/80-context_gas/09-endless_loop.c similarity index 100% rename from tests/regression/80-context_gas/10-endless_loop.c rename to tests/regression/80-context_gas/09-endless_loop.c diff --git a/tests/regression/80-context_gas/11-thread_handling.c b/tests/regression/80-context_gas/10-thread_handling_sens.c similarity index 56% rename from tests/regression/80-context_gas/11-thread_handling.c rename to tests/regression/80-context_gas/10-thread_handling_sens.c index 5077baa8f8..11db96e100 100644 --- a/tests/regression/80-context_gas/11-thread_handling.c +++ b/tests/regression/80-context_gas/10-thread_handling_sens.c @@ -4,44 +4,38 @@ int f(int i) { - int res = 0; if (i == 0) { - res = 1; + return 1; } if (i > 0) { - res = f(--i); + return f(i - 1); } - return res; } int g(int i) { - int res = 0; if (i == 0) { - res = 3; + return 2; } if (i > 0) { - res = g(--i); + return g(i - 1); } - return res; } int h(int i) { - int res = 0; if (i == 0) { - res = 2; + return 3; } if (i > 0) { - res = g(--i); + return g(i - 1); } - return res; } int procedure(int num_iterat) @@ -56,31 +50,32 @@ int procedure(int num_iterat) void *t_sens(void *arg) { int result = procedure(0); - __goblint_check(result == 8); + __goblint_check(result == 9); - result = procedure(5); - __goblint_check(result == 10); + result = procedure(6); + __goblint_check(result == 7); return NULL; } -void *t_insens(void *arg) +void *t_sens2(void *arg) { - int result = procedure(6); - __goblint_check(result == 10); // UNKNOWN + int result = procedure(1); + __goblint_check(result == 7); - result = procedure(60); - __goblint_check(result == 10); // UNKNOWN + result = procedure(8); + __goblint_check(result == 7); return NULL; } int main() { pthread_t id; + pthread_t id2; - // Creat the thread + // Create the thread pthread_create(&id, NULL, t_sens, NULL); - // Creat the thread - pthread_create(&id, NULL, t_insens, NULL); + // Create the thread + pthread_create(&id2, NULL, t_sens2, NULL); return 0; } diff --git a/tests/regression/80-context_gas/11-thread_handling_ins.c b/tests/regression/80-context_gas/11-thread_handling_ins.c new file mode 100644 index 0000000000..bd3ea86f80 --- /dev/null +++ b/tests/regression/80-context_gas/11-thread_handling_ins.c @@ -0,0 +1,67 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } +} + +int g(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } +} + +int h(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_insens(void *arg) +{ + int result = procedure(9); + __goblint_check(result == 7); // UNKNOWN + + result = procedure(60); + __goblint_check(result == 7); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Create the thread + pthread_create(&id, NULL, t_insens, NULL); + return 0; +} diff --git a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c new file mode 100644 index 0000000000..89c0d708f5 --- /dev/null +++ b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c @@ -0,0 +1,51 @@ +// PARAM: --enable ana.int.interval_set --enable ana.context.ctx_gas --set ana.context.ctx_gas_value 10 +// Tests multiple recursive function calls +#include + +int h(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return h(i - 1); + } +} + +int g(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return h(i - 1); + } +} + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return g(i - 1); + } +} + +int main(void) +{ + __goblint_check(f(10) == 3); + __goblint_check(f(8) == 3); + __goblint_check(h(5) == 3); + + __goblint_check(f(0) == 1); + __goblint_check(f(1) == 2); + __goblint_check(g(0) == 2); + __goblint_check(g(1) == 3); +} diff --git a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c new file mode 100644 index 0000000000..321df17938 --- /dev/null +++ b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c @@ -0,0 +1,50 @@ +// PARAM: --enable ana.int.interval_set --enable ana.context.ctx_gas --set ana.context.ctx_gas_value 10 +// Tests multiple recursive function calls +#include + +int h(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return h(i - 1); + } +} + +int g(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return h(i - 1); + } +} + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return g(i - 1); + } +} + +int main(void) +{ + __goblint_check(f(11) == 3); // UNKNOWN + __goblint_check(g(12) == 3); // UNKNOWN + __goblint_check(g(20) == 3); // UNKNOWN + __goblint_check(f(20) == 3); // UNKNOWN + __goblint_check(h(40) == 3); // UNKNOWN + __goblint_check(h(300) == 3); // UNKNOWN + __goblint_check(f(300) == 3); // UNKNOWN +} diff --git a/tests/regression/80-context_gas/05-ackermann.c b/tests/regression/80-context_gas/14-ackermann.c similarity index 100% rename from tests/regression/80-context_gas/05-ackermann.c rename to tests/regression/80-context_gas/14-ackermann.c diff --git a/tests/regression/80-context_gas/15-compl_loop_unrolling.c b/tests/regression/80-context_gas/15-compl_loop_unrolling.c new file mode 100644 index 0000000000..bab565688c --- /dev/null +++ b/tests/regression/80-context_gas/15-compl_loop_unrolling.c @@ -0,0 +1,32 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// TODO +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int main(void) +{ + // loop should be completely unrolled + for (int i = 3; i > 0; i--) + { + __goblint_check(f(1) == 11); + __goblint_check(f(20) == 11); // UNKNOWN + } + + for (int i = 1; i > 0; i--) + { + __goblint_check(f(2) == 11); + __goblint_check(f(2000) == 11); // UNKNOWN + } +} diff --git a/tests/regression/80-context_gas/16-loop_unrolling_sens.c b/tests/regression/80-context_gas/16-loop_unrolling_sens.c new file mode 100644 index 0000000000..4c647bff7b --- /dev/null +++ b/tests/regression/80-context_gas/16-loop_unrolling_sens.c @@ -0,0 +1,33 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// TODO +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int main(void) +{ + int res1 = 0; + int res2 = 0; + + // context sensitive analysis + for (int i = 5; i > 0; i--) + { + res1 = f(3); + res2 = f(i); + __goblint_check(res1 == 11); + __goblint_check(res2 == 11); + } + __goblint_check(res1 == 11); + __goblint_check(res2 == 11); +} diff --git a/tests/regression/80-context_gas/17-loop_unrolling_ins.c b/tests/regression/80-context_gas/17-loop_unrolling_ins.c new file mode 100644 index 0000000000..ceab5a870f --- /dev/null +++ b/tests/regression/80-context_gas/17-loop_unrolling_ins.c @@ -0,0 +1,25 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// TODO +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int main(void) +{ + + for (int i = 5; i > 0; i--) + { + __goblint_check(f(11) == 11); // UNKNOWN + } +} diff --git a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c new file mode 100644 index 0000000000..d8c5e2a013 --- /dev/null +++ b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c @@ -0,0 +1,26 @@ +// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// TODO +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int main(void) +{ + // high number of iterations + for (int i = 500; i > 0; i--) + { + __goblint_check(f(i) == 11); // UNKNOWN + __goblint_check(f(4) == 11); + } +} From 6520557b40c65a9bb6259c1d28586216fc124b46 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 12 Feb 2024 09:08:04 +0100 Subject: [PATCH 103/128] updated testcases loopfreeCallstring + callstring fundec --- src/framework/constraints.ml | 4 +- .../01-loop_calling_sens.c | 2 +- .../02-loop_calling_ins.c | 2 +- .../06-multiple_calls_sens.c | 2 +- .../07-multiple_calls_ins.c | 6 +- .../08-new_calling_set.c | 2 +- .../09-many_nested_loops.c | 4 +- .../81-loopfree_callstring/10-nested_loops.c | 2 +- .../11-value_update_sens.c | 23 +++++ .../12-value_update_ins.c | 23 +++++ .../13-circle_call_and_big_loop.c | 42 ++++++++ .../14-loop_unrolling.c | 26 +++++ .../81-loopfree_callstring/15-threads_sens.c | 84 ++++++++++++++++ .../81-loopfree_callstring/16-threads_ins.c | 71 ++++++++++++++ .../02-multiple_function_chain_tests.c | 76 --------------- .../03-multiple_rec_sens.c | 60 ------------ .../04-multiple_rec_ins.c | 59 ------------ .../05-function_chain_sens.c | 54 ----------- .../06-function_chain_ins.c | 54 ----------- .../07-call_in_call_sens.c | 54 ----------- .../11-big_call_and_loop.c | 49 ---------- .../82-callstring_Fundec/12-loop_unrolling.c | 34 ------- .../82-callstring_Fundec/13-thread_creation.c | 92 ------------------ .../14-thread_creation_problem.c | 89 ----------------- .../01-loop_calling_sens.c | 25 +++++ .../02-loop_calling_ins.c | 32 +++++++ .../03-ackermann.c} | 3 +- .../82-callstring_fundec/04-endless_loop.c | 26 +++++ .../05-multiple_calls_base_sens.c | 57 +++++++++++ .../06-multiple_calls_sens.c | 61 ++++++++++++ .../07-multiple_calls_ins.c | 57 +++++++++++ .../82-callstring_fundec/08-new_calling_set.c | 36 +++++++ .../09-new_calling_set_ins.c | 36 +++++++ .../10-many_nested_loops_sens.c | 70 ++++++++++++++ .../11-value_update_sens.c} | 7 +- .../12-value_update_ins.c} | 5 +- .../13-circle_call_and_loops.c} | 20 ++-- .../14-circle_call_and_big_loop.c} | 20 ++-- .../82-callstring_fundec/15-loop_unrolling.c | 26 +++++ .../82-callstring_fundec/16-threads_sens.c | 96 +++++++++++++++++++ .../82-callstring_fundec/17-threads_ins.c | 73 ++++++++++++++ .../18-simple_rec_inf_callstack.c} | 3 +- 42 files changed, 902 insertions(+), 665 deletions(-) create mode 100644 tests/regression/81-loopfree_callstring/11-value_update_sens.c create mode 100644 tests/regression/81-loopfree_callstring/12-value_update_ins.c create mode 100644 tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c create mode 100644 tests/regression/81-loopfree_callstring/14-loop_unrolling.c create mode 100644 tests/regression/81-loopfree_callstring/15-threads_sens.c create mode 100644 tests/regression/81-loopfree_callstring/16-threads_ins.c delete mode 100644 tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c delete mode 100644 tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c delete mode 100644 tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c delete mode 100644 tests/regression/82-callstring_Fundec/05-function_chain_sens.c delete mode 100644 tests/regression/82-callstring_Fundec/06-function_chain_ins.c delete mode 100644 tests/regression/82-callstring_Fundec/07-call_in_call_sens.c delete mode 100644 tests/regression/82-callstring_Fundec/11-big_call_and_loop.c delete mode 100644 tests/regression/82-callstring_Fundec/12-loop_unrolling.c delete mode 100644 tests/regression/82-callstring_Fundec/13-thread_creation.c delete mode 100644 tests/regression/82-callstring_Fundec/14-thread_creation_problem.c create mode 100644 tests/regression/82-callstring_fundec/01-loop_calling_sens.c create mode 100644 tests/regression/82-callstring_fundec/02-loop_calling_ins.c rename tests/regression/{82-callstring_Fundec/08-ackermann.c => 82-callstring_fundec/03-ackermann.c} (84%) create mode 100644 tests/regression/82-callstring_fundec/04-endless_loop.c create mode 100644 tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c create mode 100644 tests/regression/82-callstring_fundec/06-multiple_calls_sens.c create mode 100644 tests/regression/82-callstring_fundec/07-multiple_calls_ins.c create mode 100644 tests/regression/82-callstring_fundec/08-new_calling_set.c create mode 100644 tests/regression/82-callstring_fundec/09-new_calling_set_ins.c create mode 100644 tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c rename tests/regression/{82-callstring_Fundec/01-simple_rec_ins.c => 82-callstring_fundec/11-value_update_sens.c} (64%) rename tests/regression/{82-callstring_Fundec/15-simple_rec_ins.c => 82-callstring_fundec/12-value_update_ins.c} (69%) rename tests/regression/{82-callstring_Fundec/09-circle_call_and_loops.c => 82-callstring_fundec/13-circle_call_and_loops.c} (72%) rename tests/regression/{82-callstring_Fundec/10-circle_call_and_big_loop.c => 82-callstring_fundec/14-circle_call_and_big_loop.c} (69%) create mode 100644 tests/regression/82-callstring_fundec/15-loop_unrolling.c create mode 100644 tests/regression/82-callstring_fundec/16-threads_sens.c create mode 100644 tests/regression/82-callstring_fundec/17-threads_ins.c rename tests/regression/{82-callstring_Fundec/16-simple_rec_inf_callstack.c => 82-callstring_fundec/18-simple_rec_inf_callstack.c} (88%) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 65ce60f897..c310759e89 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -568,8 +568,8 @@ struct let asm ctx = S.asm (conv ctx), cg_val ctx let skip ctx = S.skip (conv ctx), cg_val ctx let special ctx r f args = S.special (conv ctx) r f args, cg_val ctx - let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc (fun x -> x)) (fst es) f_ask, cg_val ctx - let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc (fun x -> x)) (fst es) f_ask, cg_val ctx + let combine_env ctx r fe f args fc es f_ask = S.combine_env (conv ctx) r fe f args (Option.bind fc Fun.id) (fst es) f_ask, cg_val ctx + let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.bind fc Fun.id) (fst es) f_ask, cg_val ctx let paths_as_set ctx = List.map (fun (x) -> (x, cg_val ctx)) @@ S.paths_as_set (conv ctx) let threadspawn ctx ~multiple lval f args fctx = S.threadspawn (conv ctx) ~multiple lval f args (conv fctx), cg_val ctx let event ctx e octx = S.event (conv ctx) e (conv octx), cg_val ctx diff --git a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c index 1c8086732f..f473d88535 100644 --- a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c +++ b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c @@ -19,7 +19,7 @@ int f(int i) int main() { // main -> f(7) -> g(6) -> f(5) -> ... -> f(1) -> g(0) -> return 2 - // [main, f, g] and [main] {f, g} + // [main, f, g] and [main] {f, g} (3 times) __goblint_check(f(7) == 2); return 0; } diff --git a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c index 1612742461..9db9e48b18 100644 --- a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c +++ b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c @@ -25,6 +25,6 @@ int f(int i) int main(void) { // main -> f(9) -> g(8) -> f(7) -> ... -> g(2) -> f(1) -> g(0) -> return 2 - // [main, f, g] and [main] {f, g} + // [main, f, g] and [main] {f, g} (4 times) __goblint_check(f(9) == 2); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c index f8e31c7acc..5b84414983 100644 --- a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c +++ b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c @@ -44,7 +44,7 @@ int h(int i) int main(void) { // main -> f(3) -> ... -> f(0) -> return 11 - // [main, f] and [main] {f} + // [main, f] and [main] {f} (3 times) __goblint_check(f(3) == 11); // main -> g(3) -> f(2) -> f(1) -> f(0) -> return 11 diff --git a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c index 7e260961af..ad6d70f68f 100644 --- a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c +++ b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c @@ -44,14 +44,14 @@ int h(int i) int main(void) { // main -> f(4) -> f(3) -> f(2) -> f(1) -> f(0) -> return 11 - // [main, f] and [main] {f} + // [main, f] and [main] {f} (4 times) __goblint_check(f(4) == 11); // UNKNOWN // main -> g(20) -> f(19) -> ... -> f(0) -> return 11 - // [main, g, f] and [main, g] {f} + // [main, g, f] and [main, g] {f} (20 times) __goblint_check(g(20) == 11); // UNKNOWN // main -> h(10) -> g(9) -> f(8) -> ... -> f(1) -> f(0) -> return 11 - // [main, h, g, f] and [main, h, g] {f} + // [main, h, g, f] and [main, h, g] {f} (9 times) __goblint_check(h(10) == 11); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/08-new_calling_set.c b/tests/regression/81-loopfree_callstring/08-new_calling_set.c index 40997e99ce..f8f97bab6b 100644 --- a/tests/regression/81-loopfree_callstring/08-new_calling_set.c +++ b/tests/regression/81-loopfree_callstring/08-new_calling_set.c @@ -31,6 +31,6 @@ int g(int i) int main(void) { // main -> g(20) -> ... -> g(5) -> f(4) -> ... -> f(0) -> return 1 - // [main] {g, f} + // [main] {g} (16 times) and [main] {g, f} (5 times) __goblint_check(g(20) == 1); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c index fba400e14d..c4c0c833d8 100644 --- a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c +++ b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c @@ -67,12 +67,12 @@ int main(void) // m: [main, m] // g: [main, m, g] // f: [main, m, g, f] - // f: [main, m, g] {f} + // f: [main, m, g] {f} (3 times) // h: [main, m, g] {f} [h] // g: [main, m] {g, f, h} // a: [main, m] {g, f, h} [a] // b: [main, m] {g, f, h} [a, b] // c: [main, m] {g, f, h} [a, b, c] - // g, b, c: [main, m] {g, f, h, a, b, c} + // g, b, c: [main, m] {g, f, h, a, b, c} (3 times) __goblint_check(m(4) == 4); } diff --git a/tests/regression/81-loopfree_callstring/10-nested_loops.c b/tests/regression/81-loopfree_callstring/10-nested_loops.c index 23866b3f99..9dc3ccda8d 100644 --- a/tests/regression/81-loopfree_callstring/10-nested_loops.c +++ b/tests/regression/81-loopfree_callstring/10-nested_loops.c @@ -27,6 +27,6 @@ int f(int i) int main(void) { // main -> f(4) -> f(3) -> ... -> f(0) -> g(2) -> h(2) -> return 3 - // [main] {f} [g,h] + // [main] {f} [g,h] (4 times) __goblint_check(f(4) == 3); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/11-value_update_sens.c b/tests/regression/81-loopfree_callstring/11-value_update_sens.c new file mode 100644 index 0000000000..71f2e0ea16 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/11-value_update_sens.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + // main -> f(10) -> f(9) -> ... f(0) + // [main, f] and [main] {f} + f(1); + __goblint_check(a == 0); +} diff --git a/tests/regression/81-loopfree_callstring/12-value_update_ins.c b/tests/regression/81-loopfree_callstring/12-value_update_ins.c new file mode 100644 index 0000000000..9b26562123 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/12-value_update_ins.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Basic example +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + // main -> f(10) -> f(9) -> ... f(0) + // [main, f] and [main] {f} (2 times) + f(2); + __goblint_check(a == 0); // UNKNOWN +} diff --git a/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c new file mode 100644 index 0000000000..c8624782bd --- /dev/null +++ b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c @@ -0,0 +1,42 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed +#include + +int f(int i); + +int g(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int f(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int main(void) +{ + for (int i = 200; i > 0; i--) + { + int res1 = f(2); + int res2 = g(2); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); + } +} diff --git a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c new file mode 100644 index 0000000000..7831ff6925 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c @@ -0,0 +1,26 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set --set exp.unrolling-factor 3 + +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int main(void) +{ + for (int i = 5; i > 0; i--) + { + // main -> f(3) -> ... -> f(0) -> return 1 + // [main, f] and {f} (3 times) + __goblint_check(f(3) == 1); + } +} diff --git a/tests/regression/81-loopfree_callstring/15-threads_sens.c b/tests/regression/81-loopfree_callstring/15-threads_sens.c new file mode 100644 index 0000000000..621ab0a2e6 --- /dev/null +++ b/tests/regression/81-loopfree_callstring/15-threads_sens.c @@ -0,0 +1,84 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + // main -> t_sens -> procedure -> f(0) + // main -> t_sens -> procedure -> g(0) + // main -> t_sens -> procedure -> h(0) + __goblint_check(procedure(0) == 8); + return NULL; +} + +void *t_sens2(void *arg) +{ + // main -> t_sens2 -> procedure -> f(3) -> ... -> f(0) + // [main, t_sens2, procedure, f] and [main, t_sens2, procedure] {f} (3 times) + // main -> t_sens2 -> procedure -> g(3) -> ... -> g(0) + // [main, t_sens2, procedure, g] and [main, t_sens2, procedure] {g} (3 times) + // main -> t_sens2 -> procedure -> h(3) -> g(2) -> ... -> g(0) + // [main, t_sens2, procedure, h, g] and [main, t_sens2, procedure, h] {g} (2 times) + __goblint_check(procedure(3) == 10); + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + + // Create the thread + pthread_create(&id, NULL, t_sens, NULL); + pthread_create(&id2, NULL, t_sens2, NULL); + return 0; +} diff --git a/tests/regression/81-loopfree_callstring/16-threads_ins.c b/tests/regression/81-loopfree_callstring/16-threads_ins.c new file mode 100644 index 0000000000..90a332b25d --- /dev/null +++ b/tests/regression/81-loopfree_callstring/16-threads_ins.c @@ -0,0 +1,71 @@ +// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_ins(void *arg) +{ + // main -> t_ins -> procedure -> f(12) -> ... -> f(0) + // [main, t_ins, procedure, f] and [main, t_ins, procedure] {f} (12 times) + // main -> t_ins -> procedure -> g(12) -> g(11) -> ... -> g(0) + // main -> t_ins -> procedure -> h(12) -> g(11) -> ... -> g(0) + __goblint_check(procedure(12) == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Create the thread + pthread_create(&id, NULL, t_ins, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c b/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c deleted file mode 100644 index cfebcc4458..0000000000 --- a/tests/regression/82-callstring_Fundec/02-multiple_function_chain_tests.c +++ /dev/null @@ -1,76 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Tests multiple recursive function calls -// TODO!!! -#include - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - //__goblint_check(f(-5) == 0); - // int res1 = f(0); - //__goblint_check(res1 == 3); - //__goblint_check(f(1) == 2); - //__goblint_check(f(2) == 1); - // int res2 = f(8); - //__goblint_check(res2 == 1); //boundary (included) - //__goblint_check(f(9) == 1); //UNKNOWN //boundary (excluded) - //__goblint_check(f(20) == 1); //UNKNOWN - - //__goblint_check(g(-10) == 0); - //__goblint_check(g(0) == 2); - //__goblint_check(g(1) == 1); - - //__goblint_check(h(-10) == 0); - __goblint_check(h(5) == 1); - //__goblint_check(h(8) == 1); //boundary (included) - ///__goblint_check(h(9) == 1); //UNKNOWN //boundary (excluded) - - // int res1 = h(5); - // int res2 = h(4); - // int result = res1 + res2; - //__goblint_check(result == 2); - - //__goblint_check(f(g(h(9))) == 2); // h(9) = 1; g(1) = 1; f(1) = 2; - //__goblint_check(f(g(h(10))) == 2); //UNKNOWN // h(10) = UNKNOWN -} diff --git a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c b/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c deleted file mode 100644 index 24dade7342..0000000000 --- a/tests/regression/82-callstring_Fundec/03-multiple_rec_sens.c +++ /dev/null @@ -1,60 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 9; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - __goblint_check(res1 == 1); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); -} diff --git a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c b/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c deleted file mode 100644 index eb8f4d66ac..0000000000 --- a/tests/regression/82-callstring_Fundec/04-multiple_rec_ins.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); // UNKNOWN -} diff --git a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c b/tests/regression/82-callstring_Fundec/05-function_chain_sens.c deleted file mode 100644 index 7199dd7f84..0000000000 --- a/tests/regression/82-callstring_Fundec/05-function_chain_sens.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 11; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); -} diff --git a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c b/tests/regression/82-callstring_Fundec/06-function_chain_ins.c deleted file mode 100644 index cd4a9bd58a..0000000000 --- a/tests/regression/82-callstring_Fundec/06-function_chain_ins.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 12; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); // UNKNOWN -} diff --git a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c b/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c deleted file mode 100644 index d3f80414bc..0000000000 --- a/tests/regression/82-callstring_Fundec/07-call_in_call_sens.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Interesting if nested recursions are handled properly -#include - -int num_iterat = 9; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 - - __goblint_check(res == 1); -} \ No newline at end of file diff --git a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c b/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c deleted file mode 100644 index b977b615c6..0000000000 --- a/tests/regression/82-callstring_Fundec/11-big_call_and_loop.c +++ /dev/null @@ -1,49 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Checks proper handling of recursions in loops + should show that analyzing the same function twice with different number of recursions fastens the result -// TODO weird behavior: only if num_iterat = 9 (= same value as for f(...) and g(...)) -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(9); - int res2 = g(9); - __goblint_check(res1 == 1); // TODO - __goblint_check(res2 == 2); // TODO - for (int i = 10; i > 0; i--) - { - int res3 = f(num_iterat); - int res4 = g(num_iterat); - __goblint_check(res3 == 1); // TODO - __goblint_check(res4 == 2); // TODO - } -} diff --git a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c b/tests/regression/82-callstring_Fundec/12-loop_unrolling.c deleted file mode 100644 index 2c71062a1c..0000000000 --- a/tests/regression/82-callstring_Fundec/12-loop_unrolling.c +++ /dev/null @@ -1,34 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 -// Checks if recursion in loops are handled properly + loop unrolling -// TODO -#include - -int num_iterat = 3; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int main(void) -{ - int res = 0; - int result = 0; - for (int i = 5; i > 0; i--) - { - res = f(num_iterat); - __goblint_check(res == 1); - result += res; - } - __goblint_check(res == 1); - __goblint_check(result == 5); // TODO -} diff --git a/tests/regression/82-callstring_Fundec/13-thread_creation.c b/tests/regression/82-callstring_Fundec/13-thread_creation.c deleted file mode 100644 index 7c4ef3960b..0000000000 --- a/tests/regression/82-callstring_Fundec/13-thread_creation.c +++ /dev/null @@ -1,92 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -#include -#include -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_sens(void *arg) -{ - int result = procedure(0); - __goblint_check(result == 8); - return NULL; -} - -void *t_sens2(void *arg) -{ - int result = procedure(7); - __goblint_check(result == 10); - return NULL; -} - -void *t_insens(void *arg) -{ - int result = procedure(8); - __goblint_check(result == 10); // UNKNOWN - - result = procedure(60); - __goblint_check(result == 10); // UNKNOWN - return NULL; -} - -int main() -{ - pthread_t id; - pthread_t id2; - pthread_t id3; - - // Create the thread - pthread_create(&id, NULL, t_sens, NULL); - pthread_create(&id2, NULL, t_sens2, NULL); - pthread_create(&id3, NULL, t_insens, NULL); - return 0; -} diff --git a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c b/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c deleted file mode 100644 index eaaebb4b21..0000000000 --- a/tests/regression/82-callstring_Fundec/14-thread_creation_problem.c +++ /dev/null @@ -1,89 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -#include -#include -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_sens(void *arg) -{ - int result = procedure(0); - __goblint_check(result == 8); // TODO - - result = procedure(3); - __goblint_check(result == 10); // TODO - return NULL; -} - -void *t_insens(void *arg) -{ - int result = procedure(6); - __goblint_check(result == 10); // UNKNOWN - - result = procedure(60); - __goblint_check(result == 10); // UNKNOWN - return NULL; -} - -int main() -{ - pthread_t id; - pthread_t id2; - - // Create the thread - pthread_create(&id, NULL, t_sens, NULL); - // pthread_join(id, NULL); - - // Create the thread - pthread_create(&id2, NULL, t_insens, NULL); - return 0; -} diff --git a/tests/regression/82-callstring_fundec/01-loop_calling_sens.c b/tests/regression/82-callstring_fundec/01-loop_calling_sens.c new file mode 100644 index 0000000000..87af18fcd3 --- /dev/null +++ b/tests/regression/82-callstring_fundec/01-loop_calling_sens.c @@ -0,0 +1,25 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int f(int i) +{ + return g(i - 1); +} + +int main() +{ + // main -> f(7) -> g(6) -> f(5) -> ... -> f(1) -> g(0) -> return 2 + // [main, f, g, f, g, f, g, f, g] + __goblint_check(f(7) == 2); + return 0; +} diff --git a/tests/regression/82-callstring_fundec/02-loop_calling_ins.c b/tests/regression/82-callstring_fundec/02-loop_calling_ins.c new file mode 100644 index 0000000000..b02a4fd495 --- /dev/null +++ b/tests/regression/82-callstring_fundec/02-loop_calling_ins.c @@ -0,0 +1,32 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i); + +int g(int i) +{ + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int f(int i) +{ + if (i > 0) + { + return g(i - 1); + } + return 1; +} + +int main(void) +{ + // main -> f(15) -> g(14) -> f(13) -> ... -> g(2) -> f(1) -> g(0) -> return 2 + // [main, f, g, f, g, f, g, f, g, f] and + // [f, g, f, g, f, g, f, g, f, g] (4 times) and + // [g, f, g, f, g, f, g, f, g, f] (3 times) + __goblint_check(f(15) == 2); // UNKNOWN +} diff --git a/tests/regression/82-callstring_Fundec/08-ackermann.c b/tests/regression/82-callstring_fundec/03-ackermann.c similarity index 84% rename from tests/regression/82-callstring_Fundec/08-ackermann.c rename to tests/regression/82-callstring_fundec/03-ackermann.c index cc1d220a55..6464222bda 100644 --- a/tests/regression/82-callstring_Fundec/08-ackermann.c +++ b/tests/regression/82-callstring_fundec/03-ackermann.c @@ -1,5 +1,4 @@ // PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// This code would result in a StackOverflow if it is analyses fully context sensitive #include int ack(int n, int m) @@ -23,6 +22,8 @@ int ack(int n, int m) int main(void) { + // main -> ack -> ack -> ... + // [main, ack, ...] ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/82-callstring_fundec/04-endless_loop.c b/tests/regression/82-callstring_fundec/04-endless_loop.c new file mode 100644 index 0000000000..0fd4f49e3a --- /dev/null +++ b/tests/regression/82-callstring_fundec/04-endless_loop.c @@ -0,0 +1,26 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis +#include + +int num_iterat = 2; + +// main -> main -> ... +// [main, main, ...] +int main(void) +{ + if (num_iterat > 0) + { + num_iterat++; + int res = main(); + __goblint_check(res == 5); // UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} \ No newline at end of file diff --git a/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c b/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c new file mode 100644 index 0000000000..f45e83dbc3 --- /dev/null +++ b/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c @@ -0,0 +1,57 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(0) -> return 11 + // [main, f] + __goblint_check(f(0) == 11); + + // main -> g(0) -> return 12 + // [main, g] + __goblint_check(g(0) == 12); + + // main -> h(0) -> return 13 + // [main, h] + __goblint_check(h(0) == 13); +} diff --git a/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c b/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c new file mode 100644 index 0000000000..cbd63d5e4a --- /dev/null +++ b/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c @@ -0,0 +1,61 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(3) -> ... -> f(0) -> return 11 + // [main, f, f, f, f] + __goblint_check(f(3) == 11); + + // main -> f(6) -> ... -> f(0) -> return 11 + // [main, f, f, f, f] and [f, f, f, f, f] (3 times) + __goblint_check(f(6) == 11); + + // main -> g(3) -> f(2) -> f(1) -> f(0) -> return 11 + // [main, g, f, f, f] + __goblint_check(g(3) == 11); + + // main -> h(3) -> g(2) -> f(1) -> f(0) -> return 11 + // [main, h, g, f, f] + __goblint_check(h(3) == 11); +} diff --git a/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c b/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c new file mode 100644 index 0000000000..1f53a9f93b --- /dev/null +++ b/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c @@ -0,0 +1,57 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return f(i - 1); + } + return 1; +} + +int g(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return f(i - 1); + } + return 2; +} + +int h(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return g(i - 1); + } + return 3; +} + +int main(void) +{ + // main -> f(7) -> ... -> f(0) -> return 11 + // [main, f, f, f, f] and [f, f, f, f, f] (4 times) + __goblint_check(f(7) == 11); // UNKNOWN + + // main -> g(20) -> f(19) -> ... -> f(0) -> return 11 + // [main, g, f, f, f] and [g, f, f, f, f] and [f, f, f, f, f] (16 times) + __goblint_check(g(20) == 11); // UNKNOWN + + // main -> h(10) -> g(9) -> f(8) -> ... -> f(1) -> f(0) -> return 11 + // [main, h, g, f, f] and [h, g, f, f, f] and [g, f, f, f, f] and [f, f, f, f, f] (5 times) + __goblint_check(h(10) == 11); // UNKNOWN +} diff --git a/tests/regression/82-callstring_fundec/08-new_calling_set.c b/tests/regression/82-callstring_fundec/08-new_calling_set.c new file mode 100644 index 0000000000..4141cb4724 --- /dev/null +++ b/tests/regression/82-callstring_fundec/08-new_calling_set.c @@ -0,0 +1,36 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 0; +} + +int g(int i) +{ + if (i == 2) + { + return f(i - 1) + 1; + } + if (i > 0) + { + return g(i - 1) + 0; + } + return 1; +} + +int main(void) +{ + // main -> g(6) -> ... -> g(2) -> f(1) -> f(0) -> return 1 + // [main, g] and [g, g] (3 times) and [g, f] and [f, f] + __goblint_check(g(5) == 2); +} diff --git a/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c b/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c new file mode 100644 index 0000000000..7c56f9c83d --- /dev/null +++ b/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c @@ -0,0 +1,36 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 0; +} + +int g(int i) +{ + if (i == 2) + { + return f(i - 1) + 1; + } + if (i > 0) + { + return g(i - 1) + 0; + } + return 1; +} + +int main(void) +{ + // main -> g(6) -> ... -> g(2) -> f(1) -> f(0) -> return 1 + // [main, g] and [g, g] (4 times) and [g, f] and [f, f] + __goblint_check(g(6) == 2); // UNKNOWN +} diff --git a/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c b/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c new file mode 100644 index 0000000000..ff0cf37a8a --- /dev/null +++ b/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c @@ -0,0 +1,70 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// Basic example +#include + +int g(int i); + +int c(int i) +{ + if (i == 0) + { + return g(2); + } + else + { + return 4; + } +} + +int b(int i) +{ + return c(i - 1); +} + +int a(int i) +{ + return b(i - 1); +} + +int h(int i) +{ + return g(i - 1); +} + +int f(int i) +{ + if (i <= 0) + { + return h(4); + } + else + { + return f(i - 1); + } +} + +int g(int i) +{ + if (i == 4) + { + return f(3); + } + if (i == 3) + { + return a(2); + } + return b(20); +} + +int m(int i) +{ + return g(i); +} + +int main(void) +{ + // main -> m(4) -> g(4) -> f(3) -> f(2) -> f(1) -> f(0) -> h(4) -> g(3) -> a(2) -> b(1) -> c(0) -> g(2) -> b(20) -> c(19) -> return 4 + // [main, m] and [m, g] an [g, f] and [f, f] (3 times) and + // [f, h] and [h, g] and [g, a] and [a, b] and [b, c] and [c, g] and [g, b] and [b, c] + __goblint_check(m(4) == 4); +} diff --git a/tests/regression/82-callstring_Fundec/01-simple_rec_ins.c b/tests/regression/82-callstring_fundec/11-value_update_sens.c similarity index 64% rename from tests/regression/82-callstring_Fundec/01-simple_rec_ins.c rename to tests/regression/82-callstring_fundec/11-value_update_sens.c index eb821ccbd6..09ddfb0e16 100644 --- a/tests/regression/82-callstring_Fundec/01-simple_rec_ins.c +++ b/tests/regression/82-callstring_fundec/11-value_update_sens.c @@ -2,7 +2,6 @@ // Basic example #include -int num_iterat = 10; int a = 20; int f(int i) @@ -17,6 +16,8 @@ int f(int i) int main(void) { - f(num_iterat); - __goblint_check(a == 0); //UNKNOWN + // main -> f(10) -> f(9) -> ... f(0) + // [main, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] + f(9); + __goblint_check(a == 0); } diff --git a/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c b/tests/regression/82-callstring_fundec/12-value_update_ins.c similarity index 69% rename from tests/regression/82-callstring_Fundec/15-simple_rec_ins.c rename to tests/regression/82-callstring_fundec/12-value_update_ins.c index 3855aa3671..2ac18770f3 100644 --- a/tests/regression/82-callstring_Fundec/15-simple_rec_ins.c +++ b/tests/regression/82-callstring_fundec/12-value_update_ins.c @@ -2,7 +2,6 @@ // Basic example #include -int num_iterat = 10; int a = 20; int f(int i) @@ -17,6 +16,8 @@ int f(int i) int main(void) { - f(num_iterat); + // main -> f(10) -> f(9) -> ... f(0) + // [main, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (2 times) + f(10); __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c b/tests/regression/82-callstring_fundec/13-circle_call_and_loops.c similarity index 72% rename from tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c rename to tests/regression/82-callstring_fundec/13-circle_call_and_loops.c index 355a4aeb69..2436d6159f 100644 --- a/tests/regression/82-callstring_Fundec/09-circle_call_and_loops.c +++ b/tests/regression/82-callstring_fundec/13-circle_call_and_loops.c @@ -2,36 +2,32 @@ // Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed #include -int num_iterat = 200; - int f(int i); int g(int i) { - int res = 0; if (i == 0) { - res = 1; + return 1; } if (i > 0) { - res = f(--i); + return f(i - 1); } - return res; + return 11; } int f(int i) { - int res = 0; if (i == 0) { - res = 2; + return 2; } if (i > 0) { - res = g(--i); + return g(i - 1); } - return res; + return 12; } int main(void) @@ -40,8 +36,8 @@ int main(void) int res2 = 0; for (int i = 2; i > 0; i--) { - res1 = f(num_iterat); - res2 = g(num_iterat); + res1 = f(200); + res2 = g(200); __goblint_check(res1 == 2); // UNKNOWN __goblint_check(res2 == 1); // UNKNOWN } diff --git a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c b/tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c similarity index 69% rename from tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c rename to tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c index 751d4dbe5a..92a3dad6ba 100644 --- a/tests/regression/82-callstring_Fundec/10-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c @@ -2,44 +2,40 @@ // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include -int num_iterat = 2; - int f(int i); int g(int i) { - int res = 0; if (i == 0) { - res = 1; + return 1; } if (i > 0) { - res = f(--i); + return f(i - 1); } - return res; + return 11; } int f(int i) { - int res = 0; if (i == 0) { - res = 2; + return 2; } if (i > 0) { - res = g(--i); + return g(i - 1); } - return res; + return 12; } int main(void) { for (int i = 200; i > 0; i--) { - int res1 = f(num_iterat); - int res2 = g(num_iterat); + int res1 = f(2); + int res2 = g(2); __goblint_check(res1 == 2); __goblint_check(res2 == 1); } diff --git a/tests/regression/82-callstring_fundec/15-loop_unrolling.c b/tests/regression/82-callstring_fundec/15-loop_unrolling.c new file mode 100644 index 0000000000..c330da091d --- /dev/null +++ b/tests/regression/82-callstring_fundec/15-loop_unrolling.c @@ -0,0 +1,26 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 + +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int main(void) +{ + for (int i = 5; i > 0; i--) + { + // main -> f(3) -> ... -> f(0) -> return 1 + // [main, f] and [f, f] (3 times) + __goblint_check(f(3) == 1); + } +} diff --git a/tests/regression/82-callstring_fundec/16-threads_sens.c b/tests/regression/82-callstring_fundec/16-threads_sens.c new file mode 100644 index 0000000000..24f10edaf6 --- /dev/null +++ b/tests/regression/82-callstring_fundec/16-threads_sens.c @@ -0,0 +1,96 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + // main -> t_sens -> procedure -> f(0) + // main -> t_sens -> procedure -> g(0) + // main -> t_sens -> procedure -> h(0) + __goblint_check(procedure(0) == 8); + return NULL; +} + +void *t_sens2(void *arg) +{ + // main -> t_sens2 -> procedure -> f(8) -> ... -> f(0) + // [main, t_sens2, procedure, f, f, f, f, f, f, f] and [t_sens2, procedure, f, f, f, f, f, f, f, f] and [procedure, f, f, f, f, f, f, f, f, f] + // main -> t_sens2 -> procedure -> g(8) -> g(7) -> ... -> g(0) + // main -> t_sens2 -> procedure -> h(8) -> g(7) -> ... -> g(0) + __goblint_check(procedure(8) == 10); + return NULL; +} + +void *t_sens3(void *arg) +{ + // main -> t_sens3 -> procedure -> f(11) -> ... -> f(0) + // [main, t_sens3, procedure, f, f, f, f, f, f, f] and [t_sens3, procedure, f, f, f, f, f, f, f, f] and + // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (3 times) + + // main -> t_sens3 -> procedure -> g(11) -> g(10) -> ... -> g(0) + // main -> t_sens3 -> procedure -> h(11) -> g(10) -> ... -> g(0) + __goblint_check(procedure(11) == 10); + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + pthread_t id3; + + // Create the thread + pthread_create(&id, NULL, t_sens, NULL); + pthread_create(&id2, NULL, t_sens2, NULL); + pthread_create(&id3, NULL, t_sens3, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_fundec/17-threads_ins.c b/tests/regression/82-callstring_fundec/17-threads_ins.c new file mode 100644 index 0000000000..bbe87be424 --- /dev/null +++ b/tests/regression/82-callstring_fundec/17-threads_ins.c @@ -0,0 +1,73 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_ins(void *arg) +{ + // main -> t_ins -> procedure -> f(12) -> ... -> f(0) + // [main, t_ins, procedure, f, f, f, f, f, f, f] and [t_ins, procedure, f, f, f, f, f, f, f, f] and + // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (4 times) + + // main -> t_ins -> procedure -> g(12) -> g(11) -> ... -> g(0) + // main -> t_ins -> procedure -> h(12) -> g(11) -> ... -> g(0) + __goblint_check(procedure(12) == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Create the thread + pthread_create(&id, NULL, t_ins, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c b/tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c similarity index 88% rename from tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c rename to tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c index c2aee8e701..35a35dbadf 100644 --- a/tests/regression/82-callstring_Fundec/16-simple_rec_inf_callstack.c +++ b/tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c @@ -2,7 +2,6 @@ // Basic example #include -int num_iterat = 25; int a = 20; int f(int i) @@ -17,6 +16,6 @@ int f(int i) int main(void) { - f(num_iterat); + f(25); __goblint_check(a == 0); } From 9325303ab5ee57c15d0ab8a9183dd18be3371e64 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Feb 2024 15:50:58 +0100 Subject: [PATCH 104/128] disabled witness.yaml because join on loopfreeCallstring-stack is not possible yet --- conf/callstring-fundec.json | 2 +- conf/callstring-fundec_inf.json | 2 +- conf/callstring-loc.json | 2 +- conf/callstring-loc_inf.json | 2 +- conf/callstring-stmt.json | 2 +- conf/callstring-stmt_inf.json | 2 +- conf/context-gas-10.json | 2 +- conf/context-gas-20.json | 2 +- conf/context-gas-30.json | 2 +- conf/context-paper-24.json | 2 +- conf/context-widening.json | 2 +- conf/loopfree-callstring.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/conf/callstring-fundec.json b/conf/callstring-fundec.json index dc05393683..bd0a5e3b67 100644 --- a/conf/callstring-fundec.json +++ b/conf/callstring-fundec.json @@ -113,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/callstring-fundec_inf.json b/conf/callstring-fundec_inf.json index 823e886eec..0ec3454015 100644 --- a/conf/callstring-fundec_inf.json +++ b/conf/callstring-fundec_inf.json @@ -112,7 +112,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/callstring-loc.json b/conf/callstring-loc.json index 4a1ffdb7ff..03f0b19c8e 100644 --- a/conf/callstring-loc.json +++ b/conf/callstring-loc.json @@ -113,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/callstring-loc_inf.json b/conf/callstring-loc_inf.json index e51aa10db8..3e93d72565 100644 --- a/conf/callstring-loc_inf.json +++ b/conf/callstring-loc_inf.json @@ -112,7 +112,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/callstring-stmt.json b/conf/callstring-stmt.json index 2c2ee553bf..a7d8765cc7 100644 --- a/conf/callstring-stmt.json +++ b/conf/callstring-stmt.json @@ -113,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/callstring-stmt_inf.json b/conf/callstring-stmt_inf.json index 63b15b4a12..b973769b48 100644 --- a/conf/callstring-stmt_inf.json +++ b/conf/callstring-stmt_inf.json @@ -112,7 +112,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/context-gas-10.json b/conf/context-gas-10.json index fb335ba475..1075c82405 100644 --- a/conf/context-gas-10.json +++ b/conf/context-gas-10.json @@ -111,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/context-gas-20.json b/conf/context-gas-20.json index 95530e7eab..bb11f0f16f 100644 --- a/conf/context-gas-20.json +++ b/conf/context-gas-20.json @@ -111,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/context-gas-30.json b/conf/context-gas-30.json index 7fea39d8ac..64403ccf03 100644 --- a/conf/context-gas-30.json +++ b/conf/context-gas-30.json @@ -111,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/context-paper-24.json b/conf/context-paper-24.json index 8789ed68f3..ed688c94b9 100644 --- a/conf/context-paper-24.json +++ b/conf/context-paper-24.json @@ -112,7 +112,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/context-widening.json b/conf/context-widening.json index 05284b2d20..53cd575401 100644 --- a/conf/context-widening.json +++ b/conf/context-widening.json @@ -112,7 +112,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/loopfree-callstring.json b/conf/loopfree-callstring.json index 226ebd841d..211789d9b6 100644 --- a/conf/loopfree-callstring.json +++ b/conf/loopfree-callstring.json @@ -113,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": true, + "enabled": false, "format-version": "2.0", "entry-types": [ "invariant_set" From 530987157519d9d47d5d98b7ef6caddf6eb8eb53 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Feb 2024 16:01:52 +0100 Subject: [PATCH 105/128] changed callstring stackheight to 2 --- conf/callstring-fundec.json | 2 +- conf/callstring-loc.json | 2 +- conf/callstring-stmt.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/callstring-fundec.json b/conf/callstring-fundec.json index bd0a5e3b67..538bd024af 100644 --- a/conf/callstring-fundec.json +++ b/conf/callstring-fundec.json @@ -47,7 +47,7 @@ "widen": false, "ctx_gas": false, "inf_callStack": false, - "callStack_height": 10 + "callStack_height": 2 }, "malloc": { "wrappers": [ diff --git a/conf/callstring-loc.json b/conf/callstring-loc.json index 03f0b19c8e..d13f75279a 100644 --- a/conf/callstring-loc.json +++ b/conf/callstring-loc.json @@ -47,7 +47,7 @@ "widen": false, "ctx_gas": false, "inf_callStack": false, - "callStack_height": 10 + "callStack_height": 2 }, "malloc": { "wrappers": [ diff --git a/conf/callstring-stmt.json b/conf/callstring-stmt.json index a7d8765cc7..32be34387a 100644 --- a/conf/callstring-stmt.json +++ b/conf/callstring-stmt.json @@ -47,7 +47,7 @@ "widen": false, "ctx_gas": false, "inf_callStack": false, - "callStack_height": 10 + "callStack_height": 2 }, "malloc": { "wrappers": [ From 832f83ebc512acaa40a4f5f8169e0480a450c9a4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 7 Mar 2024 11:50:03 +0100 Subject: [PATCH 106/128] loopfree: list of elements -> elements; update comments of examples --- src/analyses/loopfreeCallstring.ml | 40 +++++-------------- .../01-loop_calling_sens.c | 2 +- .../02-loop_calling_ins.c | 2 +- .../06-multiple_calls_sens.c | 6 +-- .../07-multiple_calls_ins.c | 6 +-- .../08-new_calling_set.c | 2 +- .../09-many_nested_loops.c | 14 +++---- .../81-loopfree_callstring/10-nested_loops.c | 2 +- .../11-value_update_sens.c | 2 +- .../12-value_update_ins.c | 2 +- .../14-loop_unrolling.c | 2 +- .../81-loopfree_callstring/15-threads_sens.c | 6 +-- .../81-loopfree_callstring/16-threads_ins.c | 2 +- 13 files changed, 34 insertions(+), 54 deletions(-) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 188262d48c..5119b709ad 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -10,19 +10,19 @@ struct let name () = "loopfree_callstring" module FundecSet = SetDomain.Make (CilType.Fundec) - module FundecList = Printable.Liszt (CilType.Fundec) module Either = struct - include Lattice.Flat (Printable.Either (FundecList) (FundecSet)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) + include Lattice.Flat (Printable.Either (CilType.Fundec) (FundecSet)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) let printXml f = function | `Lifted x -> begin match x with - | `Left x -> BatPrintf.fprintf f "stack:\n%a" FundecList.printXml x + | `Left x -> BatPrintf.fprintf f "%a" CilType.Fundec.printXml x | `Right x -> BatPrintf.fprintf f "set:\n%a" FundecSet.printXml x end; | _ -> failwith "Error loopfreeCallstring (printXml): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" end + module D = Lattice.Liszt (Either) module C = D module V = EmptyV @@ -34,39 +34,19 @@ struct | `Lifted e -> e | _ -> failwith "Error loopfreeCallstring (get_either): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" - let list_after_split f stack rem_list = - let rec stack_split set (hd::rest) = - if CilType.Fundec.equal hd f - then (FundecSet.add hd set), (rest) - else stack_split (FundecSet.add hd set) rest - in - let set, new_stack = stack_split (FundecSet.empty ()) stack in - set, `Lifted(`Left new_stack)::rem_list - - let append_elem_at_end new_list f = - match new_list with - | [] -> [(`Lifted(`Left [f]))] - | x::xs -> - begin - match get_either x with - | `Left stack -> (`Lifted(`Left (f::stack)))::xs - | `Right set -> (`Lifted(`Left [f]))::new_list - end - let rec callee_state f prev_set prev_list cur_list = match cur_list with - | [] -> append_elem_at_end (List.rev prev_list) f + | [] -> (`Lifted(`Left f))::(List.rev prev_list) | e::rem_list -> begin match get_either e with - | `Left stack -> - if List.mem f stack - then (let set, new_stack = list_after_split f stack rem_list in - let new_set = FundecSet.join prev_set set in - (`Lifted(`Right new_set))::new_stack) + | `Left ele -> + if CilType.Fundec.equal f ele + then (let new_set = FundecSet.add f prev_set in + (`Lifted(`Right new_set))::rem_list) else - (let new_prev_set = FundecSet.join prev_set (FundecSet.of_list stack) in - let new_prev_list = `Lifted(`Left stack)::prev_list in + (let new_prev_set = FundecSet.add ele prev_set in + let new_prev_list = `Lifted(`Left ele)::prev_list in callee_state f new_prev_set new_prev_list rem_list) | `Right set -> let new_set = FundecSet.join prev_set set in diff --git a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c index f473d88535..2d04ecfdbb 100644 --- a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c +++ b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c @@ -19,7 +19,7 @@ int f(int i) int main() { // main -> f(7) -> g(6) -> f(5) -> ... -> f(1) -> g(0) -> return 2 - // [main, f, g] and [main] {f, g} (3 times) + // [main, f, g] and [main, {f, g}] (3 times) __goblint_check(f(7) == 2); return 0; } diff --git a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c index 9db9e48b18..96d92b346a 100644 --- a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c +++ b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c @@ -25,6 +25,6 @@ int f(int i) int main(void) { // main -> f(9) -> g(8) -> f(7) -> ... -> g(2) -> f(1) -> g(0) -> return 2 - // [main, f, g] and [main] {f, g} (4 times) + // [main, f, g] and [main, {f, g}] (4 times) __goblint_check(f(9) == 2); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c index 5b84414983..a387420768 100644 --- a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c +++ b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c @@ -44,14 +44,14 @@ int h(int i) int main(void) { // main -> f(3) -> ... -> f(0) -> return 11 - // [main, f] and [main] {f} (3 times) + // [main, f] and [main, {f}] (3 times) __goblint_check(f(3) == 11); // main -> g(3) -> f(2) -> f(1) -> f(0) -> return 11 - // [main, g, f] and [main, g] {f} + // [main, g, f] and [main, g, {f}] __goblint_check(g(3) == 11); // main -> h(5) -> g(4) -> f(3) -> ... -> f(0) -> return 11 - // [main, h, g, f] and [main, h, g] {f} + // [main, h, g, f] and [main, h, g, {f}] __goblint_check(h(5) == 11); } diff --git a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c index ad6d70f68f..0b8ce92acb 100644 --- a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c +++ b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c @@ -44,14 +44,14 @@ int h(int i) int main(void) { // main -> f(4) -> f(3) -> f(2) -> f(1) -> f(0) -> return 11 - // [main, f] and [main] {f} (4 times) + // [main, f] and [main, {f}] (4 times) __goblint_check(f(4) == 11); // UNKNOWN // main -> g(20) -> f(19) -> ... -> f(0) -> return 11 - // [main, g, f] and [main, g] {f} (20 times) + // [main, g, f] and [main, g, {f}] (20 times) __goblint_check(g(20) == 11); // UNKNOWN // main -> h(10) -> g(9) -> f(8) -> ... -> f(1) -> f(0) -> return 11 - // [main, h, g, f] and [main, h, g] {f} (9 times) + // [main, h, g, f] and [main, h, g, {f}] (9 times) __goblint_check(h(10) == 11); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/08-new_calling_set.c b/tests/regression/81-loopfree_callstring/08-new_calling_set.c index f8f97bab6b..04258ff47a 100644 --- a/tests/regression/81-loopfree_callstring/08-new_calling_set.c +++ b/tests/regression/81-loopfree_callstring/08-new_calling_set.c @@ -31,6 +31,6 @@ int g(int i) int main(void) { // main -> g(20) -> ... -> g(5) -> f(4) -> ... -> f(0) -> return 1 - // [main] {g} (16 times) and [main] {g, f} (5 times) + // [main, {g}] (16 times) and [main, {g, f}] (5 times) __goblint_check(g(20) == 1); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c index c4c0c833d8..6b3e977823 100644 --- a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c +++ b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c @@ -67,12 +67,12 @@ int main(void) // m: [main, m] // g: [main, m, g] // f: [main, m, g, f] - // f: [main, m, g] {f} (3 times) - // h: [main, m, g] {f} [h] - // g: [main, m] {g, f, h} - // a: [main, m] {g, f, h} [a] - // b: [main, m] {g, f, h} [a, b] - // c: [main, m] {g, f, h} [a, b, c] - // g, b, c: [main, m] {g, f, h, a, b, c} (3 times) + // f: [main, m, g, {f}] (3 times) + // h: [main, m, g, {f}, h] + // g: [main, m, {g, f, h}] + // a: [main, m, {g, f, h}, a] + // b: [main, m, {g, f, h}, a, b] + // c: [main, m, {g, f, h}, a, b, c] + // g, b, c: [main, m, {g, f, h, a, b, c}} (3 times) __goblint_check(m(4) == 4); } diff --git a/tests/regression/81-loopfree_callstring/10-nested_loops.c b/tests/regression/81-loopfree_callstring/10-nested_loops.c index 9dc3ccda8d..6ed6924412 100644 --- a/tests/regression/81-loopfree_callstring/10-nested_loops.c +++ b/tests/regression/81-loopfree_callstring/10-nested_loops.c @@ -27,6 +27,6 @@ int f(int i) int main(void) { // main -> f(4) -> f(3) -> ... -> f(0) -> g(2) -> h(2) -> return 3 - // [main] {f} [g,h] (4 times) + // [main, {f}, g, h] (4 times) __goblint_check(f(4) == 3); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/11-value_update_sens.c b/tests/regression/81-loopfree_callstring/11-value_update_sens.c index 71f2e0ea16..40146948b9 100644 --- a/tests/regression/81-loopfree_callstring/11-value_update_sens.c +++ b/tests/regression/81-loopfree_callstring/11-value_update_sens.c @@ -17,7 +17,7 @@ int f(int i) int main(void) { // main -> f(10) -> f(9) -> ... f(0) - // [main, f] and [main] {f} + // [main, f] and [main, {f}] f(1); __goblint_check(a == 0); } diff --git a/tests/regression/81-loopfree_callstring/12-value_update_ins.c b/tests/regression/81-loopfree_callstring/12-value_update_ins.c index 9b26562123..35e956c103 100644 --- a/tests/regression/81-loopfree_callstring/12-value_update_ins.c +++ b/tests/regression/81-loopfree_callstring/12-value_update_ins.c @@ -17,7 +17,7 @@ int f(int i) int main(void) { // main -> f(10) -> f(9) -> ... f(0) - // [main, f] and [main] {f} (2 times) + // [main, f] and [main, {f}] (2 times) f(2); __goblint_check(a == 0); // UNKNOWN } diff --git a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c index 7831ff6925..87d3e4d991 100644 --- a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c +++ b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c @@ -20,7 +20,7 @@ int main(void) for (int i = 5; i > 0; i--) { // main -> f(3) -> ... -> f(0) -> return 1 - // [main, f] and {f} (3 times) + // [main, f] and [main, {f}] (3 times) __goblint_check(f(3) == 1); } } diff --git a/tests/regression/81-loopfree_callstring/15-threads_sens.c b/tests/regression/81-loopfree_callstring/15-threads_sens.c index 621ab0a2e6..20697b1138 100644 --- a/tests/regression/81-loopfree_callstring/15-threads_sens.c +++ b/tests/regression/81-loopfree_callstring/15-threads_sens.c @@ -63,11 +63,11 @@ void *t_sens(void *arg) void *t_sens2(void *arg) { // main -> t_sens2 -> procedure -> f(3) -> ... -> f(0) - // [main, t_sens2, procedure, f] and [main, t_sens2, procedure] {f} (3 times) + // [main, t_sens2, procedure, f] and [main, t_sens2, procedure, {f}] (3 times) // main -> t_sens2 -> procedure -> g(3) -> ... -> g(0) - // [main, t_sens2, procedure, g] and [main, t_sens2, procedure] {g} (3 times) + // [main, t_sens2, procedure, g] and [main, t_sens2, procedure, {g}] (3 times) // main -> t_sens2 -> procedure -> h(3) -> g(2) -> ... -> g(0) - // [main, t_sens2, procedure, h, g] and [main, t_sens2, procedure, h] {g} (2 times) + // [main, t_sens2, procedure, h, g] and [main, t_sens2, procedure, h, {g}] (2 times) __goblint_check(procedure(3) == 10); return NULL; } diff --git a/tests/regression/81-loopfree_callstring/16-threads_ins.c b/tests/regression/81-loopfree_callstring/16-threads_ins.c index 90a332b25d..7b7fb69a92 100644 --- a/tests/regression/81-loopfree_callstring/16-threads_ins.c +++ b/tests/regression/81-loopfree_callstring/16-threads_ins.c @@ -54,7 +54,7 @@ int procedure(int num_iterat) void *t_ins(void *arg) { // main -> t_ins -> procedure -> f(12) -> ... -> f(0) - // [main, t_ins, procedure, f] and [main, t_ins, procedure] {f} (12 times) + // [main, t_ins, procedure, f] and [main, t_ins, procedure, {f}] (12 times) // main -> t_ins -> procedure -> g(12) -> g(11) -> ... -> g(0) // main -> t_ins -> procedure -> h(12) -> g(11) -> ... -> g(0) __goblint_check(procedure(12) == 10); // UNKNOWN From 12ae21e3b5bea33c5630d74af5888c595452ceaa Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 7 Mar 2024 11:51:03 +0100 Subject: [PATCH 107/128] update g2html and gobview with master --- g2html | 2 +- gobview | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/g2html b/g2html index 4b5e1bc630..b18424d114 160000 --- a/g2html +++ b/g2html @@ -1 +1 @@ -Subproject commit 4b5e1bc630f2260ad3f05af557bc65f707af1a6d +Subproject commit b18424d114c7838698b4323b49537d8e59faf55f diff --git a/gobview b/gobview index b5ab4dbd7b..54346ca9f1 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit b5ab4dbd7b1b1dc4f0bf2a912012cb1879f54903 +Subproject commit 54346ca9f15186e0b190c47f9f41bd5061208300 From 75827502215f6980527e5957132a53edcc80edaa Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Mar 2024 20:34:59 +0100 Subject: [PATCH 108/128] elegant solution for loopfree callstring --- src/analyses/loopfreeCallstring.ml | 59 +++++++++++------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 5119b709ad..26f794750e 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -10,53 +10,36 @@ struct let name () = "loopfree_callstring" module FundecSet = SetDomain.Make (CilType.Fundec) - module Either = struct - include Lattice.Flat (Printable.Either (CilType.Fundec) (FundecSet)) (* should be a list. Since a Lattice is required, Lattice.Flat is used to fulfill the type *) + module Either = Printable.Either (CilType.Fundec) (FundecSet) - let printXml f = function - | `Lifted x -> - begin - match x with - | `Left x -> BatPrintf.fprintf f "%a" CilType.Fundec.printXml x - | `Right x -> BatPrintf.fprintf f "set:\n%a" FundecSet.printXml x - end; - | _ -> failwith "Error loopfreeCallstring (printXml): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" - end - - module D = Lattice.Liszt (Either) + module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a list of Fundecs and sets of Fundecs. Lattice.Flat is used to fulfill the type *) module C = D module V = EmptyV module G = Lattice.Unit - let startstate v = [] - let exitstate v = [] + let startstate v = `Lifted([]) + let exitstate v = `Lifted([]) - let get_either either = match either with + let get_list list = match list with | `Lifted e -> e - | _ -> failwith "Error loopfreeCallstring (get_either): the Flat Lattice containing Either shouldn't be `Top or `Bottom!" + | _ -> failwith "Error loopfreeCallstring (get_list): D should represent a call stack not `Top or `Bottom!" + + let loop_detected f = function + | `Left ele -> CilType.Fundec.equal f ele + | `Right set -> FundecSet.mem f set + + let add_to_set old = function + | `Left ele -> FundecSet.add ele old + | `Right set -> FundecSet.join old set - let rec callee_state f prev_set prev_list cur_list = - match cur_list with - | [] -> (`Lifted(`Left f))::(List.rev prev_list) + let rec callee_state f prev_set prev_list = function + | [] -> (`Left f)::(List.rev prev_list) (* f is not yet contained in the call stack*) | e::rem_list -> - begin - match get_either e with - | `Left ele -> - if CilType.Fundec.equal f ele - then (let new_set = FundecSet.add f prev_set in - (`Lifted(`Right new_set))::rem_list) - else - (let new_prev_set = FundecSet.add ele prev_set in - let new_prev_list = `Lifted(`Left ele)::prev_list in - callee_state f new_prev_set new_prev_list rem_list) - | `Right set -> - let new_set = FundecSet.join prev_set set in - if FundecSet.mem f set - then (`Lifted(`Right new_set))::rem_list - else (let new_prev_list = `Lifted(`Right set)::prev_list in - callee_state f new_set new_prev_list rem_list) - end + let new_set = add_to_set prev_set e in + if loop_detected f e + then (`Right new_set)::rem_list + else callee_state f new_set (e::prev_list) rem_list - let callee_state f ctx = callee_state f (FundecSet.empty ()) [] ctx.local + let callee_state f ctx = `Lifted(callee_state f (FundecSet.empty ()) [] (get_list ctx.local)) let enter ctx r f args = [ctx.local, callee_state f ctx] From 89926d5706a444ae5804e0fdc117a188fbdf5d61 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 8 Mar 2024 20:37:22 +0100 Subject: [PATCH 109/128] updated g2html and gobview --- g2html | 2 +- gobview | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/g2html b/g2html index b18424d114..ee1bd82e20 160000 --- a/g2html +++ b/g2html @@ -1 +1 @@ -Subproject commit b18424d114c7838698b4323b49537d8e59faf55f +Subproject commit ee1bd82e20a5096629d745a647d4d9a2de234645 diff --git a/gobview b/gobview index 54346ca9f1..0013caa56a 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit 54346ca9f15186e0b190c47f9f41bd5061208300 +Subproject commit 0013caa56a89832c914e5941e250108e94266e0c From b2264136e61fe4507bede6cd7b1724fc44956807 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 12 Mar 2024 18:03:17 +0100 Subject: [PATCH 110/128] inf callstack option is now negative callstack height; implemented real call string approach and renamed the other approaches; updated callstring tests --- .../{callstringAnalysis.ml => callstring.ml} | 58 +++--- src/analyses/mCP.ml | 2 +- src/config/options.schema.json | 8 +- src/goblint_lib.ml | 2 +- .../01-multiple_tests_h5sens_cs.c | 136 +++++++++++++ .../02-multiple_tests_h5ins_cs.c | 132 +++++++++++++ .../03-multiple_tests_h2sens_cs.c | 187 ++++++++++++++++++ .../04-endless_loop_cs.c} | 3 +- .../05-ackermann_cs.c} | 3 +- .../06-big_loop_cs.c} | 3 +- .../82-callstring/07-loop_unrolling_cs.c | 24 +++ .../82-callstring/08-threads_sens_cs.c | 95 +++++++++ .../82-callstring/09-threads_ins_cs.c | 73 +++++++ .../10-inf_callstack_cs.c} | 4 +- .../11-multiple_tests_h5sens_csi.c | 132 +++++++++++++ .../12-multiple_tests_h5ins_csi.c | 128 ++++++++++++ .../13-multiple_tests_h2sens_csi.c | 180 +++++++++++++++++ .../82-callstring/14-endless_loop_csi.c | 25 +++ .../82-callstring/15-ackermann_csi.c | 28 +++ .../16-big_loop_csi.c} | 17 +- .../82-callstring/17-loop_unrolling_csi.c | 23 +++ .../82-callstring/18-threads_sens_csi.c | 91 +++++++++ .../82-callstring/19-threads_ins_csi.c | 70 +++++++ .../82-callstring/20-inf_callstack_csi.c | 21 ++ .../21-multiple_tests_h5sens_csWCallee.c | 136 +++++++++++++ .../22-multiple_tests_h5ins_csWCallee.c | 132 +++++++++++++ .../23-multiple_tests_h2sens_csWCallee.c | 183 +++++++++++++++++ .../82-callstring/24-endless_loop_csWCallee.c | 25 +++ .../82-callstring/25-ackermann_csWCallee.c | 28 +++ .../26-big_loop_csWCallee.c} | 25 +-- .../27-loop_unrolling_csWCallee.c} | 4 +- .../28-threads_sens_csWCallee.c} | 3 +- .../29-threads_ins_csWCallee.c} | 2 +- .../30-inf_callstack_csWCallee.c | 21 ++ .../01-loop_calling_sens.c | 25 --- .../02-loop_calling_ins.c | 32 --- .../05-multiple_calls_base_sens.c | 57 ------ .../06-multiple_calls_sens.c | 61 ------ .../07-multiple_calls_ins.c | 57 ------ .../82-callstring_fundec/08-new_calling_set.c | 36 ---- .../09-new_calling_set_ins.c | 36 ---- .../10-many_nested_loops_sens.c | 70 ------- .../11-value_update_sens.c | 23 --- .../12-value_update_ins.c | 23 --- .../01-simple_rec_inf_callstack.c | 22 --- .../83-callstring_Stmt/02-simple_rec_ins.c | 22 --- .../83-callstring_Stmt/03-multiple_rec_sens.c | 59 ------ .../83-callstring_Stmt/04-multiple_rec_ins.c | 59 ------ .../05-function_chain_sens.c | 54 ----- .../06-function_chain_ins.c | 54 ----- .../83-callstring_Stmt/07-call_in_call.c | 54 ----- .../08-circle_call_and_big_loop.c | 46 ----- .../83-callstring_Stmt/09-thread_creation.c | 88 --------- .../01-simple_rec_inf_callstack.c | 22 --- .../84-callstring_Loc/02-simple_rec_ins.c | 22 --- .../84-callstring_Loc/03-multiple_rec_sens.c | 59 ------ .../84-callstring_Loc/04-multiple_rec_ins.c | 59 ------ .../05-function_chain_sens.c | 54 ----- .../84-callstring_Loc/06-function_chain_ins.c | 54 ----- .../84-callstring_Loc/07-call_in_call.c | 54 ----- .../84-callstring_Loc/09-thread_creation.c | 88 --------- 61 files changed, 1931 insertions(+), 1363 deletions(-) rename src/analyses/{callstringAnalysis.ml => callstring.ml} (57%) create mode 100644 tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c create mode 100644 tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c create mode 100644 tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c rename tests/regression/{82-callstring_fundec/04-endless_loop.c => 82-callstring/04-endless_loop_cs.c} (86%) rename tests/regression/{82-callstring_fundec/03-ackermann.c => 82-callstring/05-ackermann_cs.c} (85%) rename tests/regression/{82-callstring_fundec/14-circle_call_and_big_loop.c => 82-callstring/06-big_loop_cs.c} (89%) create mode 100644 tests/regression/82-callstring/07-loop_unrolling_cs.c create mode 100644 tests/regression/82-callstring/08-threads_sens_cs.c create mode 100644 tests/regression/82-callstring/09-threads_ins_cs.c rename tests/regression/{82-callstring_fundec/18-simple_rec_inf_callstack.c => 82-callstring/10-inf_callstack_cs.c} (57%) create mode 100644 tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c create mode 100644 tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c create mode 100644 tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c create mode 100644 tests/regression/82-callstring/14-endless_loop_csi.c create mode 100644 tests/regression/82-callstring/15-ackermann_csi.c rename tests/regression/{82-callstring_fundec/13-circle_call_and_loops.c => 82-callstring/16-big_loop_csi.c} (57%) create mode 100644 tests/regression/82-callstring/17-loop_unrolling_csi.c create mode 100644 tests/regression/82-callstring/18-threads_sens_csi.c create mode 100644 tests/regression/82-callstring/19-threads_ins_csi.c create mode 100644 tests/regression/82-callstring/20-inf_callstack_csi.c create mode 100644 tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c create mode 100644 tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c create mode 100644 tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c create mode 100644 tests/regression/82-callstring/24-endless_loop_csWCallee.c create mode 100644 tests/regression/82-callstring/25-ackermann_csWCallee.c rename tests/regression/{84-callstring_Loc/08-circle_call_and_big_loop.c => 82-callstring/26-big_loop_csWCallee.c} (55%) rename tests/regression/{82-callstring_fundec/15-loop_unrolling.c => 82-callstring/27-loop_unrolling_csWCallee.c} (78%) rename tests/regression/{82-callstring_fundec/16-threads_sens.c => 82-callstring/28-threads_sens_csWCallee.c} (96%) rename tests/regression/{82-callstring_fundec/17-threads_ins.c => 82-callstring/29-threads_ins_csWCallee.c} (95%) create mode 100644 tests/regression/82-callstring/30-inf_callstack_csWCallee.c delete mode 100644 tests/regression/82-callstring_fundec/01-loop_calling_sens.c delete mode 100644 tests/regression/82-callstring_fundec/02-loop_calling_ins.c delete mode 100644 tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c delete mode 100644 tests/regression/82-callstring_fundec/06-multiple_calls_sens.c delete mode 100644 tests/regression/82-callstring_fundec/07-multiple_calls_ins.c delete mode 100644 tests/regression/82-callstring_fundec/08-new_calling_set.c delete mode 100644 tests/regression/82-callstring_fundec/09-new_calling_set_ins.c delete mode 100644 tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c delete mode 100644 tests/regression/82-callstring_fundec/11-value_update_sens.c delete mode 100644 tests/regression/82-callstring_fundec/12-value_update_ins.c delete mode 100644 tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c delete mode 100644 tests/regression/83-callstring_Stmt/02-simple_rec_ins.c delete mode 100644 tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c delete mode 100644 tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c delete mode 100644 tests/regression/83-callstring_Stmt/05-function_chain_sens.c delete mode 100644 tests/regression/83-callstring_Stmt/06-function_chain_ins.c delete mode 100644 tests/regression/83-callstring_Stmt/07-call_in_call.c delete mode 100644 tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c delete mode 100644 tests/regression/83-callstring_Stmt/09-thread_creation.c delete mode 100644 tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c delete mode 100644 tests/regression/84-callstring_Loc/02-simple_rec_ins.c delete mode 100644 tests/regression/84-callstring_Loc/03-multiple_rec_sens.c delete mode 100644 tests/regression/84-callstring_Loc/04-multiple_rec_ins.c delete mode 100644 tests/regression/84-callstring_Loc/05-function_chain_sens.c delete mode 100644 tests/regression/84-callstring_Loc/06-function_chain_ins.c delete mode 100644 tests/regression/84-callstring_Loc/07-call_in_call.c delete mode 100644 tests/regression/84-callstring_Loc/09-thread_creation.c diff --git a/src/analyses/callstringAnalysis.ml b/src/analyses/callstring.ml similarity index 57% rename from src/analyses/callstringAnalysis.ml rename to src/analyses/callstring.ml index a7d4dc0922..8ae938dd25 100644 --- a/src/analyses/callstringAnalysis.ml +++ b/src/analyses/callstring.ml @@ -2,31 +2,31 @@ open Analyses open GoblintCil open GobConfig -(* Specifies the type of the call-stack elements for the call-string analysis *) +(* Specifies the type of the call stack elements for the call string analysis *) module type Callstack_Type = sig include CilType.S val stackTypeName: string - val stackEle: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call-stack *) + val stackEle: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call stack *) end -(** Analysis with the k-call-string approach, which uses the last k call-stack elements as context. - With the CT argument it is possible to specify the type of the call-stack elements *) +(** Analysis with the k-call string approach, which uses the last k call stack elements as context. + With the CT argument it is possible to specify the type of the call stack elements *) module Spec (CT:Callstack_Type) : MCPSpec = struct include Analyses.IdentitySpec - (* simulates a call-stack of depth k *) + (* simulates a call stack of depth k *) module CallStack = struct include Printable.PQueue (CT) - let push stack elem = (* pushes elem to the call-stack, guarantees a depth of k if inf_callStack = false*) + let push stack elem = (* pushes elem to the call stack, guarantees a depth of k if it is specified with "ana.context.callStack_height" *) match elem with | None -> stack | Some e -> let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) - if get_bool "ana.context.inf_callStack" - then new_stack (* infinite call-stack*) + if get_int "ana.context.callStack_height" < 0 + then new_stack (* infinite call stack *) else (* removes element from stack, if stack was filled with k elements *) match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with @@ -40,9 +40,9 @@ struct module V = EmptyV module G = Lattice.Unit - let name () = "callstring_"^ CT.stackTypeName + let name () = "call_"^ CT.stackTypeName let startstate v = `Lifted (BatDeque.empty) - let exitstate v = `Lifted (BatDeque.empty) (*TODO: should I use startstate here? Does this make a difference*) + let exitstate v = `Lifted (BatDeque.empty) let context fd x = match x with | `Lifted x -> x @@ -60,30 +60,38 @@ struct let threadenter ctx ~multiple lval v args = [callee_state ctx (Cilfacade.find_varinfo_fundec v)] end -module Fundec:Callstack_Type = struct +module Callstring:Callstack_Type = struct include CilType.Fundec - let stackTypeName = "fundec" + let stackTypeName = "string" + let stackEle f ctx = + let f' = Node.find_fundec ctx.node in + if CilType.Fundec.equal f' dummyFunDec + then None + else Some (f') +end + +module Callstring_Callee:Callstack_Type = struct + include CilType.Fundec + let stackTypeName = "string_withCallee" let stackEle f ctx = Some f end -module Stmt:Callstack_Type = struct +module Callsite:Callstack_Type = struct include CilType.Stmt - let stackTypeName = "stmt" + let stackTypeName = "site" let stackEle f ctx = match ctx.prev_node with | Statement stmt -> Some stmt | _ -> None (* first statement is filtered *) end -module Location:Callstack_Type = struct - include CilType.Location - let stackTypeName = "loc" - let stackEle f ctx = - Some !Goblint_tracing.current_loc -end - -(* Lifters for the call-string approach with different call-stack element types *) +(* Lifters for the call string approach with different call stack element types *) let _ = - MCP.register_analysis (module Spec (Fundec) : MCPSpec); (* name: callstring_fundec *) - MCP.register_analysis (module Spec (Stmt) : MCPSpec); (* name: callstring_stmt *) - MCP.register_analysis (module Spec (Location) : MCPSpec) (* name: callstring_loc *) \ No newline at end of file + (* call string approach *) + MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string_og] *) + + (* call string approach: additionally tracks the callee function in the call stack *) + MCP.register_analysis (module Spec (Callstring_Callee) : MCPSpec); (* [call_string_incl_callee] *) + + (* call site approach *) + MCP.register_analysis (module Spec (Callsite) : MCPSpec); (* [call_site] *) \ No newline at end of file diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 7a38c4e639..2503ca9037 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -67,7 +67,7 @@ struct let specific_cont_sens xs = (* most analysis must be set to context-insensitive, because we only want to analyse context-sensitive for one specific analysis *) - let sens_ana = ["callstring_fundec"; "callstring_stmt"; "callstring_loc"; "loopfree_callstring"] in + let sens_ana = ["call_string_withCallee"; "call_string"; "call_site"; "loopfree_callstring"] in let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in (* returns the edited list of insensitive analyses if enabled *) if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 378cc31f08..05f496aa0e 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -976,15 +976,9 @@ "type": "integer", "default": 10 }, - "inf_callStack": { - "title": "ana.context.inf_callStack", - "description": "If true, the call-stack of the call.string analysis is infinite.", - "type": "boolean", - "default": false - }, "callStack_height": { "title": "ana.context.callStack_height", - "description": "Height of the call-stack that should be used as context for the call-string analysis. Must be >= 0!", + "description": "Height of the call stack that should be used as context for the call string analysis. In case the value is zero, the analysis is context-insensitive. For a negative value an infinite call stack is used!", "type": "integer", "default": 10 } diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 356bfb6112..d953edaec9 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -150,7 +150,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module LoopTermination = LoopTermination -module CallstringAnalysis = CallstringAnalysis +module Callstring = Callstring module LoopfreeCallstring = LoopfreeCallstring module Uninit = Uninit module Expsplit = Expsplit diff --git a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c new file mode 100644 index 0000000000..75bad75496 --- /dev/null +++ b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c @@ -0,0 +1,136 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(4) -> ... -> a(0) -> return 11 + [main, a, a, a, a] */ + __goblint_check(a(4) == 11); + + /* main -> a(7) -> ... -> a(0) -> return 11 + [main, a, a, a, a] and [a, a, a, a, a] (3 times) */ + __goblint_check(a(7) == 11); + + /* main -> b(4) -> a(3) -> a(2) -> a(1) -> a(0) -> return 11 + [main, b, a, a, a] */ + __goblint_check(b(4) == 11); + + /* main -> c(4) -> b(3) -> a(2) -> a(1) -> a(0) -> return 11 + [main, c, b, a, a] */ + __goblint_check(c(4) == 11); + + // Test 2: + /* main -> e(5) -> f(4) -> e(3) -> f(2) -> e(1) -> f(0) -> return 2 + [main, e, f, e, f] and [e, f , e, f, e]*/ + __goblint_check(e(5) == 5); + + // Test 3: + /* main -> k(9) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k, k, k, k] and [k, k, k, k, k] (3 times) and [k, k, k, k, h] */ + __goblint_check(k(9) == 2); + + // Test 4: + /* main -> o(5) -> o(4) -> ... o(0) + [main, o, o, o, o] and [o, o, o, o, o] */ + o(5); + __goblint_check(m == 0); + + return 0; +} diff --git a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c new file mode 100644 index 0000000000..5ca535585e --- /dev/null +++ b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c @@ -0,0 +1,132 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(8) -> ... -> a(0) -> return 11 + [main, a, a, a, a] and [a, a, a, a, a] (4 times) */ + __goblint_check(a(8) == 11); // UNKNOWN + + /* main -> b(21) -> a(20) -> ... -> a(1) -> a(0) -> return 11 + [main, b, a, a, a] and [g, a, a, a, a] and [a, a, a, a, a] (16 times) */ + __goblint_check(b(21) == 11); // UNKNOWN + + /* main -> c(11) -> b(10) -> a(9) -> ... -> a(0) -> return 11 + [main, c, b, a, a] and [c, b, a, a, a] and [b, a, a, a, a] and [a, a, a, a, a] (5 times) */ + __goblint_check(c(11) == 11); // UNKNOWN + + // Test 2: + /* main -> e(7) -> f(6) -> e(5) -> ... -> e(1) -> f(0) -> return 2 + [main, e, f, e, f] and [e, f , e, f, e] (2 times) and [f , e, f, e, f] */ + __goblint_check(e(7) == 6); // UNKNOWN + + // Test 3: + /* main -> k(10) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k, k, k, k] and [k, k, k, k, k] (4 times) and [k, k, k, k, h] */ + __goblint_check(k(10) == 2); // UNKNOWN + + // Test 4: + /* main -> o(6) -> o(5) -> ... o(0) + [main, o, o, o, o] and [o, o, o, o, o] (2 times) */ + o(6); + __goblint_check(m == 0); // UNKNOWN + + return 0; +} diff --git a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c new file mode 100644 index 0000000000..65f17dc7e2 --- /dev/null +++ b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c @@ -0,0 +1,187 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int q(int i); + +int l(int i) +{ + if (i == 0) + { + return q(2); + } + else + { + return 4; + } +} + +int p(int i) +{ + return l(i - 1); +} + +int s(int i) +{ + return p(i - 1); +} + +int r(int i) +{ + return q(i - 1); +} + +int o(int i) +{ + if (i <= 0) + { + return r(4); + } + else + { + return o(i - 1); + } +} + +int q(int i) +{ + if (i == 4) + { + return o(3); + } + if (i == 3) + { + return s(2); + } + return p(20); +} + +int m(int i) +{ + return q(i); +} + +int main(void) +{ + // Test 1: + /* main -> a(1) -> a(0) -> return 11 + [main, a] */ + __goblint_check(a(1) == 11); + + /* main -> a(0) -> return 11 + [main] */ + __goblint_check(a(0) == 11); + + /* main -> b(0) -> return 12 + [main] */ + __goblint_check(b(0) == 12); + + /* main -> c(0) -> return 13 + [main] */ + __goblint_check(c(0) == 13); + + // Test 2: + /* main -> f(0) -> return 2 + [main] */ + __goblint_check(f(0) == 2); + + /* main -> e(0) -> f(-1) -> return 2 + [main, e] */ + __goblint_check(e(0) == 3); + + // Test 3: + /* main -> k(6) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k] and [k, k] (3 times) and [k, h] and [h, h] */ + __goblint_check(k(6) == 2); + + // Test 4: + /* main -> m(4) -> q(4) -> o(3) -> o(2) -> o(1) -> o(0) -> r(4) -> q(3) -> s(2) -> p(1) -> l(0) -> q(2) -> p(20) -> l(19) -> return 4 + [main, m] and [m, q] an [q, o] and [o, o] (3 times) and + [o, r] and [r, q] and [q, s] and [s, p] and [p, l] and [l, q] and [q, p] and [p, l] */ + __goblint_check(m(4) == 4); + + return 0; +} diff --git a/tests/regression/82-callstring_fundec/04-endless_loop.c b/tests/regression/82-callstring/04-endless_loop_cs.c similarity index 86% rename from tests/regression/82-callstring_fundec/04-endless_loop.c rename to tests/regression/82-callstring/04-endless_loop_cs.c index 0fd4f49e3a..5b799bfe8a 100644 --- a/tests/regression/82-callstring_fundec/04-endless_loop.c +++ b/tests/regression/82-callstring/04-endless_loop_cs.c @@ -1,6 +1,5 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis -#include int num_iterat = 2; diff --git a/tests/regression/82-callstring_fundec/03-ackermann.c b/tests/regression/82-callstring/05-ackermann_cs.c similarity index 85% rename from tests/regression/82-callstring_fundec/03-ackermann.c rename to tests/regression/82-callstring/05-ackermann_cs.c index 6464222bda..dbbd059e46 100644 --- a/tests/regression/82-callstring_fundec/03-ackermann.c +++ b/tests/regression/82-callstring/05-ackermann_cs.c @@ -1,5 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -#include +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c b/tests/regression/82-callstring/06-big_loop_cs.c similarity index 89% rename from tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c rename to tests/regression/82-callstring/06-big_loop_cs.c index 92a3dad6ba..b40dc10dee 100644 --- a/tests/regression/82-callstring_fundec/14-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring/06-big_loop_cs.c @@ -1,6 +1,5 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed -#include int f(int i); diff --git a/tests/regression/82-callstring/07-loop_unrolling_cs.c b/tests/regression/82-callstring/07-loop_unrolling_cs.c new file mode 100644 index 0000000000..496f3ed6ba --- /dev/null +++ b/tests/regression/82-callstring/07-loop_unrolling_cs.c @@ -0,0 +1,24 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --enable ana.int.interval_set --set exp.unrolling-factor 2 + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int main(void) +{ + for (int i = 5; i > 0; i--) + { + // main -> f(4) -> ... -> f(0) -> return 1 + // [main, f] and [f, f] (3 times) + __goblint_check(f(4) == 1); + } +} diff --git a/tests/regression/82-callstring/08-threads_sens_cs.c b/tests/regression/82-callstring/08-threads_sens_cs.c new file mode 100644 index 0000000000..3ed9f46b36 --- /dev/null +++ b/tests/regression/82-callstring/08-threads_sens_cs.c @@ -0,0 +1,95 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + // main -> t_sens -> procedure -> f(0) + // main -> t_sens -> procedure -> g(0) + // main -> t_sens -> procedure -> h(0) + __goblint_check(procedure(0) == 8); + return NULL; +} + +void *t_sens2(void *arg) +{ + // main -> t_sens2 -> procedure -> f(9) -> ... -> f(0) + // [main, t_sens2, procedure, f, f, f, f, f, f, f] and [t_sens2, procedure, f, f, f, f, f, f, f, f] and [procedure, f, f, f, f, f, f, f, f, f] + // main -> t_sens2 -> procedure -> g(9) -> g(8) -> ... -> g(0) + // main -> t_sens2 -> procedure -> h(9) -> g(8) -> ... -> g(0) + __goblint_check(procedure(9) == 10); + return NULL; +} + +void *t_sens3(void *arg) +{ + // main -> t_sens3 -> procedure -> f(12) -> ... -> f(0) + // [main, t_sens3, procedure, f, f, f, f, f, f, f] and [t_sens3, procedure, f, f, f, f, f, f, f, f] and + // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (3 times) + + // main -> t_sens3 -> procedure -> g(12) -> g(11) -> ... -> g(0) + // main -> t_sens3 -> procedure -> h(12) -> g(11) -> ... -> g(0) + __goblint_check(procedure(12) == 10); + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + pthread_t id3; + + // Create the thread + pthread_create(&id, NULL, t_sens, NULL); + pthread_create(&id2, NULL, t_sens2, NULL); + pthread_create(&id3, NULL, t_sens3, NULL); + return 0; +} diff --git a/tests/regression/82-callstring/09-threads_ins_cs.c b/tests/regression/82-callstring/09-threads_ins_cs.c new file mode 100644 index 0000000000..e4b68938d5 --- /dev/null +++ b/tests/regression/82-callstring/09-threads_ins_cs.c @@ -0,0 +1,73 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_ins(void *arg) +{ + // main -> t_ins -> procedure -> f(13) -> ... -> f(0) + // [main, t_ins, procedure, f, f, f, f, f, f, f] and [t_ins, procedure, f, f, f, f, f, f, f, f] and + // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (4 times) + + // main -> t_ins -> procedure -> g(13) -> g(12) -> ... -> g(0) + // main -> t_ins -> procedure -> h(13) -> g(12) -> ... -> g(0) + __goblint_check(procedure(13) == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Create the thread + pthread_create(&id, NULL, t_ins, NULL); + return 0; +} diff --git a/tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c b/tests/regression/82-callstring/10-inf_callstack_cs.c similarity index 57% rename from tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c rename to tests/regression/82-callstring/10-inf_callstack_cs.c index 35a35dbadf..67ccf2e56c 100644 --- a/tests/regression/82-callstring_fundec/18-simple_rec_inf_callstack.c +++ b/tests/regression/82-callstring/10-inf_callstack_cs.c @@ -1,5 +1,5 @@ -// PARAM: --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --enable ana.context.inf_callStack -// Basic example +// PARAM: --set "ana.activated[+]" call_string --enable ana.int.interval_set --set ana.context.callStack_height -1 + #include int a = 20; diff --git a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c new file mode 100644 index 0000000000..2b953e13cc --- /dev/null +++ b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c @@ -0,0 +1,132 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(3) -> ... -> a(0) -> return 11 + [a(), a(i-1), a(i-1), a(i-1)] */ + __goblint_check(a(3) == 11); + + /* main -> a(7) -> ... -> a(0) -> return 11 + [a(), a(i-1), a(i-1), a(i-1), a(i-1)] and [a(i-1), a(i-1), a(i-1), a(i-1), a(i-1)] (3 times) */ + __goblint_check(a(7) == 11); + + /* main -> b(3) -> a(2) -> a(1) -> a(0) -> return 11 + [b(), a(), a(i-1), a(i-1)] */ + __goblint_check(b(3) == 11); + + /* main -> c(3) -> b(2) -> a(1) -> a(0) -> return 11 */ + __goblint_check(c(3) == 11); + + // Test 2: + /* main -> e(5) -> f(4) -> e(3) -> f(2) -> e(1) -> f(0) -> return 2 */ + __goblint_check(e(5) == 5); + + // Test 3: + /* main -> k(9) -> ... -> k(2) -> h(1) -> h(0) -> return 1 */ + __goblint_check(k(9) == 2); + + // Test 4: + /* main -> o(5) -> o(3) -> ... o(0)*/ + o(5); + __goblint_check(m == 0); + + return 0; +} diff --git a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c new file mode 100644 index 0000000000..56f13c36d9 --- /dev/null +++ b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c @@ -0,0 +1,128 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(7) -> ... -> a(0) -> return 11 */ + __goblint_check(a(8) == 11); // UNKNOWN + + /* main -> b(21) -> a(20) -> ... -> a(0) -> return 11 */ + __goblint_check(b(21) == 11); // UNKNOWN + + /* main -> c(11) -> b(10) -> a(9) -> ... -> a(0) -> return 11 */ + __goblint_check(c(11) == 11); // UNKNOWN + + // Test 2: + /* main -> e(7) -> f(6) -> e(5) -> ... -> e(1) -> f(0) -> return 2 */ + __goblint_check(e(7) == 6); // UNKNOWN + + // Test 3: + /* main -> k(10) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k, k, k, k] and [k, k, k, k, k] (4 times) and [k, k, k, k, h] */ + __goblint_check(k(10) == 2); // UNKNOWN + + // Test 4: + /* main -> o(6) -> o(5) -> ... o(0) + [main, o, o, o, o] and [o, o, o, o, o] (2 times) */ + o(6); + __goblint_check(m == 0); // UNKNOWN + + return 0; +} diff --git a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c new file mode 100644 index 0000000000..e65606916f --- /dev/null +++ b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c @@ -0,0 +1,180 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int q(int i); + +int l(int i) +{ + if (i == 0) + { + return q(2); + } + else + { + return 4; + } +} + +int p(int i) +{ + return l(i - 1); +} + +int s(int i) +{ + return p(i - 1); +} + +int r(int i) +{ + return q(i - 1); +} + +int o(int i) +{ + if (i <= 0) + { + return r(4); + } + else + { + return o(i - 1); + } +} + +int q(int i) +{ + if (i == 4) + { + return o(3); + } + if (i == 3) + { + return s(2); + } + return p(20); +} + +int m(int i) +{ + return q(i); +} + +int main(void) +{ + // Test 1: + /* main -> a(0) -> return 11 + [a()] */ + __goblint_check(a(0) == 11); + + /* main -> b(0) -> return 12 + [b()] */ + __goblint_check(b(0) == 12); + + /* main -> c(0) -> return 13 + [c()] */ + __goblint_check(c(0) == 13); + + // Test 2: + /* main -> f(0) -> return 2 + [f()] */ + __goblint_check(f(0) == 2); + + /* main -> e(0) -> f(-1) -> return 2 + [e(), f(i - 1)] */ + __goblint_check(e(0) == 3); + + // Test 3: + /* main -> k(6) -> ... -> k(2) -> h(1) -> h(0) -> return 1 */ + __goblint_check(k(6) == 2); + + // Test 4: + /* main -> m(4) -> q(4) -> o(3) -> o(2) -> o(1) -> o(0) -> r(4) -> q(3) -> s(2) -> p(1) -> l(0) -> q(2) -> p(20) -> l(19) -> return 4 */ + __goblint_check(m(5) == 4); + + return 0; +} diff --git a/tests/regression/82-callstring/14-endless_loop_csi.c b/tests/regression/82-callstring/14-endless_loop_csi.c new file mode 100644 index 0000000000..b6818b3512 --- /dev/null +++ b/tests/regression/82-callstring/14-endless_loop_csi.c @@ -0,0 +1,25 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis + +int num_iterat = 2; + +// main -> main -> ... +// [main, main, ...] +int main(void) +{ + if (num_iterat > 0) + { + num_iterat++; + int res = main(); + __goblint_check(res == 5); // UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} \ No newline at end of file diff --git a/tests/regression/82-callstring/15-ackermann_csi.c b/tests/regression/82-callstring/15-ackermann_csi.c new file mode 100644 index 0000000000..0167f8a5f5 --- /dev/null +++ b/tests/regression/82-callstring/15-ackermann_csi.c @@ -0,0 +1,28 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) +{ + // main -> ack -> ack -> ... + // [main, ack, ...] + ack(4, 1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/82-callstring_fundec/13-circle_call_and_loops.c b/tests/regression/82-callstring/16-big_loop_csi.c similarity index 57% rename from tests/regression/82-callstring_fundec/13-circle_call_and_loops.c rename to tests/regression/82-callstring/16-big_loop_csi.c index 2436d6159f..e2deb86fb2 100644 --- a/tests/regression/82-callstring_fundec/13-circle_call_and_loops.c +++ b/tests/regression/82-callstring/16-big_loop_csi.c @@ -1,6 +1,5 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Checks proper handling of recursions in loops + shows that not all 90 recursions are analyzed -#include +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); @@ -32,13 +31,11 @@ int f(int i) int main(void) { - int res1 = 0; - int res2 = 0; - for (int i = 2; i > 0; i--) + for (int i = 200; i > 0; i--) { - res1 = f(200); - res2 = g(200); - __goblint_check(res1 == 2); // UNKNOWN - __goblint_check(res2 == 1); // UNKNOWN + int res1 = f(2); + int res2 = g(2); + __goblint_check(res1 == 2); + __goblint_check(res2 == 1); } } diff --git a/tests/regression/82-callstring/17-loop_unrolling_csi.c b/tests/regression/82-callstring/17-loop_unrolling_csi.c new file mode 100644 index 0000000000..3e53897862 --- /dev/null +++ b/tests/regression/82-callstring/17-loop_unrolling_csi.c @@ -0,0 +1,23 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set --set exp.unrolling-factor 2 + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int main(void) +{ + for (int i = 5; i > 0; i--) + { + // main -> f(4) -> ... -> f(0) -> return 1 + __goblint_check(f(4) == 1); + } +} diff --git a/tests/regression/82-callstring/18-threads_sens_csi.c b/tests/regression/82-callstring/18-threads_sens_csi.c new file mode 100644 index 0000000000..adacbcb59b --- /dev/null +++ b/tests/regression/82-callstring/18-threads_sens_csi.c @@ -0,0 +1,91 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_sens(void *arg) +{ + // main -> t_sens -> procedure -> f(0) + // main -> t_sens -> procedure -> g(0) + // main -> t_sens -> procedure -> h(0) + __goblint_check(procedure(0) == 8); + return NULL; +} + +void *t_sens2(void *arg) +{ + // main -> t_sens2 -> procedure -> f(8) -> ... -> f(0) + // main -> t_sens2 -> procedure -> g(8) -> g(7) -> ... -> g(0) + // main -> t_sens2 -> procedure -> h(8) -> g(7) -> ... -> g(0) + __goblint_check(procedure(8) == 10); + return NULL; +} + +void *t_sens3(void *arg) +{ + // main -> t_sens3 -> procedure -> f(12) -> ... -> f(0) + // main -> t_sens3 -> procedure -> g(12) -> g(11) -> ... -> g(0) + // main -> t_sens3 -> procedure -> h(12) -> g(11) -> ... -> g(0) + __goblint_check(procedure(12) == 10); + return NULL; +} + +int main() +{ + pthread_t id; + pthread_t id2; + pthread_t id3; + + // Create the thread + pthread_create(&id, NULL, t_sens, NULL); + pthread_create(&id2, NULL, t_sens2, NULL); + pthread_create(&id3, NULL, t_sens3, NULL); + return 0; +} diff --git a/tests/regression/82-callstring/19-threads_ins_csi.c b/tests/regression/82-callstring/19-threads_ins_csi.c new file mode 100644 index 0000000000..c94e704b72 --- /dev/null +++ b/tests/regression/82-callstring/19-threads_ins_csi.c @@ -0,0 +1,70 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +#include +#include +#include + +int f(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return f(i - 1); + } + return 11; +} + +int g(int i) +{ + if (i == 0) + { + return 3; + } + if (i > 0) + { + return g(i - 1); + } + return 13; +} + +int h(int i) +{ + if (i == 0) + { + return 2; + } + if (i > 0) + { + return g(i - 1); + } + return 12; +} + +int procedure(int num_iterat) +{ + int res1 = f(num_iterat); + int res2 = g(num_iterat); + int res3 = h(num_iterat); + int res4 = h(num_iterat); + return res1 + res2 + res3 + res4; +} + +void *t_ins(void *arg) +{ + // main -> t_ins -> procedure -> f(13) -> ... -> f(0) + // main -> t_ins -> procedure -> g(13) -> g(12) -> ... -> g(0) + // main -> t_ins -> procedure -> h(13) -> g(12) -> ... -> g(0) + __goblint_check(procedure(13) == 10); // UNKNOWN + return NULL; +} + +int main() +{ + pthread_t id; + + // Create the thread + pthread_create(&id, NULL, t_ins, NULL); + return 0; +} diff --git a/tests/regression/82-callstring/20-inf_callstack_csi.c b/tests/regression/82-callstring/20-inf_callstack_csi.c new file mode 100644 index 0000000000..f1c0daa72f --- /dev/null +++ b/tests/regression/82-callstring/20-inf_callstack_csi.c @@ -0,0 +1,21 @@ +// PARAM: --set "ana.activated[+]" call_site --enable ana.int.interval_set --set ana.context.callStack_height -1 + +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(25); + __goblint_check(a == 0); +} diff --git a/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c b/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c new file mode 100644 index 0000000000..d52cfc2fbc --- /dev/null +++ b/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c @@ -0,0 +1,136 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(3) -> ... -> a(0) -> return 11 + [main, a, a, a, a] */ + __goblint_check(a(3) == 11); + + /* main -> a(6) -> ... -> a(0) -> return 11 + [main, a, a, a, a] and [a, a, a, a, a] (3 times) */ + __goblint_check(a(6) == 11); + + /* main -> b(3) -> a(2) -> a(1) -> a(0) -> return 11 + [main, b, a, a, a] */ + __goblint_check(b(3) == 11); + + /* main -> c(3) -> b(2) -> a(1) -> a(0) -> return 11 + [main, c, b, a, a] */ + __goblint_check(c(3) == 11); + + // Test 2: + /* main -> e(5) -> f(4) -> e(3) -> f(2) -> e(1) -> f(0) -> return 2 + [main, e, f, e, f] and [e, f , e, f, e] and [f , e, f, e, f]*/ + __goblint_check(e(5) == 5); + + // Test 3: + /* main -> k(8) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k, k, k, k] and [k, k, k, k, k] (3 times) and [k, k, k, k, h] */ + __goblint_check(k(8) == 2); + + // Test 4: + /* main -> o(4) -> o(3) -> ... o(0) + [main, o, o, o, o] and [o, o, o, o, o] */ + o(4); + __goblint_check(m == 0); + + return 0; +} diff --git a/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c b/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c new file mode 100644 index 0000000000..74e2673d2f --- /dev/null +++ b/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c @@ -0,0 +1,132 @@ +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int m = 20; + +int o(int i) +{ + if (i > 0) + { + m = --i; + o(i); + } + return 0; +} + +int main(void) +{ + // Test 1: + /* main -> a(7) -> ... -> a(0) -> return 11 + [main, a, a, a, a] and [a, a, a, a, a] (4 times) */ + __goblint_check(a(7) == 11); // UNKNOWN + + /* main -> b(20) -> a(19) -> ... -> a(0) -> return 11 + [main, b, a, a, a] and [g, a, a, a, a] and [a, a, a, a, a] (16 times) */ + __goblint_check(b(20) == 11); // UNKNOWN + + /* main -> c(10) -> b(9) -> a(8) -> ... -> a(0) -> return 11 + [main, c, b, a, a] and [c, b, a, a, a] and [b, a, a, a, a] and [a, a, a, a, a] (5 times) */ + __goblint_check(c(10) == 11); // UNKNOWN + + // Test 2: + /* main -> e(7) -> f(6) -> e(5) -> ... -> e(1) -> f(0) -> return 2 + [main, e, f, e, f] and [e, f , e, f, e] (2 times) and [f , e, f, e, f] (2 times) */ + __goblint_check(e(7) == 6); // UNKNOWN + + // Test 3: + /* main -> k(9) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k, k, k, k] and [k, k, k, k, k] (4 times) and [k, k, k, k, h] */ + __goblint_check(k(9) == 2); // UNKNOWN + + // Test 4: + /* main -> o(5) -> o(4) -> ... o(0) + [main, o, o, o, o] and [o, o, o, o, o] (2 times) */ + o(5); + __goblint_check(m == 0); // UNKNOWN + + return 0; +} diff --git a/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c b/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c new file mode 100644 index 0000000000..26bc0fcb7f --- /dev/null +++ b/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c @@ -0,0 +1,183 @@ +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set + +// Test 1: +int a(int i) +{ + if (i == 0) + { + return 11; + } + if (i > 0) + { + return a(i - 1); + } + return 1; +} + +int b(int i) +{ + if (i == 0) + { + return 12; + } + if (i > 0) + { + return a(i - 1); + } + return 2; +} + +int c(int i) +{ + if (i == 0) + { + return 13; + } + if (i > 0) + { + return b(i - 1); + } + return 3; +} + +// Test 2: +int e(int i); + +int f(int i) +{ + if (i > 0) + { + return e(i - 1); + } + return 2; +} + +int e(int i) +{ + return f(i - 1) + 1; +} + +// Test 3: +int h(int i) +{ + if (i == 0) + { + return 1; + } + if (i > 0) + { + return h(i - 1); + } + return 0; +} + +int k(int i) +{ + if (i == 2) + { + return h(i - 1) + 1; + } + if (i > 0) + { + return k(i - 1); + } + return 1; +} + +// Test 4: +int q(int i); + +int l(int i) +{ + if (i == 0) + { + return q(2); + } + else + { + return 4; + } +} + +int p(int i) +{ + return l(i - 1); +} + +int s(int i) +{ + return p(i - 1); +} + +int r(int i) +{ + return q(i - 1); +} + +int o(int i) +{ + if (i <= 0) + { + return r(4); + } + else + { + return o(i - 1); + } +} + +int q(int i) +{ + if (i == 4) + { + return o(3); + } + if (i == 3) + { + return s(2); + } + return p(20); +} + +int m(int i) +{ + return q(i); +} + +int main(void) +{ + // Test 1: + /* main -> a(0) -> return 11 + [main, a] */ + __goblint_check(a(0) == 11); + + /* main -> b(0) -> return 12 + [main, b] */ + __goblint_check(b(0) == 12); + + /* main -> c(0) -> return 13 + [main, c] */ + __goblint_check(c(0) == 13); + + // Test 2: + /* main -> f(0) -> return 2 + [main, f] */ + __goblint_check(f(0) == 2); + + /* main -> e(0) -> f(-1) -> return 2 + [main, e] and [e, f] */ + __goblint_check(e(0) == 3); + + // Test 3: + /* main -> k(5) -> ... -> k(2) -> h(1) -> h(0) -> return 1 + [main, k] and [k, k] (3 times) and [k, h] and [h, h] */ + __goblint_check(k(5) == 2); + + // Test 4: + /* main -> m(4) -> q(4) -> o(3) -> o(2) -> o(1) -> o(0) -> r(4) -> q(3) -> s(2) -> p(1) -> l(0) -> q(2) -> p(20) -> l(19) -> return 4 + [main, m] and [m, q] an [q, o] and [o, o] (3 times) and + [o, r] and [r, q] and [q, s] and [s, p] and [p, l] and [l, q] and [q, p] and [p, l] */ + __goblint_check(m(4) == 4); + + return 0; +} diff --git a/tests/regression/82-callstring/24-endless_loop_csWCallee.c b/tests/regression/82-callstring/24-endless_loop_csWCallee.c new file mode 100644 index 0000000000..1ec78577ce --- /dev/null +++ b/tests/regression/82-callstring/24-endless_loop_csWCallee.c @@ -0,0 +1,25 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// Will result in an endless loop without context insensitive analysis + +int num_iterat = 2; + +// main -> main -> ... +// [main, main, ...] +int main(void) +{ + if (num_iterat > 0) + { + num_iterat++; + int res = main(); + __goblint_check(res == 5); // UNKNOWN + return res; + } + else + { + if (num_iterat == 0) + { + return 5; + } + return 2; + } +} \ No newline at end of file diff --git a/tests/regression/82-callstring/25-ackermann_csWCallee.c b/tests/regression/82-callstring/25-ackermann_csWCallee.c new file mode 100644 index 0000000000..6db58caf12 --- /dev/null +++ b/tests/regression/82-callstring/25-ackermann_csWCallee.c @@ -0,0 +1,28 @@ +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set + +int ack(int n, int m) +{ + if (n == 0) + { + return m + 1; + } + else + { + if (m == 0) + { + return ack(n - 1, 1); + } + else + { + return ack(n - 1, ack(n, m - 1)); + } + } +} + +int main(void) +{ + // main -> ack -> ack -> ... + // [main, ack, ...] + ack(4, 1); + __goblint_check(1); // reachable +} \ No newline at end of file diff --git a/tests/regression/84-callstring_Loc/08-circle_call_and_big_loop.c b/tests/regression/82-callstring/26-big_loop_csWCallee.c similarity index 55% rename from tests/regression/84-callstring_Loc/08-circle_call_and_big_loop.c rename to tests/regression/82-callstring/26-big_loop_csWCallee.c index 2c3e7184cf..6b43259b62 100644 --- a/tests/regression/84-callstring_Loc/08-circle_call_and_big_loop.c +++ b/tests/regression/82-callstring/26-big_loop_csWCallee.c @@ -1,45 +1,40 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed -#include - -int num_iterat = 2; +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); int g(int i) { - int res = 0; if (i == 0) { - res = 1; + return 1; } if (i > 0) { - res = f(--i); + return f(i - 1); } - return res; + return 11; } int f(int i) { - int res = 0; if (i == 0) { - res = 2; + return 2; } if (i > 0) { - res = g(--i); + return g(i - 1); } - return res; + return 12; } int main(void) { for (int i = 200; i > 0; i--) { - int res1 = f(num_iterat); - int res2 = g(num_iterat); + int res1 = f(2); + int res2 = g(2); __goblint_check(res1 == 2); __goblint_check(res2 == 1); } diff --git a/tests/regression/82-callstring_fundec/15-loop_unrolling.c b/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c similarity index 78% rename from tests/regression/82-callstring_fundec/15-loop_unrolling.c rename to tests/regression/82-callstring/27-loop_unrolling_csWCallee.c index c330da091d..5ac8ddcd89 100644 --- a/tests/regression/82-callstring_fundec/15-loop_unrolling.c +++ b/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c @@ -1,6 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set --set exp.unrolling-factor 3 - -#include +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring_fundec/16-threads_sens.c b/tests/regression/82-callstring/28-threads_sens_csWCallee.c similarity index 96% rename from tests/regression/82-callstring_fundec/16-threads_sens.c rename to tests/regression/82-callstring/28-threads_sens_csWCallee.c index 24f10edaf6..70927d29b1 100644 --- a/tests/regression/82-callstring_fundec/16-threads_sens.c +++ b/tests/regression/82-callstring/28-threads_sens_csWCallee.c @@ -1,6 +1,5 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set #include -#include #include int f(int i) diff --git a/tests/regression/82-callstring_fundec/17-threads_ins.c b/tests/regression/82-callstring/29-threads_ins_csWCallee.c similarity index 95% rename from tests/regression/82-callstring_fundec/17-threads_ins.c rename to tests/regression/82-callstring/29-threads_ins_csWCallee.c index bbe87be424..3c929f4398 100644 --- a/tests/regression/82-callstring_fundec/17-threads_ins.c +++ b/tests/regression/82-callstring/29-threads_ins_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/30-inf_callstack_csWCallee.c b/tests/regression/82-callstring/30-inf_callstack_csWCallee.c new file mode 100644 index 0000000000..c6e5e6e61f --- /dev/null +++ b/tests/regression/82-callstring/30-inf_callstack_csWCallee.c @@ -0,0 +1,21 @@ +// PARAM: --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set --set ana.context.callStack_height -1 + +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + f(25); + __goblint_check(a == 0); +} diff --git a/tests/regression/82-callstring_fundec/01-loop_calling_sens.c b/tests/regression/82-callstring_fundec/01-loop_calling_sens.c deleted file mode 100644 index 87af18fcd3..0000000000 --- a/tests/regression/82-callstring_fundec/01-loop_calling_sens.c +++ /dev/null @@ -1,25 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set - -int f(int i); - -int g(int i) -{ - if (i > 0) - { - return f(i - 1); - } - return 2; -} - -int f(int i) -{ - return g(i - 1); -} - -int main() -{ - // main -> f(7) -> g(6) -> f(5) -> ... -> f(1) -> g(0) -> return 2 - // [main, f, g, f, g, f, g, f, g] - __goblint_check(f(7) == 2); - return 0; -} diff --git a/tests/regression/82-callstring_fundec/02-loop_calling_ins.c b/tests/regression/82-callstring_fundec/02-loop_calling_ins.c deleted file mode 100644 index b02a4fd495..0000000000 --- a/tests/regression/82-callstring_fundec/02-loop_calling_ins.c +++ /dev/null @@ -1,32 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i); - -int g(int i) -{ - if (i > 0) - { - return f(i - 1); - } - return 2; -} - -int f(int i) -{ - if (i > 0) - { - return g(i - 1); - } - return 1; -} - -int main(void) -{ - // main -> f(15) -> g(14) -> f(13) -> ... -> g(2) -> f(1) -> g(0) -> return 2 - // [main, f, g, f, g, f, g, f, g, f] and - // [f, g, f, g, f, g, f, g, f, g] (4 times) and - // [g, f, g, f, g, f, g, f, g, f] (3 times) - __goblint_check(f(15) == 2); // UNKNOWN -} diff --git a/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c b/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c deleted file mode 100644 index f45e83dbc3..0000000000 --- a/tests/regression/82-callstring_fundec/05-multiple_calls_base_sens.c +++ /dev/null @@ -1,57 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return f(i - 1); - } - return 1; -} - -int g(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return f(i - 1); - } - return 2; -} - -int h(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return g(i - 1); - } - return 3; -} - -int main(void) -{ - // main -> f(0) -> return 11 - // [main, f] - __goblint_check(f(0) == 11); - - // main -> g(0) -> return 12 - // [main, g] - __goblint_check(g(0) == 12); - - // main -> h(0) -> return 13 - // [main, h] - __goblint_check(h(0) == 13); -} diff --git a/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c b/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c deleted file mode 100644 index cbd63d5e4a..0000000000 --- a/tests/regression/82-callstring_fundec/06-multiple_calls_sens.c +++ /dev/null @@ -1,61 +0,0 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return f(i - 1); - } - return 1; -} - -int g(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return f(i - 1); - } - return 2; -} - -int h(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return g(i - 1); - } - return 3; -} - -int main(void) -{ - // main -> f(3) -> ... -> f(0) -> return 11 - // [main, f, f, f, f] - __goblint_check(f(3) == 11); - - // main -> f(6) -> ... -> f(0) -> return 11 - // [main, f, f, f, f] and [f, f, f, f, f] (3 times) - __goblint_check(f(6) == 11); - - // main -> g(3) -> f(2) -> f(1) -> f(0) -> return 11 - // [main, g, f, f, f] - __goblint_check(g(3) == 11); - - // main -> h(3) -> g(2) -> f(1) -> f(0) -> return 11 - // [main, h, g, f, f] - __goblint_check(h(3) == 11); -} diff --git a/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c b/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c deleted file mode 100644 index 1f53a9f93b..0000000000 --- a/tests/regression/82-callstring_fundec/07-multiple_calls_ins.c +++ /dev/null @@ -1,57 +0,0 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return f(i - 1); - } - return 1; -} - -int g(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return f(i - 1); - } - return 2; -} - -int h(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return g(i - 1); - } - return 3; -} - -int main(void) -{ - // main -> f(7) -> ... -> f(0) -> return 11 - // [main, f, f, f, f] and [f, f, f, f, f] (4 times) - __goblint_check(f(7) == 11); // UNKNOWN - - // main -> g(20) -> f(19) -> ... -> f(0) -> return 11 - // [main, g, f, f, f] and [g, f, f, f, f] and [f, f, f, f, f] (16 times) - __goblint_check(g(20) == 11); // UNKNOWN - - // main -> h(10) -> g(9) -> f(8) -> ... -> f(1) -> f(0) -> return 11 - // [main, h, g, f, f] and [h, g, f, f, f] and [g, f, f, f, f] and [f, f, f, f, f] (5 times) - __goblint_check(h(10) == 11); // UNKNOWN -} diff --git a/tests/regression/82-callstring_fundec/08-new_calling_set.c b/tests/regression/82-callstring_fundec/08-new_calling_set.c deleted file mode 100644 index 4141cb4724..0000000000 --- a/tests/regression/82-callstring_fundec/08-new_calling_set.c +++ /dev/null @@ -1,36 +0,0 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 0; -} - -int g(int i) -{ - if (i == 2) - { - return f(i - 1) + 1; - } - if (i > 0) - { - return g(i - 1) + 0; - } - return 1; -} - -int main(void) -{ - // main -> g(6) -> ... -> g(2) -> f(1) -> f(0) -> return 1 - // [main, g] and [g, g] (3 times) and [g, f] and [f, f] - __goblint_check(g(5) == 2); -} diff --git a/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c b/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c deleted file mode 100644 index 7c56f9c83d..0000000000 --- a/tests/regression/82-callstring_fundec/09-new_calling_set_ins.c +++ /dev/null @@ -1,36 +0,0 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int f(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 0; -} - -int g(int i) -{ - if (i == 2) - { - return f(i - 1) + 1; - } - if (i > 0) - { - return g(i - 1) + 0; - } - return 1; -} - -int main(void) -{ - // main -> g(6) -> ... -> g(2) -> f(1) -> f(0) -> return 1 - // [main, g] and [g, g] (4 times) and [g, f] and [f, f] - __goblint_check(g(6) == 2); // UNKNOWN -} diff --git a/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c b/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c deleted file mode 100644 index ff0cf37a8a..0000000000 --- a/tests/regression/82-callstring_fundec/10-many_nested_loops_sens.c +++ /dev/null @@ -1,70 +0,0 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int g(int i); - -int c(int i) -{ - if (i == 0) - { - return g(2); - } - else - { - return 4; - } -} - -int b(int i) -{ - return c(i - 1); -} - -int a(int i) -{ - return b(i - 1); -} - -int h(int i) -{ - return g(i - 1); -} - -int f(int i) -{ - if (i <= 0) - { - return h(4); - } - else - { - return f(i - 1); - } -} - -int g(int i) -{ - if (i == 4) - { - return f(3); - } - if (i == 3) - { - return a(2); - } - return b(20); -} - -int m(int i) -{ - return g(i); -} - -int main(void) -{ - // main -> m(4) -> g(4) -> f(3) -> f(2) -> f(1) -> f(0) -> h(4) -> g(3) -> a(2) -> b(1) -> c(0) -> g(2) -> b(20) -> c(19) -> return 4 - // [main, m] and [m, g] an [g, f] and [f, f] (3 times) and - // [f, h] and [h, g] and [g, a] and [a, b] and [b, c] and [c, g] and [g, b] and [b, c] - __goblint_check(m(4) == 4); -} diff --git a/tests/regression/82-callstring_fundec/11-value_update_sens.c b/tests/regression/82-callstring_fundec/11-value_update_sens.c deleted file mode 100644 index 09ddfb0e16..0000000000 --- a/tests/regression/82-callstring_fundec/11-value_update_sens.c +++ /dev/null @@ -1,23 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - // main -> f(10) -> f(9) -> ... f(0) - // [main, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] - f(9); - __goblint_check(a == 0); -} diff --git a/tests/regression/82-callstring_fundec/12-value_update_ins.c b/tests/regression/82-callstring_fundec/12-value_update_ins.c deleted file mode 100644 index 2ac18770f3..0000000000 --- a/tests/regression/82-callstring_fundec/12-value_update_ins.c +++ /dev/null @@ -1,23 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_fundec --enable ana.int.interval_set -// Basic example -#include - -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - // main -> f(10) -> f(9) -> ... f(0) - // [main, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (2 times) - f(10); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c b/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c deleted file mode 100644 index 13cf70be57..0000000000 --- a/tests/regression/83-callstring_Stmt/01-simple_rec_inf_callstack.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.context.inf_callStack --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 15; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); -} diff --git a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c b/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c deleted file mode 100644 index 6a8d06c849..0000000000 --- a/tests/regression/83-callstring_Stmt/02-simple_rec_ins.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 11; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c b/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c deleted file mode 100644 index 19c43b3089..0000000000 --- a/tests/regression/83-callstring_Stmt/03-multiple_rec_sens.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); -} diff --git a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c b/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c deleted file mode 100644 index 28901ead13..0000000000 --- a/tests/regression/83-callstring_Stmt/04-multiple_rec_ins.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 11; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); // UNKNOWN -} diff --git a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c b/tests/regression/83-callstring_Stmt/05-function_chain_sens.c deleted file mode 100644 index d65685cf86..0000000000 --- a/tests/regression/83-callstring_Stmt/05-function_chain_sens.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 12; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); -} diff --git a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c b/tests/regression/83-callstring_Stmt/06-function_chain_ins.c deleted file mode 100644 index c0db02aeb8..0000000000 --- a/tests/regression/83-callstring_Stmt/06-function_chain_ins.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 13; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); // UNKNOWN -} diff --git a/tests/regression/83-callstring_Stmt/07-call_in_call.c b/tests/regression/83-callstring_Stmt/07-call_in_call.c deleted file mode 100644 index 8abd2bd44d..0000000000 --- a/tests/regression/83-callstring_Stmt/07-call_in_call.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Interesting if nested recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 - - __goblint_check(res == 1); -} \ No newline at end of file diff --git a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c b/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c deleted file mode 100644 index 7c958a63d0..0000000000 --- a/tests/regression/83-callstring_Stmt/08-circle_call_and_big_loop.c +++ /dev/null @@ -1,46 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -// Checks proper handling of recursions in loops + shows that not all 200 iterations need to be analyzed -#include - -int num_iterat = 2; - -int f(int i); - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - for (int i = 200; i > 0; i--) - { - int res1 = f(num_iterat); - int res2 = g(num_iterat); - __goblint_check(res1 == 2); - __goblint_check(res2 == 1); - } -} diff --git a/tests/regression/83-callstring_Stmt/09-thread_creation.c b/tests/regression/83-callstring_Stmt/09-thread_creation.c deleted file mode 100644 index a80aab4386..0000000000 --- a/tests/regression/83-callstring_Stmt/09-thread_creation.c +++ /dev/null @@ -1,88 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_stmt --enable ana.int.interval_set -#include -#include -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_sens(void *arg) -{ - int result = procedure(0); - __goblint_check(result == 8); - - result = procedure(8); - __goblint_check(result == 10); - return NULL; -} - -void *t_insens(void *arg) -{ - int result = procedure(9); - __goblint_check(result == 10); // UNKNOWN - - result = procedure(60); - __goblint_check(result == 10); // UNKNOWN - return NULL; -} - -int main() -{ - pthread_t id; - pthread_t id2; - - // Create the thread - pthread_create(&id, NULL, t_sens, NULL); - - // Create the thread - pthread_create(&id2, NULL, t_insens, NULL); - return 0; -} diff --git a/tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c b/tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c deleted file mode 100644 index 02f2bdb78f..0000000000 --- a/tests/regression/84-callstring_Loc/01-simple_rec_inf_callstack.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --enable ana.context.inf_callStack --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 15; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); -} diff --git a/tests/regression/84-callstring_Loc/02-simple_rec_ins.c b/tests/regression/84-callstring_Loc/02-simple_rec_ins.c deleted file mode 100644 index 406ef49f9f..0000000000 --- a/tests/regression/84-callstring_Loc/02-simple_rec_ins.c +++ /dev/null @@ -1,22 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Basic example -#include - -int num_iterat = 11; -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(num_iterat); - __goblint_check(a == 0); // UNKNOWN -} diff --git a/tests/regression/84-callstring_Loc/03-multiple_rec_sens.c b/tests/regression/84-callstring_Loc/03-multiple_rec_sens.c deleted file mode 100644 index ccdfa680a2..0000000000 --- a/tests/regression/84-callstring_Loc/03-multiple_rec_sens.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); -} diff --git a/tests/regression/84-callstring_Loc/04-multiple_rec_ins.c b/tests/regression/84-callstring_Loc/04-multiple_rec_ins.c deleted file mode 100644 index 1c4602474a..0000000000 --- a/tests/regression/84-callstring_Loc/04-multiple_rec_ins.c +++ /dev/null @@ -1,59 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Interesting if multiple recursions are handled properly -#include - -int num_iterat = 11; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - int res5 = h(num_iterat); - - int result = res1 + res2 + res3 + res4 + res5; - __goblint_check(result == 5); // UNKNOWN -} diff --git a/tests/regression/84-callstring_Loc/05-function_chain_sens.c b/tests/regression/84-callstring_Loc/05-function_chain_sens.c deleted file mode 100644 index 60edae4f32..0000000000 --- a/tests/regression/84-callstring_Loc/05-function_chain_sens.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 12; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); -} diff --git a/tests/regression/84-callstring_Loc/06-function_chain_ins.c b/tests/regression/84-callstring_Loc/06-function_chain_ins.c deleted file mode 100644 index 2330ec02e3..0000000000 --- a/tests/regression/84-callstring_Loc/06-function_chain_ins.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Checks if function chains are handled properly -#include - -int num_iterat = 13; - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int main(void) -{ - int result = f(num_iterat); - - __goblint_check(result == 1); // UNKNOWN -} diff --git a/tests/regression/84-callstring_Loc/07-call_in_call.c b/tests/regression/84-callstring_Loc/07-call_in_call.c deleted file mode 100644 index 92cba9752e..0000000000 --- a/tests/regression/84-callstring_Loc/07-call_in_call.c +++ /dev/null @@ -1,54 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -// Interesting if nested recursions are handled properly -#include - -int num_iterat = 10; - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = h(--i); - } - return res; -} - -int main(void) -{ - int res = f(g(h(num_iterat))); // h(4) = 3; g(3) = 2; f(2) = 1 - - __goblint_check(res == 1); -} \ No newline at end of file diff --git a/tests/regression/84-callstring_Loc/09-thread_creation.c b/tests/regression/84-callstring_Loc/09-thread_creation.c deleted file mode 100644 index 1367e19374..0000000000 --- a/tests/regression/84-callstring_Loc/09-thread_creation.c +++ /dev/null @@ -1,88 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" callstring_loc --enable ana.int.interval_set -#include -#include -#include - -int f(int i) -{ - int res = 0; - if (i == 0) - { - res = 1; - } - if (i > 0) - { - res = f(--i); - } - return res; -} - -int g(int i) -{ - int res = 0; - if (i == 0) - { - res = 3; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int h(int i) -{ - int res = 0; - if (i == 0) - { - res = 2; - } - if (i > 0) - { - res = g(--i); - } - return res; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_sens(void *arg) -{ - int result = procedure(0); - __goblint_check(result == 8); - - result = procedure(8); - __goblint_check(result == 10); - return NULL; -} - -void *t_insens(void *arg) -{ - int result = procedure(9); - __goblint_check(result == 10); // UNKNOWN - - result = procedure(60); - __goblint_check(result == 10); // UNKNOWN - return NULL; -} - -int main() -{ - pthread_t id; - pthread_t id2; - - // Create the thread - pthread_create(&id, NULL, t_sens, NULL); - - // Create the thread - pthread_create(&id2, NULL, t_insens, NULL); - return 0; -} From 9853562c879c882fd097d85af62acf83c4c5ed21 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 12 Mar 2024 18:17:35 +0100 Subject: [PATCH 111/128] option to enable/disable is merged with context gas value: negative value means disabled --- src/config/options.schema.json | 14 ++++-------- src/framework/constraints.ml | 4 ++-- src/framework/control.ml | 2 +- .../01-basic_tests_bound_sens.c | 2 +- .../80-context_gas/02-basic_tests_bound_ins.c | 2 +- .../80-context_gas/03-contextGas0.c | 2 +- .../80-context_gas/04-contextGasNeg.c | 4 ++-- .../80-context_gas/05-circle_call_sens.c | 6 +++-- .../80-context_gas/06-circle_call_ins.c | 2 +- .../80-context_gas/07-main_recursion_sens.c | 2 +- .../80-context_gas/08-main_recursion_ins.c | 2 +- .../80-context_gas/09-endless_loop.c | 2 +- .../80-context_gas/10-thread_handling_sens.c | 2 +- .../80-context_gas/11-thread_handling_ins.c | 2 +- .../12-multiple_function_chain_sens.c | 2 +- .../13-multiple_function_chain_ins.c | 2 +- .../regression/80-context_gas/14-ackermann.c | 2 +- .../80-context_gas/15-compl_loop_unrolling.c | 2 +- .../80-context_gas/16-loop_unrolling_sens.c | 2 +- .../80-context_gas/17-loop_unrolling_ins.c | 2 +- .../18-loop_unrolling_big_loop.c | 2 +- .../80-context_gas/19-value_update_sens.c | 22 +++++++++++++++++++ .../80-context_gas/20-value_update_ins.c | 22 +++++++++++++++++++ 23 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 tests/regression/80-context_gas/19-value_update_sens.c create mode 100644 tests/regression/80-context_gas/20-value_update_ins.c diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 05f496aa0e..ddd79b5e00 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -964,17 +964,11 @@ "type": "boolean", "default": false }, - "ctx_gas": { - "title": "ana.context.ctx_gas", - "description": "If enabled, the first x recursions of each path are analyzed context-sensitive, the remaining context-insensitive. x denotes the context gas, which is defined in ana.context.ctx_gas_value.", - "type": "boolean", - "default": false - }, - "ctx_gas_value": { - "title": "ana.context.ctx_gas_value", - "description": "Number of calls that are analyzed context-sensitive. Used for the ContextGasLifter, which is enabled with ana.context.ctx_gas. Must be >= 0!", + "gas_value": { + "title": "ana.context.gas_value", + "description": "x denotes the gas value for the ContextGasLifter. Negative value means deactivated, zero means context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitive, the remaining with empty context.", "type": "integer", - "default": 10 + "default": -1 }, "callStack_height": { "title": "ana.context.callStack_height", diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 44a7044446..0ab2b3fc16 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -534,8 +534,8 @@ struct let cg_val ctx = snd ctx.local let name () = S.name ()^" with context gas" - let startstate v = S.startstate v, get_int "ana.context.ctx_gas_value" - let exitstate v = S.exitstate v, get_int "ana.context.ctx_gas_value" (* TODO: probably doesn't matter*) + let startstate v = S.startstate v, get_int "ana.context.gas_value" + let exitstate v = S.exitstate v, get_int "ana.context.gas_value" (* TODO: probably doesn't matter*) let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = diff --git a/src/framework/control.ml b/src/framework/control.ml index 5019ead12f..7f0c9b8dd6 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -22,7 +22,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val (module MCP.MCP2 : Spec) - |> lift (get_bool "ana.context.ctx_gas") (module ContextGasLifter) + |> lift (get_int "ana.context.gas_value" >= 0) (module ContextGasLifter) |> lift true (module WidenContextLifterSide) (* option checked in functor *) (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) diff --git a/tests/regression/80-context_gas/01-basic_tests_bound_sens.c b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c index dcc48381fb..03f5c78b53 100644 --- a/tests/regression/80-context_gas/01-basic_tests_bound_sens.c +++ b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Basic examples int f(int x, int y) diff --git a/tests/regression/80-context_gas/02-basic_tests_bound_ins.c b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c index 0cfa24f5c1..25b8ec34ad 100644 --- a/tests/regression/80-context_gas/02-basic_tests_bound_ins.c +++ b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Basic examples int f(int x, int y) diff --git a/tests/regression/80-context_gas/03-contextGas0.c b/tests/regression/80-context_gas/03-contextGas0.c index dc445ba371..daf60d2e60 100644 --- a/tests/regression/80-context_gas/03-contextGas0.c +++ b/tests/regression/80-context_gas/03-contextGas0.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 0 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 0 int f(int x, int y) { diff --git a/tests/regression/80-context_gas/04-contextGasNeg.c b/tests/regression/80-context_gas/04-contextGasNeg.c index 30d2d4f9b2..500228eb4c 100644 --- a/tests/regression/80-context_gas/04-contextGasNeg.c +++ b/tests/regression/80-context_gas/04-contextGasNeg.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value -5 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value -5 int f(int x, int y) { @@ -11,5 +11,5 @@ int f(int x, int y) int main() { - __goblint_check(f(5, 5) == 0); // UNKNOWN + __goblint_check(f(20, 20) == 0); // is analyzed fully context sensitive } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-circle_call_sens.c b/tests/regression/80-context_gas/05-circle_call_sens.c index b9a20432a9..4cafc5bff0 100644 --- a/tests/regression/80-context_gas/05-circle_call_sens.c +++ b/tests/regression/80-context_gas/05-circle_call_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 15 // Checks if recursion in loops is handled properly #include @@ -34,7 +34,9 @@ int main(void) { __goblint_check(f(0) == 2); __goblint_check(f(7) == 101); - __goblint_check(f(9) == 265); + // f(9) -> g(7) -> f(8) -> g(6) -> f(7) -> g(5) -> f(6) -> g(4) -> f(5) -> g(3) -> f(4) -> g(2) -> f(3) -> g(1) -> f(2) -> g(0) -> return + // f(9) -> g(6) -> f(7) -> g(4) -> f(5) -> g(2) -> f(3) -> g(0) + __goblint_check(f(9) == 265); __goblint_check(f(10) == 429); __goblint_check(g(0) == 1); diff --git a/tests/regression/80-context_gas/06-circle_call_ins.c b/tests/regression/80-context_gas/06-circle_call_ins.c index feb97c1e2c..f10ca6b6f7 100644 --- a/tests/regression/80-context_gas/06-circle_call_ins.c +++ b/tests/regression/80-context_gas/06-circle_call_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 15 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 15 // Checks if recursion in loops is handled properly #include diff --git a/tests/regression/80-context_gas/07-main_recursion_sens.c b/tests/regression/80-context_gas/07-main_recursion_sens.c index 867522dc52..b538413700 100644 --- a/tests/regression/80-context_gas/07-main_recursion_sens.c +++ b/tests/regression/80-context_gas/07-main_recursion_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Checks if only recursion in main works properly + boundary check // TODO #include diff --git a/tests/regression/80-context_gas/08-main_recursion_ins.c b/tests/regression/80-context_gas/08-main_recursion_ins.c index f28ef0cd95..825e5b0f4a 100644 --- a/tests/regression/80-context_gas/08-main_recursion_ins.c +++ b/tests/regression/80-context_gas/08-main_recursion_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Without context insensitive analysis: Stack Overflow #include diff --git a/tests/regression/80-context_gas/09-endless_loop.c b/tests/regression/80-context_gas/09-endless_loop.c index cb52630e3c..bf6e9052fd 100644 --- a/tests/regression/80-context_gas/09-endless_loop.c +++ b/tests/regression/80-context_gas/09-endless_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Will result in an endless loop without context insensitive analysis #include diff --git a/tests/regression/80-context_gas/10-thread_handling_sens.c b/tests/regression/80-context_gas/10-thread_handling_sens.c index 11db96e100..533d27c0a1 100644 --- a/tests/regression/80-context_gas/10-thread_handling_sens.c +++ b/tests/regression/80-context_gas/10-thread_handling_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 #include #include diff --git a/tests/regression/80-context_gas/11-thread_handling_ins.c b/tests/regression/80-context_gas/11-thread_handling_ins.c index bd3ea86f80..157fb282f4 100644 --- a/tests/regression/80-context_gas/11-thread_handling_ins.c +++ b/tests/regression/80-context_gas/11-thread_handling_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 #include #include diff --git a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c index 89c0d708f5..106f5b73a2 100644 --- a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c +++ b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.context.ctx_gas --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Tests multiple recursive function calls #include diff --git a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c index 321df17938..65896f1b06 100644 --- a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c +++ b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.int.interval_set --enable ana.context.ctx_gas --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // Tests multiple recursive function calls #include diff --git a/tests/regression/80-context_gas/14-ackermann.c b/tests/regression/80-context_gas/14-ackermann.c index 4b5579f03b..6c725d54fa 100644 --- a/tests/regression/80-context_gas/14-ackermann.c +++ b/tests/regression/80-context_gas/14-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 // This code would result in a StackOverflow if it is analyses fully context sensitive #include diff --git a/tests/regression/80-context_gas/15-compl_loop_unrolling.c b/tests/regression/80-context_gas/15-compl_loop_unrolling.c index bab565688c..a28b9dcf26 100644 --- a/tests/regression/80-context_gas/15-compl_loop_unrolling.c +++ b/tests/regression/80-context_gas/15-compl_loop_unrolling.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 // TODO #include diff --git a/tests/regression/80-context_gas/16-loop_unrolling_sens.c b/tests/regression/80-context_gas/16-loop_unrolling_sens.c index 4c647bff7b..93a4d01409 100644 --- a/tests/regression/80-context_gas/16-loop_unrolling_sens.c +++ b/tests/regression/80-context_gas/16-loop_unrolling_sens.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 // TODO #include diff --git a/tests/regression/80-context_gas/17-loop_unrolling_ins.c b/tests/regression/80-context_gas/17-loop_unrolling_ins.c index ceab5a870f..5c702f43f7 100644 --- a/tests/regression/80-context_gas/17-loop_unrolling_ins.c +++ b/tests/regression/80-context_gas/17-loop_unrolling_ins.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 // TODO #include diff --git a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c index d8c5e2a013..1d95444a71 100644 --- a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c +++ b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --enable ana.context.ctx_gas --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.ctx_gas_value 10 +// PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 // TODO #include diff --git a/tests/regression/80-context_gas/19-value_update_sens.c b/tests/regression/80-context_gas/19-value_update_sens.c new file mode 100644 index 0000000000..bddedb9737 --- /dev/null +++ b/tests/regression/80-context_gas/19-value_update_sens.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 +// Basic example +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + // main -> f(8) -> f(7) -> ... f(0) + f(8); + __goblint_check(a == 0); +} diff --git a/tests/regression/80-context_gas/20-value_update_ins.c b/tests/regression/80-context_gas/20-value_update_ins.c new file mode 100644 index 0000000000..5435b0ea71 --- /dev/null +++ b/tests/regression/80-context_gas/20-value_update_ins.c @@ -0,0 +1,22 @@ +// PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 +// Basic example +#include + +int a = 20; + +int f(int i) +{ + if (i > 0) + { + a = --i; + f(i); + } + return 0; +} + +int main(void) +{ + // main -> f(9) -> f(8) -> ... f(0) + f(9); + __goblint_check(a == 0); //UNKNOWN +} From 08e1c7329e97a42e21e09ba709202b597e8adce3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 12 Mar 2024 18:25:24 +0100 Subject: [PATCH 112/128] updated comment of analysis in callstring; updated configs for sv comp --- ...-loc_inf.json => callstring-callsite.json} | 6 +- ...mt_inf.json => callstring-callstring.json} | 6 +- ...json => callstring-callstringWCallee.json} | 5 +- conf/callstring-fundec.json | 146 ------------------ ...ndec_inf.json => callstring-site_inf.json} | 6 +- conf/callstring-stmt.json | 146 ------------------ conf/callstring-stringWCallee_inf.json | 145 +++++++++++++++++ conf/callstring-string_inf.json | 145 +++++++++++++++++ conf/context-gas-10.json | 3 +- conf/context-gas-20.json | 3 +- conf/context-gas-30.json | 3 +- src/analyses/callstring.ml | 4 +- 12 files changed, 306 insertions(+), 312 deletions(-) rename conf/{callstring-loc_inf.json => callstring-callsite.json} (97%) rename conf/{callstring-stmt_inf.json => callstring-callstring.json} (97%) rename conf/{callstring-loc.json => callstring-callstringWCallee.json} (97%) delete mode 100644 conf/callstring-fundec.json rename conf/{callstring-fundec_inf.json => callstring-site_inf.json} (97%) delete mode 100644 conf/callstring-stmt.json create mode 100644 conf/callstring-stringWCallee_inf.json create mode 100644 conf/callstring-string_inf.json diff --git a/conf/callstring-loc_inf.json b/conf/callstring-callsite.json similarity index 97% rename from conf/callstring-loc_inf.json rename to conf/callstring-callsite.json index 3e93d72565..c32a59c3a7 100644 --- a/conf/callstring-loc_inf.json +++ b/conf/callstring-callsite.json @@ -32,7 +32,7 @@ "thread", "threadJoins", "taintPartialContexts", - "callstring_loc" + "call_site" ], "path_sens": [ "mutex", @@ -45,8 +45,8 @@ ], "context": { "widen": false, - "ctx_gas": false, - "inf_callStack": true + "gas_value": -1, + "callStack_height": 2 }, "malloc": { "wrappers": [ diff --git a/conf/callstring-stmt_inf.json b/conf/callstring-callstring.json similarity index 97% rename from conf/callstring-stmt_inf.json rename to conf/callstring-callstring.json index b973769b48..8b3d620adc 100644 --- a/conf/callstring-stmt_inf.json +++ b/conf/callstring-callstring.json @@ -32,7 +32,7 @@ "thread", "threadJoins", "taintPartialContexts", - "callstring_stmt" + "call_string" ], "path_sens": [ "mutex", @@ -45,8 +45,8 @@ ], "context": { "widen": false, - "ctx_gas": false, - "inf_callStack": true + "gas_value": -1, + "callStack_height": 2 }, "malloc": { "wrappers": [ diff --git a/conf/callstring-loc.json b/conf/callstring-callstringWCallee.json similarity index 97% rename from conf/callstring-loc.json rename to conf/callstring-callstringWCallee.json index d13f75279a..165f3e9f3e 100644 --- a/conf/callstring-loc.json +++ b/conf/callstring-callstringWCallee.json @@ -32,7 +32,7 @@ "thread", "threadJoins", "taintPartialContexts", - "callstring_loc" + "call_string_withCallee" ], "path_sens": [ "mutex", @@ -45,8 +45,7 @@ ], "context": { "widen": false, - "ctx_gas": false, - "inf_callStack": false, + "gas_value": -1, "callStack_height": 2 }, "malloc": { diff --git a/conf/callstring-fundec.json b/conf/callstring-fundec.json deleted file mode 100644 index 538bd024af..0000000000 --- a/conf/callstring-fundec.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "callstring_fundec" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "ctx_gas": false, - "inf_callStack": false, - "callStack_height": 2 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": false, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/callstring-fundec_inf.json b/conf/callstring-site_inf.json similarity index 97% rename from conf/callstring-fundec_inf.json rename to conf/callstring-site_inf.json index 0ec3454015..174cb381e3 100644 --- a/conf/callstring-fundec_inf.json +++ b/conf/callstring-site_inf.json @@ -32,7 +32,7 @@ "thread", "threadJoins", "taintPartialContexts", - "callstring_fundec" + "call_site" ], "path_sens": [ "mutex", @@ -45,8 +45,8 @@ ], "context": { "widen": false, - "ctx_gas": false, - "inf_callStack": true + "gas_value": -1, + "callStack_height": -1 }, "malloc": { "wrappers": [ diff --git a/conf/callstring-stmt.json b/conf/callstring-stmt.json deleted file mode 100644 index 32be34387a..0000000000 --- a/conf/callstring-stmt.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "callstring_stmt" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "ctx_gas": false, - "inf_callStack": false, - "callStack_height": 2 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": false, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/callstring-stringWCallee_inf.json b/conf/callstring-stringWCallee_inf.json new file mode 100644 index 0000000000..47e9abc300 --- /dev/null +++ b/conf/callstring-stringWCallee_inf.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "call_string_withCallee" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": -1, + "callStack_height": -1 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-string_inf.json b/conf/callstring-string_inf.json new file mode 100644 index 0000000000..1ddfd66e93 --- /dev/null +++ b/conf/callstring-string_inf.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "call_string" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": -1, + "callStack_height": -1 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/context-gas-10.json b/conf/context-gas-10.json index 1075c82405..1ed44eea90 100644 --- a/conf/context-gas-10.json +++ b/conf/context-gas-10.json @@ -44,8 +44,7 @@ ], "context": { "widen": false, - "ctx_gas": true, - "ctx_gas_value": 10 + "gas_value": 10 }, "malloc": { "wrappers": [ diff --git a/conf/context-gas-20.json b/conf/context-gas-20.json index bb11f0f16f..25238d3cbd 100644 --- a/conf/context-gas-20.json +++ b/conf/context-gas-20.json @@ -44,8 +44,7 @@ ], "context": { "widen": false, - "ctx_gas": true, - "ctx_gas_value": 20 + "gas_value": 20 }, "malloc": { "wrappers": [ diff --git a/conf/context-gas-30.json b/conf/context-gas-30.json index 64403ccf03..dbbea92e36 100644 --- a/conf/context-gas-30.json +++ b/conf/context-gas-30.json @@ -44,8 +44,7 @@ ], "context": { "widen": false, - "ctx_gas": true, - "ctx_gas_value": 30 + "gas_value": 30 }, "malloc": { "wrappers": [ diff --git a/src/analyses/callstring.ml b/src/analyses/callstring.ml index 8ae938dd25..773ea882f9 100644 --- a/src/analyses/callstring.ml +++ b/src/analyses/callstring.ml @@ -88,10 +88,10 @@ end (* Lifters for the call string approach with different call stack element types *) let _ = (* call string approach *) - MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string_og] *) + MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string] *) (* call string approach: additionally tracks the callee function in the call stack *) - MCP.register_analysis (module Spec (Callstring_Callee) : MCPSpec); (* [call_string_incl_callee] *) + MCP.register_analysis (module Spec (Callstring_Callee) : MCPSpec); (* [call_string_withCallee] *) (* call site approach *) MCP.register_analysis (module Spec (Callsite) : MCPSpec); (* [call_site] *) \ No newline at end of file From 73f5a166b8e77fb6086dfb85202e3584812c26e3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 12 Mar 2024 22:47:49 +0100 Subject: [PATCH 113/128] add marshal to context gas lifter --- src/framework/constraints.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0ab2b3fc16..61c087f8de 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -533,6 +533,10 @@ struct (* returns context gas value of the given ctx *) let cg_val ctx = snd ctx.local + type marshal = S.marshal + let init = S.init + let finalize = S.finalize + let name () = S.name ()^" with context gas" let startstate v = S.startstate v, get_int "ana.context.gas_value" let exitstate v = S.exitstate v, get_int "ana.context.gas_value" (* TODO: probably doesn't matter*) From 1649dca59a9b31a3f9ac59ed59489e2396fce932 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 13 Mar 2024 16:20:53 +0100 Subject: [PATCH 114/128] add ana.ctx_sens option --- src/analyses/mCP.ml | 37 ++++++++----------- src/config/options.schema.json | 9 ++++- .../01-loop_calling_sens.c | 2 +- .../02-loop_calling_ins.c | 2 +- .../81-loopfree_callstring/03-ackermann.c | 2 +- .../81-loopfree_callstring/04-endless_loop.c | 2 +- .../05-multiple_calls_base_sens.c | 2 +- .../06-multiple_calls_sens.c | 2 +- .../07-multiple_calls_ins.c | 2 +- .../08-new_calling_set.c | 2 +- .../09-many_nested_loops.c | 2 +- .../81-loopfree_callstring/10-nested_loops.c | 2 +- .../11-value_update_sens.c | 2 +- .../12-value_update_ins.c | 2 +- .../13-circle_call_and_big_loop.c | 2 +- .../14-loop_unrolling.c | 2 +- .../81-loopfree_callstring/15-threads_sens.c | 2 +- .../81-loopfree_callstring/16-threads_ins.c | 2 +- .../01-multiple_tests_h5sens_cs.c | 2 +- .../02-multiple_tests_h5ins_cs.c | 2 +- .../03-multiple_tests_h2sens_cs.c | 2 +- .../82-callstring/04-endless_loop_cs.c | 2 +- .../82-callstring/05-ackermann_cs.c | 2 +- .../regression/82-callstring/06-big_loop_cs.c | 2 +- .../82-callstring/07-loop_unrolling_cs.c | 2 +- .../82-callstring/08-threads_sens_cs.c | 2 +- .../82-callstring/09-threads_ins_cs.c | 2 +- .../82-callstring/10-inf_callstack_cs.c | 2 +- .../11-multiple_tests_h5sens_csi.c | 2 +- .../12-multiple_tests_h5ins_csi.c | 2 +- .../13-multiple_tests_h2sens_csi.c | 2 +- .../82-callstring/14-endless_loop_csi.c | 2 +- .../82-callstring/15-ackermann_csi.c | 2 +- .../82-callstring/16-big_loop_csi.c | 2 +- .../82-callstring/17-loop_unrolling_csi.c | 2 +- .../82-callstring/18-threads_sens_csi.c | 2 +- .../82-callstring/19-threads_ins_csi.c | 2 +- .../82-callstring/20-inf_callstack_csi.c | 2 +- .../21-multiple_tests_h5sens_csWCallee.c | 2 +- .../22-multiple_tests_h5ins_csWCallee.c | 2 +- .../23-multiple_tests_h2sens_csWCallee.c | 2 +- .../82-callstring/24-endless_loop_csWCallee.c | 2 +- .../82-callstring/25-ackermann_csWCallee.c | 2 +- .../82-callstring/26-big_loop_csWCallee.c | 2 +- .../27-loop_unrolling_csWCallee.c | 2 +- .../82-callstring/28-threads_sens_csWCallee.c | 2 +- .../82-callstring/29-threads_ins_csWCallee.c | 2 +- .../30-inf_callstack_csWCallee.c | 2 +- 48 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 2503ca9037..8b06b39fe6 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -36,6 +36,7 @@ struct let name () = "MCP2" let path_sens = ref [] + let cont_sens = ref [] let cont_inse = ref [] let base_id = ref (-1) @@ -65,13 +66,6 @@ struct let deps (x,_) = iter (check_dep x) @@ (find_spec x).dep in iter deps xs - let specific_cont_sens xs = - (* most analysis must be set to context-insensitive, because we only want to analyse context-sensitive for one specific analysis *) - let sens_ana = ["call_string_withCallee"; "call_string"; "call_site"; "loopfree_callstring"] in - let enabled = List.fold_left (fun acc x -> acc || (mem x xs)) false sens_ana in - (* returns the edited list of insensitive analyses if enabled *) - if enabled then Some(filter (fun x -> not (mem x sens_ana)) xs) else None - type marshal = Obj.t list let init marshal = let map' f = @@ -82,20 +76,21 @@ struct List.map f in let xs = get_string_list "ana.activated" in - let special_inse = specific_cont_sens xs in let xs = map' find_id xs in base_id := find_id "base"; activated := map (fun s -> s, find_spec s) xs; path_sens := map' find_id @@ get_string_list "ana.path_sens"; - (* checks if an analysis is enabled which requires special handling of context-sensitivity *) - begin - match special_inse with - | Some ins -> cont_inse := map' find_id ins; - | None -> cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; - end; check_deps !activated; activated := topo_sort_an !activated; - activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; + begin + match get_string_list "ana.ctx_sens" with + | [] -> (* use values of "ana.ctx_insens" (blacklist) *) + cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; + activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; + | sens -> (* use values of "ana.ctx_sens" (whitelist) *) + cont_sens := map' find_id @@ sens; + activated_ctx_sens := List.filter (fun (n, _) -> List.mem n !cont_sens) !activated; + end; activated_path_sens := List.filter (fun (n, _) -> List.mem n !path_sens) !activated; match marshal with | Some marshal -> @@ -120,7 +115,7 @@ struct let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> - if mem n !cont_inse then + if (mem n !cont_inse) || not @@ (List.is_empty !cont_sens || mem n !cont_sens) then (* TODO: do I need to check if it is contained in activated ana?*) None else Some (n, repr @@ S.context fd (obj d)) @@ -192,13 +187,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/config/options.schema.json b/src/config/options.schema.json index ddd79b5e00..f3fb8dac3d 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -356,11 +356,18 @@ }, "ctx_insens": { "title": "ana.ctx_insens", - "description": "List of context-insensitive analyses", + "description": "List of context-insensitive analyses, which is ignored if `ctx_sens` is not empty.", "type": "array", "items": { "type": "string" }, "default": [ "stack_loc", "stack_trace_set" ] }, + "ctx_sens": { + "title": "ana.ctx_sens", + "description": "List of context-sensitive analyses. In case of an empty array `ctx_insens` is used, otherwise `ctx_insens` is ignored.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, "setjmp" : { "title": "ana.setjmp", "description": "Setjmp/Longjmp analysis", diff --git a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c index 2d04ecfdbb..2b88d06c6d 100644 --- a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c +++ b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set int f(int i); diff --git a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c index 96d92b346a..96fb2fcc31 100644 --- a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c +++ b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/03-ackermann.c b/tests/regression/81-loopfree_callstring/03-ackermann.c index c91428e362..52a55ae673 100644 --- a/tests/regression/81-loopfree_callstring/03-ackermann.c +++ b/tests/regression/81-loopfree_callstring/03-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int ack(int n, int m) diff --git a/tests/regression/81-loopfree_callstring/04-endless_loop.c b/tests/regression/81-loopfree_callstring/04-endless_loop.c index ecb521038c..940d0d3a82 100644 --- a/tests/regression/81-loopfree_callstring/04-endless_loop.c +++ b/tests/regression/81-loopfree_callstring/04-endless_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis #include diff --git a/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c index 68d57d56d9..a21df3d2b9 100644 --- a/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c +++ b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c index a387420768..3caa345108 100644 --- a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c +++ b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c index 0b8ce92acb..0650f78418 100644 --- a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c +++ b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/08-new_calling_set.c b/tests/regression/81-loopfree_callstring/08-new_calling_set.c index 04258ff47a..bcb74d9799 100644 --- a/tests/regression/81-loopfree_callstring/08-new_calling_set.c +++ b/tests/regression/81-loopfree_callstring/08-new_calling_set.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c index 6b3e977823..9db0786268 100644 --- a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c +++ b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/10-nested_loops.c b/tests/regression/81-loopfree_callstring/10-nested_loops.c index 6ed6924412..7f7ef43dd4 100644 --- a/tests/regression/81-loopfree_callstring/10-nested_loops.c +++ b/tests/regression/81-loopfree_callstring/10-nested_loops.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/11-value_update_sens.c b/tests/regression/81-loopfree_callstring/11-value_update_sens.c index 40146948b9..c926a5c5a9 100644 --- a/tests/regression/81-loopfree_callstring/11-value_update_sens.c +++ b/tests/regression/81-loopfree_callstring/11-value_update_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/12-value_update_ins.c b/tests/regression/81-loopfree_callstring/12-value_update_ins.c index 35e956c103..fe5fd7ff2c 100644 --- a/tests/regression/81-loopfree_callstring/12-value_update_ins.c +++ b/tests/regression/81-loopfree_callstring/12-value_update_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c index c8624782bd..9da8f652da 100644 --- a/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c +++ b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include diff --git a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c index 87d3e4d991..d422672f88 100644 --- a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c +++ b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set --set exp.unrolling-factor 3 +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set --set exp.unrolling-factor 3 #include diff --git a/tests/regression/81-loopfree_callstring/15-threads_sens.c b/tests/regression/81-loopfree_callstring/15-threads_sens.c index 20697b1138..66e7453125 100644 --- a/tests/regression/81-loopfree_callstring/15-threads_sens.c +++ b/tests/regression/81-loopfree_callstring/15-threads_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/81-loopfree_callstring/16-threads_ins.c b/tests/regression/81-loopfree_callstring/16-threads_ins.c index 7b7fb69a92..1593b6571e 100644 --- a/tests/regression/81-loopfree_callstring/16-threads_ins.c +++ b/tests/regression/81-loopfree_callstring/16-threads_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c index 75bad75496..c5eb7d09b3 100644 --- a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c +++ b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c index 5ca535585e..19fd172e35 100644 --- a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c +++ b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c index 65f17dc7e2..4e21efa010 100644 --- a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c +++ b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/04-endless_loop_cs.c b/tests/regression/82-callstring/04-endless_loop_cs.c index 5b799bfe8a..9e0326b318 100644 --- a/tests/regression/82-callstring/04-endless_loop_cs.c +++ b/tests/regression/82-callstring/04-endless_loop_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis int num_iterat = 2; diff --git a/tests/regression/82-callstring/05-ackermann_cs.c b/tests/regression/82-callstring/05-ackermann_cs.c index dbbd059e46..aedfdef552 100644 --- a/tests/regression/82-callstring/05-ackermann_cs.c +++ b/tests/regression/82-callstring/05-ackermann_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/06-big_loop_cs.c b/tests/regression/82-callstring/06-big_loop_cs.c index b40dc10dee..d03507b16f 100644 --- a/tests/regression/82-callstring/06-big_loop_cs.c +++ b/tests/regression/82-callstring/06-big_loop_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/07-loop_unrolling_cs.c b/tests/regression/82-callstring/07-loop_unrolling_cs.c index 496f3ed6ba..dc58208687 100644 --- a/tests/regression/82-callstring/07-loop_unrolling_cs.c +++ b/tests/regression/82-callstring/07-loop_unrolling_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/08-threads_sens_cs.c b/tests/regression/82-callstring/08-threads_sens_cs.c index 3ed9f46b36..bf5caceeee 100644 --- a/tests/regression/82-callstring/08-threads_sens_cs.c +++ b/tests/regression/82-callstring/08-threads_sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/09-threads_ins_cs.c b/tests/regression/82-callstring/09-threads_ins_cs.c index e4b68938d5..0b1bbd2a3c 100644 --- a/tests/regression/82-callstring/09-threads_ins_cs.c +++ b/tests/regression/82-callstring/09-threads_ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/10-inf_callstack_cs.c b/tests/regression/82-callstring/10-inf_callstack_cs.c index 67ccf2e56c..add6427935 100644 --- a/tests/regression/82-callstring/10-inf_callstack_cs.c +++ b/tests/regression/82-callstring/10-inf_callstack_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_string --enable ana.int.interval_set --set ana.context.callStack_height -1 +// PARAM: --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set ana.context.callStack_height -1 #include diff --git a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c index 2b953e13cc..4a914ea482 100644 --- a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c +++ b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c index 56f13c36d9..53e318b172 100644 --- a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c +++ b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c index e65606916f..c32a044808 100644 --- a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c +++ b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/14-endless_loop_csi.c b/tests/regression/82-callstring/14-endless_loop_csi.c index b6818b3512..88372f963e 100644 --- a/tests/regression/82-callstring/14-endless_loop_csi.c +++ b/tests/regression/82-callstring/14-endless_loop_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis int num_iterat = 2; diff --git a/tests/regression/82-callstring/15-ackermann_csi.c b/tests/regression/82-callstring/15-ackermann_csi.c index 0167f8a5f5..16f06c0360 100644 --- a/tests/regression/82-callstring/15-ackermann_csi.c +++ b/tests/regression/82-callstring/15-ackermann_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/16-big_loop_csi.c b/tests/regression/82-callstring/16-big_loop_csi.c index e2deb86fb2..7afe068a30 100644 --- a/tests/regression/82-callstring/16-big_loop_csi.c +++ b/tests/regression/82-callstring/16-big_loop_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/17-loop_unrolling_csi.c b/tests/regression/82-callstring/17-loop_unrolling_csi.c index 3e53897862..33b66d5995 100644 --- a/tests/regression/82-callstring/17-loop_unrolling_csi.c +++ b/tests/regression/82-callstring/17-loop_unrolling_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/18-threads_sens_csi.c b/tests/regression/82-callstring/18-threads_sens_csi.c index adacbcb59b..6b3713d20b 100644 --- a/tests/regression/82-callstring/18-threads_sens_csi.c +++ b/tests/regression/82-callstring/18-threads_sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/19-threads_ins_csi.c b/tests/regression/82-callstring/19-threads_ins_csi.c index c94e704b72..e73af0b3b9 100644 --- a/tests/regression/82-callstring/19-threads_ins_csi.c +++ b/tests/regression/82-callstring/19-threads_ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/20-inf_callstack_csi.c b/tests/regression/82-callstring/20-inf_callstack_csi.c index f1c0daa72f..2bffbc393a 100644 --- a/tests/regression/82-callstring/20-inf_callstack_csi.c +++ b/tests/regression/82-callstring/20-inf_callstack_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_site --enable ana.int.interval_set --set ana.context.callStack_height -1 +// PARAM: --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set ana.context.callStack_height -1 #include diff --git a/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c b/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c index d52cfc2fbc..8e36b9094e 100644 --- a/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c +++ b/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c b/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c index 74e2673d2f..b7c2782bc3 100644 --- a/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c +++ b/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c b/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c index 26bc0fcb7f..1337d107b5 100644 --- a/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c +++ b/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/24-endless_loop_csWCallee.c b/tests/regression/82-callstring/24-endless_loop_csWCallee.c index 1ec78577ce..d50cf0e8af 100644 --- a/tests/regression/82-callstring/24-endless_loop_csWCallee.c +++ b/tests/regression/82-callstring/24-endless_loop_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis int num_iterat = 2; diff --git a/tests/regression/82-callstring/25-ackermann_csWCallee.c b/tests/regression/82-callstring/25-ackermann_csWCallee.c index 6db58caf12..7655a019d2 100644 --- a/tests/regression/82-callstring/25-ackermann_csWCallee.c +++ b/tests/regression/82-callstring/25-ackermann_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/26-big_loop_csWCallee.c b/tests/regression/82-callstring/26-big_loop_csWCallee.c index 6b43259b62..fc2b6f03ea 100644 --- a/tests/regression/82-callstring/26-big_loop_csWCallee.c +++ b/tests/regression/82-callstring/26-big_loop_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c b/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c index 5ac8ddcd89..06b98e533a 100644 --- a/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c +++ b/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/28-threads_sens_csWCallee.c b/tests/regression/82-callstring/28-threads_sens_csWCallee.c index 70927d29b1..b0f21f0b08 100644 --- a/tests/regression/82-callstring/28-threads_sens_csWCallee.c +++ b/tests/regression/82-callstring/28-threads_sens_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/29-threads_ins_csWCallee.c b/tests/regression/82-callstring/29-threads_ins_csWCallee.c index 3c929f4398..c18df22d9c 100644 --- a/tests/regression/82-callstring/29-threads_ins_csWCallee.c +++ b/tests/regression/82-callstring/29-threads_ins_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set +// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/30-inf_callstack_csWCallee.c b/tests/regression/82-callstring/30-inf_callstack_csWCallee.c index c6e5e6e61f..da14add437 100644 --- a/tests/regression/82-callstring/30-inf_callstack_csWCallee.c +++ b/tests/regression/82-callstring/30-inf_callstack_csWCallee.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_string_withCallee --enable ana.int.interval_set --set ana.context.callStack_height -1 +// PARAM: --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set --set ana.context.callStack_height -1 #include From 1eb23c02ce649f9790fbfb06590f92bcd360b34d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 13 Mar 2024 16:57:00 +0100 Subject: [PATCH 115/128] update comment of contextGasLifter --- src/config/options.schema.json | 2 +- src/framework/constraints.ml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index f3fb8dac3d..910028d814 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -973,7 +973,7 @@ }, "gas_value": { "title": "ana.context.gas_value", - "description": "x denotes the gas value for the ContextGasLifter. Negative value means deactivated, zero means context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitive, the remaining with empty context.", + "description": "x denotes the gas value for the ContextGasLifter. Negative value means deactivated, zero means context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitive, the remaining with no context.", "type": "integer", "default": -1 }, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 61c087f8de..b89b1ac988 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -505,7 +505,7 @@ struct end (** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. - If the context gas is 0, the remaining function calls are analyzed context insensitively (before the analysis is context sensitive) *) + If the gas is 0, the remaining function calls are analyzed without context-information *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) and module C = Printable.Option (S.C) (NoContext) @@ -530,7 +530,7 @@ struct let of_elt (x, _) = of_elt x end - (* returns context gas value of the given ctx *) + (* returns value of the given ctx *) let cg_val ctx = snd ctx.local type marshal = S.marshal From 3b9889c4e4a18f54ac540ba12af47ac93c3f460f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 13 Mar 2024 17:29:09 +0100 Subject: [PATCH 116/128] new config file for master thesis -> moved all thesis related configs to folder --- .../callstring-callsite_h2.json} | 0 conf/masterthesis/callstring-callsite_h5.json | 145 ++++++++++++++++++ .../callstring-callstringWCallee_h2.json} | 0 .../callstring-callstringWCallee_h5.json | 145 ++++++++++++++++++ .../callstring-callstring_h2.json} | 0 .../callstring-callstring_h5.json | 145 ++++++++++++++++++ .../callstring-site_inf.json | 0 .../callstring-stringWCallee_inf.json | 0 .../callstring-string_inf.json | 0 conf/{ => masterthesis}/context-gas-10.json | 0 conf/{ => masterthesis}/context-gas-20.json | 0 conf/{ => masterthesis}/context-gas-30.json | 0 conf/masterthesis/context-gas-40.json | 143 +++++++++++++++++ conf/{ => masterthesis}/context-paper-24.json | 1 + conf/{ => masterthesis}/context-widening.json | 1 + .../loopfree-callstring.json | 1 + 16 files changed, 581 insertions(+) rename conf/{callstring-callsite.json => masterthesis/callstring-callsite_h2.json} (100%) create mode 100644 conf/masterthesis/callstring-callsite_h5.json rename conf/{callstring-callstringWCallee.json => masterthesis/callstring-callstringWCallee_h2.json} (100%) create mode 100644 conf/masterthesis/callstring-callstringWCallee_h5.json rename conf/{callstring-callstring.json => masterthesis/callstring-callstring_h2.json} (100%) create mode 100644 conf/masterthesis/callstring-callstring_h5.json rename conf/{ => masterthesis}/callstring-site_inf.json (100%) rename conf/{ => masterthesis}/callstring-stringWCallee_inf.json (100%) rename conf/{ => masterthesis}/callstring-string_inf.json (100%) rename conf/{ => masterthesis}/context-gas-10.json (100%) rename conf/{ => masterthesis}/context-gas-20.json (100%) rename conf/{ => masterthesis}/context-gas-30.json (100%) create mode 100644 conf/masterthesis/context-gas-40.json rename conf/{ => masterthesis}/context-paper-24.json (99%) rename conf/{ => masterthesis}/context-widening.json (99%) rename conf/{ => masterthesis}/loopfree-callstring.json (99%) diff --git a/conf/callstring-callsite.json b/conf/masterthesis/callstring-callsite_h2.json similarity index 100% rename from conf/callstring-callsite.json rename to conf/masterthesis/callstring-callsite_h2.json diff --git a/conf/masterthesis/callstring-callsite_h5.json b/conf/masterthesis/callstring-callsite_h5.json new file mode 100644 index 0000000000..0b5b396550 --- /dev/null +++ b/conf/masterthesis/callstring-callsite_h5.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "call_site" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": -1, + "callStack_height": 5 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-callstringWCallee.json b/conf/masterthesis/callstring-callstringWCallee_h2.json similarity index 100% rename from conf/callstring-callstringWCallee.json rename to conf/masterthesis/callstring-callstringWCallee_h2.json diff --git a/conf/masterthesis/callstring-callstringWCallee_h5.json b/conf/masterthesis/callstring-callstringWCallee_h5.json new file mode 100644 index 0000000000..d43bfdecf3 --- /dev/null +++ b/conf/masterthesis/callstring-callstringWCallee_h5.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "call_string_withCallee" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": -1, + "callStack_height": 5 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-callstring.json b/conf/masterthesis/callstring-callstring_h2.json similarity index 100% rename from conf/callstring-callstring.json rename to conf/masterthesis/callstring-callstring_h2.json diff --git a/conf/masterthesis/callstring-callstring_h5.json b/conf/masterthesis/callstring-callstring_h5.json new file mode 100644 index 0000000000..282f7b1886 --- /dev/null +++ b/conf/masterthesis/callstring-callstring_h5.json @@ -0,0 +1,145 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts", + "call_string" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": -1, + "callStack_height": 5 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/callstring-site_inf.json b/conf/masterthesis/callstring-site_inf.json similarity index 100% rename from conf/callstring-site_inf.json rename to conf/masterthesis/callstring-site_inf.json diff --git a/conf/callstring-stringWCallee_inf.json b/conf/masterthesis/callstring-stringWCallee_inf.json similarity index 100% rename from conf/callstring-stringWCallee_inf.json rename to conf/masterthesis/callstring-stringWCallee_inf.json diff --git a/conf/callstring-string_inf.json b/conf/masterthesis/callstring-string_inf.json similarity index 100% rename from conf/callstring-string_inf.json rename to conf/masterthesis/callstring-string_inf.json diff --git a/conf/context-gas-10.json b/conf/masterthesis/context-gas-10.json similarity index 100% rename from conf/context-gas-10.json rename to conf/masterthesis/context-gas-10.json diff --git a/conf/context-gas-20.json b/conf/masterthesis/context-gas-20.json similarity index 100% rename from conf/context-gas-20.json rename to conf/masterthesis/context-gas-20.json diff --git a/conf/context-gas-30.json b/conf/masterthesis/context-gas-30.json similarity index 100% rename from conf/context-gas-30.json rename to conf/masterthesis/context-gas-30.json diff --git a/conf/masterthesis/context-gas-40.json b/conf/masterthesis/context-gas-40.json new file mode 100644 index 0000000000..74e420d09e --- /dev/null +++ b/conf/masterthesis/context-gas-40.json @@ -0,0 +1,143 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": 40 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": false, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/conf/context-paper-24.json b/conf/masterthesis/context-paper-24.json similarity index 99% rename from conf/context-paper-24.json rename to conf/masterthesis/context-paper-24.json index ed688c94b9..730de29493 100644 --- a/conf/context-paper-24.json +++ b/conf/masterthesis/context-paper-24.json @@ -43,6 +43,7 @@ "threadflag" ], "context": { + "gas_value": -1, "widen": false }, "malloc": { diff --git a/conf/context-widening.json b/conf/masterthesis/context-widening.json similarity index 99% rename from conf/context-widening.json rename to conf/masterthesis/context-widening.json index 53cd575401..823683137e 100644 --- a/conf/context-widening.json +++ b/conf/masterthesis/context-widening.json @@ -43,6 +43,7 @@ "threadflag" ], "context": { + "gas_value": -1, "widen": true }, "malloc": { diff --git a/conf/loopfree-callstring.json b/conf/masterthesis/loopfree-callstring.json similarity index 99% rename from conf/loopfree-callstring.json rename to conf/masterthesis/loopfree-callstring.json index 211789d9b6..96f4a07e86 100644 --- a/conf/loopfree-callstring.json +++ b/conf/masterthesis/loopfree-callstring.json @@ -44,6 +44,7 @@ "threadflag" ], "context": { + "gas_value": -1, "widen": false }, "malloc": { From 14a8fe972d185123597f2c2bb6995d5d32cc7a32 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 15 Mar 2024 16:11:43 +0100 Subject: [PATCH 117/128] enabled octagon autotuning and yaml for masterthesis configs --- conf/masterthesis/callstring-callsite_h2.json | 3 ++- conf/masterthesis/callstring-callsite_h5.json | 3 ++- conf/masterthesis/callstring-callstringWCallee_h2.json | 3 ++- conf/masterthesis/callstring-callstringWCallee_h5.json | 3 ++- conf/masterthesis/callstring-callstring_h2.json | 3 ++- conf/masterthesis/callstring-callstring_h5.json | 3 ++- conf/masterthesis/callstring-site_inf.json | 3 ++- conf/masterthesis/callstring-stringWCallee_inf.json | 3 ++- conf/masterthesis/callstring-string_inf.json | 3 ++- conf/masterthesis/context-gas-10.json | 3 ++- conf/masterthesis/context-gas-20.json | 3 ++- conf/masterthesis/context-gas-30.json | 3 ++- conf/masterthesis/context-gas-40.json | 3 ++- conf/masterthesis/context-paper-24.json | 3 ++- conf/masterthesis/context-widening.json | 3 ++- conf/masterthesis/loopfree-callstring.json | 3 ++- 16 files changed, 32 insertions(+), 16 deletions(-) diff --git a/conf/masterthesis/callstring-callsite_h2.json b/conf/masterthesis/callstring-callsite_h2.json index c32a59c3a7..2b8f3ec56b 100644 --- a/conf/masterthesis/callstring-callsite_h2.json +++ b/conf/masterthesis/callstring-callsite_h2.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-callsite_h5.json b/conf/masterthesis/callstring-callsite_h5.json index 0b5b396550..13589cdb70 100644 --- a/conf/masterthesis/callstring-callsite_h5.json +++ b/conf/masterthesis/callstring-callsite_h5.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-callstringWCallee_h2.json b/conf/masterthesis/callstring-callstringWCallee_h2.json index 165f3e9f3e..c9dfada70f 100644 --- a/conf/masterthesis/callstring-callstringWCallee_h2.json +++ b/conf/masterthesis/callstring-callstringWCallee_h2.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-callstringWCallee_h5.json b/conf/masterthesis/callstring-callstringWCallee_h5.json index d43bfdecf3..505d383940 100644 --- a/conf/masterthesis/callstring-callstringWCallee_h5.json +++ b/conf/masterthesis/callstring-callstringWCallee_h5.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-callstring_h2.json b/conf/masterthesis/callstring-callstring_h2.json index 8b3d620adc..bde722030d 100644 --- a/conf/masterthesis/callstring-callstring_h2.json +++ b/conf/masterthesis/callstring-callstring_h2.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-callstring_h5.json b/conf/masterthesis/callstring-callstring_h5.json index 282f7b1886..fc2bcfb588 100644 --- a/conf/masterthesis/callstring-callstring_h5.json +++ b/conf/masterthesis/callstring-callstring_h5.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-site_inf.json b/conf/masterthesis/callstring-site_inf.json index 174cb381e3..df04588c76 100644 --- a/conf/masterthesis/callstring-site_inf.json +++ b/conf/masterthesis/callstring-site_inf.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-stringWCallee_inf.json b/conf/masterthesis/callstring-stringWCallee_inf.json index 47e9abc300..c45f956dc3 100644 --- a/conf/masterthesis/callstring-stringWCallee_inf.json +++ b/conf/masterthesis/callstring-stringWCallee_inf.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/callstring-string_inf.json b/conf/masterthesis/callstring-string_inf.json index 1ddfd66e93..16298f4e83 100644 --- a/conf/masterthesis/callstring-string_inf.json +++ b/conf/masterthesis/callstring-string_inf.json @@ -82,6 +82,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -112,7 +113,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-gas-10.json b/conf/masterthesis/context-gas-10.json index 1ed44eea90..f7d3461f9a 100644 --- a/conf/masterthesis/context-gas-10.json +++ b/conf/masterthesis/context-gas-10.json @@ -80,6 +80,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -110,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-gas-20.json b/conf/masterthesis/context-gas-20.json index 25238d3cbd..5d3e808cab 100644 --- a/conf/masterthesis/context-gas-20.json +++ b/conf/masterthesis/context-gas-20.json @@ -80,6 +80,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -110,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-gas-30.json b/conf/masterthesis/context-gas-30.json index dbbea92e36..ef27da1e83 100644 --- a/conf/masterthesis/context-gas-30.json +++ b/conf/masterthesis/context-gas-30.json @@ -80,6 +80,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -110,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-gas-40.json b/conf/masterthesis/context-gas-40.json index 74e420d09e..4dc41b820a 100644 --- a/conf/masterthesis/context-gas-40.json +++ b/conf/masterthesis/context-gas-40.json @@ -80,6 +80,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -110,7 +111,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-paper-24.json b/conf/masterthesis/context-paper-24.json index 730de29493..8fc9611273 100644 --- a/conf/masterthesis/context-paper-24.json +++ b/conf/masterthesis/context-paper-24.json @@ -83,6 +83,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -113,7 +114,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/context-widening.json b/conf/masterthesis/context-widening.json index 823683137e..5dbd101fb2 100644 --- a/conf/masterthesis/context-widening.json +++ b/conf/masterthesis/context-widening.json @@ -83,6 +83,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -113,7 +114,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" diff --git a/conf/masterthesis/loopfree-callstring.json b/conf/masterthesis/loopfree-callstring.json index 96f4a07e86..de75170637 100644 --- a/conf/masterthesis/loopfree-callstring.json +++ b/conf/masterthesis/loopfree-callstring.json @@ -84,6 +84,7 @@ "mallocWrappers", "enums", "congruence", + "octagon", "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", @@ -114,7 +115,7 @@ "unknown": false }, "yaml": { - "enabled": false, + "enabled": true, "format-version": "2.0", "entry-types": [ "invariant_set" From e9c31737d64c09a52c612138b8c4cb808d3f5706 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 15 Mar 2024 16:16:47 +0100 Subject: [PATCH 118/128] added context gas 0 config --- conf/masterthesis/context-gas-0.json | 144 +++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 conf/masterthesis/context-gas-0.json diff --git a/conf/masterthesis/context-gas-0.json b/conf/masterthesis/context-gas-0.json new file mode 100644 index 0000000000..c7358964e5 --- /dev/null +++ b/conf/masterthesis/context-gas-0.json @@ -0,0 +1,144 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "taintPartialContexts" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false, + "gas_value": 0 + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + "ldv_malloc", + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "enums", + "congruence", + "octagon", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file From a9b03bb60a70bf09c6e90736b109961fdc1dd684 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 20 Mar 2024 12:00:50 +0100 Subject: [PATCH 119/128] add explanatory comments --- src/analyses/callstring.ml | 8 +++----- src/analyses/loopfreeCallstring.ml | 11 +++++++---- src/framework/constraints.ml | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/analyses/callstring.ml b/src/analyses/callstring.ml index 773ea882f9..3d3be53dfd 100644 --- a/src/analyses/callstring.ml +++ b/src/analyses/callstring.ml @@ -2,7 +2,7 @@ open Analyses open GoblintCil open GobConfig -(* Specifies the type of the call stack elements for the call string analysis *) +(* Specifies the type of the call stack elements *) module type Callstack_Type = sig include CilType.S @@ -10,7 +10,7 @@ sig val stackEle: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call stack *) end -(** Analysis with the k-call string approach, which uses the last k call stack elements as context. +(** Call string approach and Call site approach. It is possible to use an infinite call stack of the k-CFA approach, which tracks the last k stack elements. With the CT argument it is possible to specify the type of the call stack elements *) module Spec (CT:Callstack_Type) : MCPSpec = struct @@ -27,8 +27,7 @@ struct let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) if get_int "ana.context.callStack_height" < 0 then new_stack (* infinite call stack *) - else - (* removes element from stack, if stack was filled with k elements *) + else (* maximum of k elements *) match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with | x when x <= 0 -> new_stack | 1 -> fst @@ Option.get (BatDeque.rear new_stack) @@ -85,7 +84,6 @@ module Callsite:Callstack_Type = struct | _ -> None (* first statement is filtered *) end -(* Lifters for the call string approach with different call stack element types *) let _ = (* call string approach *) MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string] *) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 26f794750e..a83de1ea89 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -1,5 +1,7 @@ (** This approach is inspired by - @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. *) + @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. + The idea is to improve the call string appraoch, by representing all detected loops of the call stack in a set +*) open Analyses @@ -12,7 +14,7 @@ struct module FundecSet = SetDomain.Make (CilType.Fundec) module Either = Printable.Either (CilType.Fundec) (FundecSet) - module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a list of Fundecs and sets of Fundecs. Lattice.Flat is used to fulfill the type *) + module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a list of Fundecs and Sets of Fundecs. Lattice.Flat is used to fulfill the type *) module C = D module V = EmptyV module G = Lattice.Unit @@ -24,6 +26,7 @@ struct | _ -> failwith "Error loopfreeCallstring (get_list): D should represent a call stack not `Top or `Bottom!" let loop_detected f = function + (* a call stack contains each function at most once *) | `Left ele -> CilType.Fundec.equal f ele | `Right set -> FundecSet.mem f set @@ -35,8 +38,8 @@ struct | [] -> (`Left f)::(List.rev prev_list) (* f is not yet contained in the call stack*) | e::rem_list -> let new_set = add_to_set prev_set e in - if loop_detected f e - then (`Right new_set)::rem_list + if loop_detected f e (* f is already present in the call stack *) + then (`Right new_set)::rem_list (* combine all elements of the loop in a set *) else callee_state f new_set (e::prev_list) rem_list let callee_state f ctx = `Lifted(callee_state f (FundecSet.empty ()) [] (get_list ctx.local)) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index b89b1ac988..d9b4c9068b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -504,8 +504,8 @@ struct let names x = Format.asprintf "%d" x end -(** Lifts a [Spec] with the context gas variable. For every function call the context gas is reduced. - If the gas is 0, the remaining function calls are analyzed without context-information *) +(** Lifts a [Spec] with the context gas variable. For every function call the gas is reduced. + If the gas is zero, the remaining function calls are analyzed without context-information *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) and module C = Printable.Option (S.C) (NoContext) @@ -555,7 +555,7 @@ struct ; context = (fun () -> Option.get (ctx.context ()))} let enter ctx r f args = - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in (* callee gas = caller gas - 1 *) liftmap_tup (S.enter (conv ctx) r f args) let threadenter ctx ~multiple lval f args = From 3b75f9e8dd3f781876cbe7415dd40a5998bdd79f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 7 Apr 2024 21:00:59 +0200 Subject: [PATCH 120/128] add cont_sens_ids set to check for inse ana more efficiently --- src/analyses/mCP.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 8d964479d9..73579442b4 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -36,8 +36,7 @@ struct let name () = "MCP2" let path_sens = ref [] - let cont_sens = ref [] - let cont_inse = ref [] + let cont_sens_ids = ref Set.empty let base_id = ref (-1) @@ -85,12 +84,13 @@ struct begin match get_string_list "ana.ctx_sens" with | [] -> (* use values of "ana.ctx_insens" (blacklist) *) - cont_inse := map' find_id @@ get_string_list "ana.ctx_insens"; - activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n !cont_inse)) !activated; + let cont_inse = map' find_id @@ get_string_list "ana.ctx_insens" in + activated_ctx_sens := List.filter (fun (n, _) -> not (List.mem n cont_inse)) !activated; | sens -> (* use values of "ana.ctx_sens" (whitelist) *) - cont_sens := map' find_id @@ sens; - activated_ctx_sens := List.filter (fun (n, _) -> List.mem n !cont_sens) !activated; + let cont_sens = map' find_id @@ sens in + activated_ctx_sens := List.filter (fun (n, _) -> List.mem n cont_sens) !activated; end; + cont_sens_ids := Set.of_list (List.map (fun (n,p) -> n) !activated_ctx_sens); activated_path_sens := List.filter (fun (n, _) -> List.mem n !path_sens) !activated; match marshal with | Some marshal -> @@ -115,7 +115,7 @@ struct let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> - if (mem n !cont_inse) || not @@ (List.is_empty !cont_sens || mem n !cont_sens) then (* TODO: do I need to check if it is contained in activated ana?*) + if Set.is_empty !cont_sens_ids || not (Set.mem n !cont_sens_ids) then (*n is insensitive*) None else Some (n, repr @@ S.context fd (obj d)) From a88606e9dddcdadb3ca67da1f7b66cacc9c2e389 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 14 Apr 2024 13:37:55 +0200 Subject: [PATCH 121/128] deleted configurations, deleted call_string_withCallee, updated callstring file (variable names: call stack -> call string, comments) --- conf/masterthesis/callstring-callsite_h2.json | 146 -------------- conf/masterthesis/callstring-callsite_h5.json | 146 -------------- .../callstring-callstringWCallee_h2.json | 146 -------------- .../callstring-callstringWCallee_h5.json | 146 -------------- .../callstring-callstring_h2.json | 146 -------------- .../callstring-callstring_h5.json | 146 -------------- conf/masterthesis/callstring-site_inf.json | 146 -------------- .../callstring-stringWCallee_inf.json | 146 -------------- conf/masterthesis/callstring-string_inf.json | 146 -------------- conf/masterthesis/context-gas-0.json | 144 -------------- conf/masterthesis/context-gas-10.json | 144 -------------- conf/masterthesis/context-gas-20.json | 144 -------------- conf/masterthesis/context-gas-30.json | 144 -------------- conf/masterthesis/context-gas-40.json | 144 -------------- conf/masterthesis/context-paper-24.json | 147 -------------- conf/masterthesis/context-widening.json | 147 -------------- conf/masterthesis/loopfree-callstring.json | 148 -------------- src/analyses/callstring.ml | 81 ++++---- src/config/options.schema.json | 6 +- .../01-multiple_tests_h5sens_cs.c | 2 +- .../02-multiple_tests_h5ins_cs.c | 2 +- .../03-multiple_tests_h2sens_cs.c | 2 +- .../82-callstring/04-endless_loop_cs.c | 2 +- .../82-callstring/05-ackermann_cs.c | 2 +- .../regression/82-callstring/06-big_loop_cs.c | 2 +- .../82-callstring/07-loop_unrolling_cs.c | 2 +- .../82-callstring/08-threads_sens_cs.c | 2 +- .../82-callstring/09-threads_ins_cs.c | 2 +- .../82-callstring/10-inf_callstack_cs.c | 2 +- .../11-multiple_tests_h5sens_csi.c | 2 +- .../12-multiple_tests_h5ins_csi.c | 2 +- .../13-multiple_tests_h2sens_csi.c | 2 +- .../82-callstring/14-endless_loop_csi.c | 2 +- .../82-callstring/15-ackermann_csi.c | 2 +- .../82-callstring/16-big_loop_csi.c | 2 +- .../82-callstring/17-loop_unrolling_csi.c | 2 +- .../82-callstring/18-threads_sens_csi.c | 2 +- .../82-callstring/19-threads_ins_csi.c | 2 +- .../82-callstring/20-inf_callstack_csi.c | 2 +- .../21-multiple_tests_h5sens_csWCallee.c | 136 ------------- .../22-multiple_tests_h5ins_csWCallee.c | 132 ------------- .../23-multiple_tests_h2sens_csWCallee.c | 183 ------------------ .../82-callstring/24-endless_loop_csWCallee.c | 25 --- .../82-callstring/25-ackermann_csWCallee.c | 28 --- .../82-callstring/26-big_loop_csWCallee.c | 41 ---- .../27-loop_unrolling_csWCallee.c | 24 --- .../82-callstring/28-threads_sens_csWCallee.c | 95 --------- .../82-callstring/29-threads_ins_csWCallee.c | 73 ------- .../30-inf_callstack_csWCallee.c | 21 -- 49 files changed, 63 insertions(+), 3298 deletions(-) delete mode 100644 conf/masterthesis/callstring-callsite_h2.json delete mode 100644 conf/masterthesis/callstring-callsite_h5.json delete mode 100644 conf/masterthesis/callstring-callstringWCallee_h2.json delete mode 100644 conf/masterthesis/callstring-callstringWCallee_h5.json delete mode 100644 conf/masterthesis/callstring-callstring_h2.json delete mode 100644 conf/masterthesis/callstring-callstring_h5.json delete mode 100644 conf/masterthesis/callstring-site_inf.json delete mode 100644 conf/masterthesis/callstring-stringWCallee_inf.json delete mode 100644 conf/masterthesis/callstring-string_inf.json delete mode 100644 conf/masterthesis/context-gas-0.json delete mode 100644 conf/masterthesis/context-gas-10.json delete mode 100644 conf/masterthesis/context-gas-20.json delete mode 100644 conf/masterthesis/context-gas-30.json delete mode 100644 conf/masterthesis/context-gas-40.json delete mode 100644 conf/masterthesis/context-paper-24.json delete mode 100644 conf/masterthesis/context-widening.json delete mode 100644 conf/masterthesis/loopfree-callstring.json delete mode 100644 tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c delete mode 100644 tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c delete mode 100644 tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c delete mode 100644 tests/regression/82-callstring/24-endless_loop_csWCallee.c delete mode 100644 tests/regression/82-callstring/25-ackermann_csWCallee.c delete mode 100644 tests/regression/82-callstring/26-big_loop_csWCallee.c delete mode 100644 tests/regression/82-callstring/27-loop_unrolling_csWCallee.c delete mode 100644 tests/regression/82-callstring/28-threads_sens_csWCallee.c delete mode 100644 tests/regression/82-callstring/29-threads_ins_csWCallee.c delete mode 100644 tests/regression/82-callstring/30-inf_callstack_csWCallee.c diff --git a/conf/masterthesis/callstring-callsite_h2.json b/conf/masterthesis/callstring-callsite_h2.json deleted file mode 100644 index 2b8f3ec56b..0000000000 --- a/conf/masterthesis/callstring-callsite_h2.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_site" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 2 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-callsite_h5.json b/conf/masterthesis/callstring-callsite_h5.json deleted file mode 100644 index 13589cdb70..0000000000 --- a/conf/masterthesis/callstring-callsite_h5.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_site" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 5 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-callstringWCallee_h2.json b/conf/masterthesis/callstring-callstringWCallee_h2.json deleted file mode 100644 index c9dfada70f..0000000000 --- a/conf/masterthesis/callstring-callstringWCallee_h2.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string_withCallee" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 2 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-callstringWCallee_h5.json b/conf/masterthesis/callstring-callstringWCallee_h5.json deleted file mode 100644 index 505d383940..0000000000 --- a/conf/masterthesis/callstring-callstringWCallee_h5.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string_withCallee" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 5 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-callstring_h2.json b/conf/masterthesis/callstring-callstring_h2.json deleted file mode 100644 index bde722030d..0000000000 --- a/conf/masterthesis/callstring-callstring_h2.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 2 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-callstring_h5.json b/conf/masterthesis/callstring-callstring_h5.json deleted file mode 100644 index fc2bcfb588..0000000000 --- a/conf/masterthesis/callstring-callstring_h5.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": 5 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-site_inf.json b/conf/masterthesis/callstring-site_inf.json deleted file mode 100644 index df04588c76..0000000000 --- a/conf/masterthesis/callstring-site_inf.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_site" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": -1 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-stringWCallee_inf.json b/conf/masterthesis/callstring-stringWCallee_inf.json deleted file mode 100644 index c45f956dc3..0000000000 --- a/conf/masterthesis/callstring-stringWCallee_inf.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string_withCallee" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": -1 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/callstring-string_inf.json b/conf/masterthesis/callstring-string_inf.json deleted file mode 100644 index 16298f4e83..0000000000 --- a/conf/masterthesis/callstring-string_inf.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "call_string" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": -1, - "callStack_height": -1 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-gas-0.json b/conf/masterthesis/context-gas-0.json deleted file mode 100644 index c7358964e5..0000000000 --- a/conf/masterthesis/context-gas-0.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": 0 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-gas-10.json b/conf/masterthesis/context-gas-10.json deleted file mode 100644 index f7d3461f9a..0000000000 --- a/conf/masterthesis/context-gas-10.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": 10 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-gas-20.json b/conf/masterthesis/context-gas-20.json deleted file mode 100644 index 5d3e808cab..0000000000 --- a/conf/masterthesis/context-gas-20.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": 20 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-gas-30.json b/conf/masterthesis/context-gas-30.json deleted file mode 100644 index ef27da1e83..0000000000 --- a/conf/masterthesis/context-gas-30.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": 30 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-gas-40.json b/conf/masterthesis/context-gas-40.json deleted file mode 100644 index 4dc41b820a..0000000000 --- a/conf/masterthesis/context-gas-40.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false, - "gas_value": 40 - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - "ldv_malloc", - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/conf/masterthesis/context-paper-24.json b/conf/masterthesis/context-paper-24.json deleted file mode 100644 index 8fc9611273..0000000000 --- a/conf/masterthesis/context-paper-24.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "gas_value": -1, - "widen": false - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - - "ldv_malloc", - - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} diff --git a/conf/masterthesis/context-widening.json b/conf/masterthesis/context-widening.json deleted file mode 100644 index 5dbd101fb2..0000000000 --- a/conf/masterthesis/context-widening.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "gas_value": -1, - "widen": true - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - - "ldv_malloc", - - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} diff --git a/conf/masterthesis/loopfree-callstring.json b/conf/masterthesis/loopfree-callstring.json deleted file mode 100644 index de75170637..0000000000 --- a/conf/masterthesis/loopfree-callstring.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "taintPartialContexts", - "loopfree_callstring" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "gas_value": -1, - "widen": false - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - - "ldv_malloc", - - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "enums", - "congruence", - "octagon", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} diff --git a/src/analyses/callstring.ml b/src/analyses/callstring.ml index 3d3be53dfd..ee3a1d8cd0 100644 --- a/src/analyses/callstring.ml +++ b/src/analyses/callstring.ml @@ -1,56 +1,63 @@ +(** + Call String analysis [call_string] and/or Call Site analysis [call_site]. + The call string limitation for both approaches can be adjusted with the "callString_length" option. + By adding new implementations of the CallstringType, additional analyses can be added. +*) + open Analyses open GoblintCil open GobConfig -(* Specifies the type of the call stack elements *) -module type Callstack_Type = +(* Specifies the type of the call string elements *) +module type CallstringType = sig include CilType.S - val stackTypeName: string - val stackEle: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call stack *) + val ana_name: string + val new_ele: fundec -> ('d,'g,'c,'v) ctx -> t option (* returns an element that should be pushed to the call string *) end -(** Call string approach and Call site approach. It is possible to use an infinite call stack of the k-CFA approach, which tracks the last k stack elements. - With the CT argument it is possible to specify the type of the call stack elements *) -module Spec (CT:Callstack_Type) : MCPSpec = +(** Analysis with infinite call string or with limited call string (k-CFA, tracks the last k call stack elements). + With the CT argument it is possible to specify the type of the call string elements *) +module Spec (CT:CallstringType) : MCPSpec = struct include Analyses.IdentitySpec - (* simulates a call stack of depth k *) - module CallStack = struct + (* simulates a call string (with or without limitation)*) + module CallString = struct include Printable.PQueue (CT) - let push stack elem = (* pushes elem to the call stack, guarantees a depth of k if it is specified with "ana.context.callStack_height" *) + (* pushes "elem" to the call string, guarantees a depth of k if limitation is specified with "ana.context.callString_length" *) + let push callstr elem = match elem with - | None -> stack + | None -> callstr | Some e -> - let new_stack = BatDeque.cons e stack in (* pushes new element to stack *) - if get_int "ana.context.callStack_height" < 0 - then new_stack (* infinite call stack *) + let new_callstr = BatDeque.cons e callstr in (* pushes new element to callstr *) + if get_int "ana.context.callString_length" < 0 + then new_callstr (* infinite call string *) else (* maximum of k elements *) - match (BatDeque.size new_stack - (get_int "ana.context.callStack_height")) with - | x when x <= 0 -> new_stack - | 1 -> fst @@ Option.get (BatDeque.rear new_stack) - | _ -> failwith "Callstack Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" + match (BatDeque.size new_callstr - (get_int "ana.context.callString_length")) with + | 1 -> fst @@ Option.get (BatDeque.rear new_callstr) + | x when x <= 0 -> new_callstr + | _ -> failwith "CallString Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" end - module D = Lattice.Flat (CallStack) (* should be the CallStack (C=D). Since a Lattice is required, Lattice.Flat is used to fulfill the type *) - module C = CallStack + module D = Lattice.Flat (CallString) (* should be the CallString (C=D). Since a Lattice is required, Lattice.Flat is used to fulfill the type *) + module C = CallString module V = EmptyV module G = Lattice.Unit - let name () = "call_"^ CT.stackTypeName + let name () = "call_"^ CT.ana_name let startstate v = `Lifted (BatDeque.empty) let exitstate v = `Lifted (BatDeque.empty) let context fd x = match x with | `Lifted x -> x - | _ -> failwith "Callstring: Context error! The context cannot be derived from Top or Bottom!" + | _ -> failwith "CallString: Context error! The context cannot be derived from Top or Bottom!" let callee_state ctx f = - let elem = CT.stackEle f ctx in - let new_stack = CallStack.push (context f ctx.local) elem in - `Lifted new_stack + let elem = CT.new_ele f ctx in (* receive element that should be added to call string *) + let new_callstr = CallString.push (context f ctx.local) elem in + `Lifted new_callstr let enter ctx r f args = [ctx.local, callee_state ctx f] @@ -59,26 +66,21 @@ struct let threadenter ctx ~multiple lval v args = [callee_state ctx (Cilfacade.find_varinfo_fundec v)] end -module Callstring:Callstack_Type = struct +(* implementations of CallstringTypes*) +module Callstring:CallstringType = struct include CilType.Fundec - let stackTypeName = "string" - let stackEle f ctx = + let ana_name = "string" + let new_ele f ctx = let f' = Node.find_fundec ctx.node in if CilType.Fundec.equal f' dummyFunDec then None - else Some (f') + else Some f' end -module Callstring_Callee:Callstack_Type = struct - include CilType.Fundec - let stackTypeName = "string_withCallee" - let stackEle f ctx = Some f -end - -module Callsite:Callstack_Type = struct +module Callsite:CallstringType = struct include CilType.Stmt - let stackTypeName = "site" - let stackEle f ctx = + let ana_name = "site" + let new_ele f ctx = match ctx.prev_node with | Statement stmt -> Some stmt | _ -> None (* first statement is filtered *) @@ -88,8 +90,5 @@ let _ = (* call string approach *) MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string] *) - (* call string approach: additionally tracks the callee function in the call stack *) - MCP.register_analysis (module Spec (Callstring_Callee) : MCPSpec); (* [call_string_withCallee] *) - (* call site approach *) MCP.register_analysis (module Spec (Callsite) : MCPSpec); (* [call_site] *) \ No newline at end of file diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 5e80ad8051..90f6950a97 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -984,9 +984,9 @@ "type": "integer", "default": -1 }, - "callStack_height": { - "title": "ana.context.callStack_height", - "description": "Height of the call stack that should be used as context for the call string analysis. In case the value is zero, the analysis is context-insensitive. For a negative value an infinite call stack is used!", + "callString_length": { + "title": "ana.context.callString_length", + "description": "Length of the call string that should be used as context for the Call String analysis. In case the value is zero, the analysis is context-insensitive. For a negative value an infinite call string is used!", "type": "integer", "default": 2 } diff --git a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c index c5eb7d09b3..22e682bb3b 100644 --- a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c +++ b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c index 19fd172e35..f28abe0e99 100644 --- a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c +++ b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c index 4e21efa010..51e5bdf16d 100644 --- a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c +++ b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/04-endless_loop_cs.c b/tests/regression/82-callstring/04-endless_loop_cs.c index 9e0326b318..0d0b2c0612 100644 --- a/tests/regression/82-callstring/04-endless_loop_cs.c +++ b/tests/regression/82-callstring/04-endless_loop_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis int num_iterat = 2; diff --git a/tests/regression/82-callstring/05-ackermann_cs.c b/tests/regression/82-callstring/05-ackermann_cs.c index aedfdef552..c6340a9dbb 100644 --- a/tests/regression/82-callstring/05-ackermann_cs.c +++ b/tests/regression/82-callstring/05-ackermann_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/06-big_loop_cs.c b/tests/regression/82-callstring/06-big_loop_cs.c index d03507b16f..e9ba61f324 100644 --- a/tests/regression/82-callstring/06-big_loop_cs.c +++ b/tests/regression/82-callstring/06-big_loop_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/07-loop_unrolling_cs.c b/tests/regression/82-callstring/07-loop_unrolling_cs.c index dc58208687..cdbd6d49bb 100644 --- a/tests/regression/82-callstring/07-loop_unrolling_cs.c +++ b/tests/regression/82-callstring/07-loop_unrolling_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/08-threads_sens_cs.c b/tests/regression/82-callstring/08-threads_sens_cs.c index bf5caceeee..3f046efad5 100644 --- a/tests/regression/82-callstring/08-threads_sens_cs.c +++ b/tests/regression/82-callstring/08-threads_sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/09-threads_ins_cs.c b/tests/regression/82-callstring/09-threads_ins_cs.c index 0b1bbd2a3c..d61954c767 100644 --- a/tests/regression/82-callstring/09-threads_ins_cs.c +++ b/tests/regression/82-callstring/09-threads_ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/10-inf_callstack_cs.c b/tests/regression/82-callstring/10-inf_callstack_cs.c index add6427935..c52e1d0bb5 100644 --- a/tests/regression/82-callstring/10-inf_callstack_cs.c +++ b/tests/regression/82-callstring/10-inf_callstack_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set ana.context.callStack_height -1 +// PARAM: --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set ana.context.callString_length -1 #include diff --git a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c index 4a914ea482..1d6cb73dcc 100644 --- a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c +++ b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c index 53e318b172..815aaba148 100644 --- a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c +++ b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c index c32a044808..e4a085b7d7 100644 --- a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c +++ b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/14-endless_loop_csi.c b/tests/regression/82-callstring/14-endless_loop_csi.c index 88372f963e..fd19e6a578 100644 --- a/tests/regression/82-callstring/14-endless_loop_csi.c +++ b/tests/regression/82-callstring/14-endless_loop_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Will result in an endless loop without context insensitive analysis int num_iterat = 2; diff --git a/tests/regression/82-callstring/15-ackermann_csi.c b/tests/regression/82-callstring/15-ackermann_csi.c index 16f06c0360..f37de2d357 100644 --- a/tests/regression/82-callstring/15-ackermann_csi.c +++ b/tests/regression/82-callstring/15-ackermann_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/16-big_loop_csi.c b/tests/regression/82-callstring/16-big_loop_csi.c index 7afe068a30..7a993cfc5c 100644 --- a/tests/regression/82-callstring/16-big_loop_csi.c +++ b/tests/regression/82-callstring/16-big_loop_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/17-loop_unrolling_csi.c b/tests/regression/82-callstring/17-loop_unrolling_csi.c index 33b66d5995..2b37ad2af2 100644 --- a/tests/regression/82-callstring/17-loop_unrolling_csi.c +++ b/tests/regression/82-callstring/17-loop_unrolling_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/18-threads_sens_csi.c b/tests/regression/82-callstring/18-threads_sens_csi.c index 6b3713d20b..58b39addc6 100644 --- a/tests/regression/82-callstring/18-threads_sens_csi.c +++ b/tests/regression/82-callstring/18-threads_sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/19-threads_ins_csi.c b/tests/regression/82-callstring/19-threads_ins_csi.c index e73af0b3b9..51850988a9 100644 --- a/tests/regression/82-callstring/19-threads_ins_csi.c +++ b/tests/regression/82-callstring/19-threads_ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/20-inf_callstack_csi.c b/tests/regression/82-callstring/20-inf_callstack_csi.c index 2bffbc393a..6007ab9b85 100644 --- a/tests/regression/82-callstring/20-inf_callstack_csi.c +++ b/tests/regression/82-callstring/20-inf_callstack_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set ana.context.callStack_height -1 +// PARAM: --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set ana.context.callString_length -1 #include diff --git a/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c b/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c deleted file mode 100644 index 8e36b9094e..0000000000 --- a/tests/regression/82-callstring/21-multiple_tests_h5sens_csWCallee.c +++ /dev/null @@ -1,136 +0,0 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set - -// Test 1: -int a(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return a(i - 1); - } - return 1; -} - -int b(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return a(i - 1); - } - return 2; -} - -int c(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return b(i - 1); - } - return 3; -} - -// Test 2: -int e(int i); - -int f(int i) -{ - if (i > 0) - { - return e(i - 1); - } - return 2; -} - -int e(int i) -{ - return f(i - 1) + 1; -} - -// Test 3: -int h(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return h(i - 1); - } - return 0; -} - -int k(int i) -{ - if (i == 2) - { - return h(i - 1) + 1; - } - if (i > 0) - { - return k(i - 1); - } - return 1; -} - -// Test 4: -int m = 20; - -int o(int i) -{ - if (i > 0) - { - m = --i; - o(i); - } - return 0; -} - -int main(void) -{ - // Test 1: - /* main -> a(3) -> ... -> a(0) -> return 11 - [main, a, a, a, a] */ - __goblint_check(a(3) == 11); - - /* main -> a(6) -> ... -> a(0) -> return 11 - [main, a, a, a, a] and [a, a, a, a, a] (3 times) */ - __goblint_check(a(6) == 11); - - /* main -> b(3) -> a(2) -> a(1) -> a(0) -> return 11 - [main, b, a, a, a] */ - __goblint_check(b(3) == 11); - - /* main -> c(3) -> b(2) -> a(1) -> a(0) -> return 11 - [main, c, b, a, a] */ - __goblint_check(c(3) == 11); - - // Test 2: - /* main -> e(5) -> f(4) -> e(3) -> f(2) -> e(1) -> f(0) -> return 2 - [main, e, f, e, f] and [e, f , e, f, e] and [f , e, f, e, f]*/ - __goblint_check(e(5) == 5); - - // Test 3: - /* main -> k(8) -> ... -> k(2) -> h(1) -> h(0) -> return 1 - [main, k, k, k, k] and [k, k, k, k, k] (3 times) and [k, k, k, k, h] */ - __goblint_check(k(8) == 2); - - // Test 4: - /* main -> o(4) -> o(3) -> ... o(0) - [main, o, o, o, o] and [o, o, o, o, o] */ - o(4); - __goblint_check(m == 0); - - return 0; -} diff --git a/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c b/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c deleted file mode 100644 index b7c2782bc3..0000000000 --- a/tests/regression/82-callstring/22-multiple_tests_h5ins_csWCallee.c +++ /dev/null @@ -1,132 +0,0 @@ -// PARAM: --set ana.context.callStack_height 5 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set - -// Test 1: -int a(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return a(i - 1); - } - return 1; -} - -int b(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return a(i - 1); - } - return 2; -} - -int c(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return b(i - 1); - } - return 3; -} - -// Test 2: -int e(int i); - -int f(int i) -{ - if (i > 0) - { - return e(i - 1); - } - return 2; -} - -int e(int i) -{ - return f(i - 1) + 1; -} - -// Test 3: -int h(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return h(i - 1); - } - return 0; -} - -int k(int i) -{ - if (i == 2) - { - return h(i - 1) + 1; - } - if (i > 0) - { - return k(i - 1); - } - return 1; -} - -// Test 4: -int m = 20; - -int o(int i) -{ - if (i > 0) - { - m = --i; - o(i); - } - return 0; -} - -int main(void) -{ - // Test 1: - /* main -> a(7) -> ... -> a(0) -> return 11 - [main, a, a, a, a] and [a, a, a, a, a] (4 times) */ - __goblint_check(a(7) == 11); // UNKNOWN - - /* main -> b(20) -> a(19) -> ... -> a(0) -> return 11 - [main, b, a, a, a] and [g, a, a, a, a] and [a, a, a, a, a] (16 times) */ - __goblint_check(b(20) == 11); // UNKNOWN - - /* main -> c(10) -> b(9) -> a(8) -> ... -> a(0) -> return 11 - [main, c, b, a, a] and [c, b, a, a, a] and [b, a, a, a, a] and [a, a, a, a, a] (5 times) */ - __goblint_check(c(10) == 11); // UNKNOWN - - // Test 2: - /* main -> e(7) -> f(6) -> e(5) -> ... -> e(1) -> f(0) -> return 2 - [main, e, f, e, f] and [e, f , e, f, e] (2 times) and [f , e, f, e, f] (2 times) */ - __goblint_check(e(7) == 6); // UNKNOWN - - // Test 3: - /* main -> k(9) -> ... -> k(2) -> h(1) -> h(0) -> return 1 - [main, k, k, k, k] and [k, k, k, k, k] (4 times) and [k, k, k, k, h] */ - __goblint_check(k(9) == 2); // UNKNOWN - - // Test 4: - /* main -> o(5) -> o(4) -> ... o(0) - [main, o, o, o, o] and [o, o, o, o, o] (2 times) */ - o(5); - __goblint_check(m == 0); // UNKNOWN - - return 0; -} diff --git a/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c b/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c deleted file mode 100644 index 1337d107b5..0000000000 --- a/tests/regression/82-callstring/23-multiple_tests_h2sens_csWCallee.c +++ /dev/null @@ -1,183 +0,0 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set - -// Test 1: -int a(int i) -{ - if (i == 0) - { - return 11; - } - if (i > 0) - { - return a(i - 1); - } - return 1; -} - -int b(int i) -{ - if (i == 0) - { - return 12; - } - if (i > 0) - { - return a(i - 1); - } - return 2; -} - -int c(int i) -{ - if (i == 0) - { - return 13; - } - if (i > 0) - { - return b(i - 1); - } - return 3; -} - -// Test 2: -int e(int i); - -int f(int i) -{ - if (i > 0) - { - return e(i - 1); - } - return 2; -} - -int e(int i) -{ - return f(i - 1) + 1; -} - -// Test 3: -int h(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return h(i - 1); - } - return 0; -} - -int k(int i) -{ - if (i == 2) - { - return h(i - 1) + 1; - } - if (i > 0) - { - return k(i - 1); - } - return 1; -} - -// Test 4: -int q(int i); - -int l(int i) -{ - if (i == 0) - { - return q(2); - } - else - { - return 4; - } -} - -int p(int i) -{ - return l(i - 1); -} - -int s(int i) -{ - return p(i - 1); -} - -int r(int i) -{ - return q(i - 1); -} - -int o(int i) -{ - if (i <= 0) - { - return r(4); - } - else - { - return o(i - 1); - } -} - -int q(int i) -{ - if (i == 4) - { - return o(3); - } - if (i == 3) - { - return s(2); - } - return p(20); -} - -int m(int i) -{ - return q(i); -} - -int main(void) -{ - // Test 1: - /* main -> a(0) -> return 11 - [main, a] */ - __goblint_check(a(0) == 11); - - /* main -> b(0) -> return 12 - [main, b] */ - __goblint_check(b(0) == 12); - - /* main -> c(0) -> return 13 - [main, c] */ - __goblint_check(c(0) == 13); - - // Test 2: - /* main -> f(0) -> return 2 - [main, f] */ - __goblint_check(f(0) == 2); - - /* main -> e(0) -> f(-1) -> return 2 - [main, e] and [e, f] */ - __goblint_check(e(0) == 3); - - // Test 3: - /* main -> k(5) -> ... -> k(2) -> h(1) -> h(0) -> return 1 - [main, k] and [k, k] (3 times) and [k, h] and [h, h] */ - __goblint_check(k(5) == 2); - - // Test 4: - /* main -> m(4) -> q(4) -> o(3) -> o(2) -> o(1) -> o(0) -> r(4) -> q(3) -> s(2) -> p(1) -> l(0) -> q(2) -> p(20) -> l(19) -> return 4 - [main, m] and [m, q] an [q, o] and [o, o] (3 times) and - [o, r] and [r, q] and [q, s] and [s, p] and [p, l] and [l, q] and [q, p] and [p, l] */ - __goblint_check(m(4) == 4); - - return 0; -} diff --git a/tests/regression/82-callstring/24-endless_loop_csWCallee.c b/tests/regression/82-callstring/24-endless_loop_csWCallee.c deleted file mode 100644 index d50cf0e8af..0000000000 --- a/tests/regression/82-callstring/24-endless_loop_csWCallee.c +++ /dev/null @@ -1,25 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set -// Will result in an endless loop without context insensitive analysis - -int num_iterat = 2; - -// main -> main -> ... -// [main, main, ...] -int main(void) -{ - if (num_iterat > 0) - { - num_iterat++; - int res = main(); - __goblint_check(res == 5); // UNKNOWN - return res; - } - else - { - if (num_iterat == 0) - { - return 5; - } - return 2; - } -} \ No newline at end of file diff --git a/tests/regression/82-callstring/25-ackermann_csWCallee.c b/tests/regression/82-callstring/25-ackermann_csWCallee.c deleted file mode 100644 index 7655a019d2..0000000000 --- a/tests/regression/82-callstring/25-ackermann_csWCallee.c +++ /dev/null @@ -1,28 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set - -int ack(int n, int m) -{ - if (n == 0) - { - return m + 1; - } - else - { - if (m == 0) - { - return ack(n - 1, 1); - } - else - { - return ack(n - 1, ack(n, m - 1)); - } - } -} - -int main(void) -{ - // main -> ack -> ack -> ... - // [main, ack, ...] - ack(4, 1); - __goblint_check(1); // reachable -} \ No newline at end of file diff --git a/tests/regression/82-callstring/26-big_loop_csWCallee.c b/tests/regression/82-callstring/26-big_loop_csWCallee.c deleted file mode 100644 index fc2b6f03ea..0000000000 --- a/tests/regression/82-callstring/26-big_loop_csWCallee.c +++ /dev/null @@ -1,41 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set -// Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed - -int f(int i); - -int g(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 11; -} - -int f(int i) -{ - if (i == 0) - { - return 2; - } - if (i > 0) - { - return g(i - 1); - } - return 12; -} - -int main(void) -{ - for (int i = 200; i > 0; i--) - { - int res1 = f(2); - int res2 = g(2); - __goblint_check(res1 == 2); - __goblint_check(res2 == 1); - } -} diff --git a/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c b/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c deleted file mode 100644 index 06b98e533a..0000000000 --- a/tests/regression/82-callstring/27-loop_unrolling_csWCallee.c +++ /dev/null @@ -1,24 +0,0 @@ -// PARAM: --set ana.context.callStack_height 2 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set --set exp.unrolling-factor 2 - -int f(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 11; -} - -int main(void) -{ - for (int i = 5; i > 0; i--) - { - // main -> f(3) -> ... -> f(0) -> return 1 - // [main, f] and [f, f] (3 times) - __goblint_check(f(3) == 1); - } -} diff --git a/tests/regression/82-callstring/28-threads_sens_csWCallee.c b/tests/regression/82-callstring/28-threads_sens_csWCallee.c deleted file mode 100644 index b0f21f0b08..0000000000 --- a/tests/regression/82-callstring/28-threads_sens_csWCallee.c +++ /dev/null @@ -1,95 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set -#include -#include - -int f(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 11; -} - -int g(int i) -{ - if (i == 0) - { - return 3; - } - if (i > 0) - { - return g(i - 1); - } - return 13; -} - -int h(int i) -{ - if (i == 0) - { - return 2; - } - if (i > 0) - { - return g(i - 1); - } - return 12; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_sens(void *arg) -{ - // main -> t_sens -> procedure -> f(0) - // main -> t_sens -> procedure -> g(0) - // main -> t_sens -> procedure -> h(0) - __goblint_check(procedure(0) == 8); - return NULL; -} - -void *t_sens2(void *arg) -{ - // main -> t_sens2 -> procedure -> f(8) -> ... -> f(0) - // [main, t_sens2, procedure, f, f, f, f, f, f, f] and [t_sens2, procedure, f, f, f, f, f, f, f, f] and [procedure, f, f, f, f, f, f, f, f, f] - // main -> t_sens2 -> procedure -> g(8) -> g(7) -> ... -> g(0) - // main -> t_sens2 -> procedure -> h(8) -> g(7) -> ... -> g(0) - __goblint_check(procedure(8) == 10); - return NULL; -} - -void *t_sens3(void *arg) -{ - // main -> t_sens3 -> procedure -> f(11) -> ... -> f(0) - // [main, t_sens3, procedure, f, f, f, f, f, f, f] and [t_sens3, procedure, f, f, f, f, f, f, f, f] and - // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (3 times) - - // main -> t_sens3 -> procedure -> g(11) -> g(10) -> ... -> g(0) - // main -> t_sens3 -> procedure -> h(11) -> g(10) -> ... -> g(0) - __goblint_check(procedure(11) == 10); - return NULL; -} - -int main() -{ - pthread_t id; - pthread_t id2; - pthread_t id3; - - // Create the thread - pthread_create(&id, NULL, t_sens, NULL); - pthread_create(&id2, NULL, t_sens2, NULL); - pthread_create(&id3, NULL, t_sens3, NULL); - return 0; -} diff --git a/tests/regression/82-callstring/29-threads_ins_csWCallee.c b/tests/regression/82-callstring/29-threads_ins_csWCallee.c deleted file mode 100644 index c18df22d9c..0000000000 --- a/tests/regression/82-callstring/29-threads_ins_csWCallee.c +++ /dev/null @@ -1,73 +0,0 @@ -// PARAM: --set ana.context.callStack_height 10 --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set -#include -#include -#include - -int f(int i) -{ - if (i == 0) - { - return 1; - } - if (i > 0) - { - return f(i - 1); - } - return 11; -} - -int g(int i) -{ - if (i == 0) - { - return 3; - } - if (i > 0) - { - return g(i - 1); - } - return 13; -} - -int h(int i) -{ - if (i == 0) - { - return 2; - } - if (i > 0) - { - return g(i - 1); - } - return 12; -} - -int procedure(int num_iterat) -{ - int res1 = f(num_iterat); - int res2 = g(num_iterat); - int res3 = h(num_iterat); - int res4 = h(num_iterat); - return res1 + res2 + res3 + res4; -} - -void *t_ins(void *arg) -{ - // main -> t_ins -> procedure -> f(12) -> ... -> f(0) - // [main, t_ins, procedure, f, f, f, f, f, f, f] and [t_ins, procedure, f, f, f, f, f, f, f, f] and - // [procedure, f, f, f, f, f, f, f, f, f] and [f, f, f, f, f, f, f, f, f, f] (4 times) - - // main -> t_ins -> procedure -> g(12) -> g(11) -> ... -> g(0) - // main -> t_ins -> procedure -> h(12) -> g(11) -> ... -> g(0) - __goblint_check(procedure(12) == 10); // UNKNOWN - return NULL; -} - -int main() -{ - pthread_t id; - - // Create the thread - pthread_create(&id, NULL, t_ins, NULL); - return 0; -} diff --git a/tests/regression/82-callstring/30-inf_callstack_csWCallee.c b/tests/regression/82-callstring/30-inf_callstack_csWCallee.c deleted file mode 100644 index da14add437..0000000000 --- a/tests/regression/82-callstring/30-inf_callstack_csWCallee.c +++ /dev/null @@ -1,21 +0,0 @@ -// PARAM: --set "ana.activated[+]" call_string_withCallee --set ana.ctx_sens "['call_string_withCallee']" --enable ana.int.interval_set --set ana.context.callStack_height -1 - -#include - -int a = 20; - -int f(int i) -{ - if (i > 0) - { - a = --i; - f(i); - } - return 0; -} - -int main(void) -{ - f(25); - __goblint_check(a == 0); -} From 12fab368de7a40f4d01c6257dfdc929e9b83ef5c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 15 Apr 2024 02:18:50 +0200 Subject: [PATCH 122/128] update comments on constraints and loopfreeCallstring --- src/analyses/loopfreeCallstring.ml | 25 +++++++++++++++---------- src/framework/constraints.ml | 14 ++++++++------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index a83de1ea89..0751e4e809 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -1,8 +1,13 @@ -(** This approach is inspired by - @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. - The idea is to improve the call string appraoch, by representing all detected loops of the call stack in a set +(** + Loopfree Callstring analysis [loopfree_callstring] that reduces the call string length of the classical Call String approach for recursions + The idea is to improve the Call String analysis by representing all detected call cycle of the call string in a set + In case no call cycle apprears, the call string is identical to the call string of the Call String approach + For example: + - call string [main, a, b, c, a] is represented as [main, {a, b, c}] + - call string [main, a, a, b, b, b] is represented as [main, {a}, {b}] + + This approach is inspired by @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. *) - open Analyses module Spec : MCPSpec = @@ -14,7 +19,7 @@ struct module FundecSet = SetDomain.Make (CilType.Fundec) module Either = Printable.Either (CilType.Fundec) (FundecSet) - module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a list of Fundecs and Sets of Fundecs. Lattice.Flat is used to fulfill the type *) + module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a List containing Sets of Fundecs and Fundecs. Lattice.Flat is used to fulfill the type *) module C = D module V = EmptyV module G = Lattice.Unit @@ -23,10 +28,10 @@ struct let get_list list = match list with | `Lifted e -> e - | _ -> failwith "Error loopfreeCallstring (get_list): D should represent a call stack not `Top or `Bottom!" + | _ -> failwith "Error loopfreeCallstring (get_list): The list cannot be derived from Top or Bottom!" let loop_detected f = function - (* a call stack contains each function at most once *) + (* note: a call string contains each Fundec at most once *) | `Left ele -> CilType.Fundec.equal f ele | `Right set -> FundecSet.mem f set @@ -35,11 +40,11 @@ struct | `Right set -> FundecSet.join old set let rec callee_state f prev_set prev_list = function - | [] -> (`Left f)::(List.rev prev_list) (* f is not yet contained in the call stack*) + | [] -> (`Left f)::(List.rev prev_list) (* f is not yet contained in the call string *) | e::rem_list -> let new_set = add_to_set prev_set e in - if loop_detected f e (* f is already present in the call stack *) - then (`Right new_set)::rem_list (* combine all elements of the loop in a set *) + if loop_detected f e (* f is already present in the call string *) + then (`Right new_set)::rem_list (* combine all elements of the call cycle in a set *) else callee_state f new_set (e::prev_list) rem_list let callee_state f ctx = `Lifted(callee_state f (FundecSet.empty ()) [] (get_list ctx.local)) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a7338b483d..42232d2db1 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -504,8 +504,8 @@ struct let names x = Format.asprintf "%d" x end -(** Lifts a [Spec] with the context gas variable. For every function call the gas is reduced. - If the gas is zero, the remaining function calls are analyzed without context-information *) +(** Lifts a [Spec] with the context gas variable. The gas variable limits the number of context-sensitively function calls in a call stack. + For every function call the gas is reduced. If the gas is zero, the remaining function calls are analyzed without context-information *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) and module C = Printable.Option (S.C) (NoContext) @@ -520,7 +520,7 @@ struct let printXml f (x,y) = BatPrintf.fprintf f "\n\n\n%s\n\n%a\nContext Gas Value\n\n%a\n\n" (XmlUtil.escape (Base1.name ())) Base1.printXml x Base2.printXml y end - module D = Context_Gas_Prod (S.D) (Lattice.Chain (IntConf)) + module D = Context_Gas_Prod (S.D) (Lattice.Chain (IntConf)) (* Product of S.D and an integer tracking the context gas value *) module C = Printable.Option (S.C) (NoContext) module G = S.G module V = S.V @@ -530,7 +530,7 @@ struct let of_elt (x, _) = of_elt x end - (* returns value of the given ctx *) + (* returns context gas value of the given ctx *) let cg_val ctx = snd ctx.local type marshal = S.marshal @@ -539,10 +539,11 @@ struct let name () = S.name ()^" with context gas" let startstate v = S.startstate v, get_int "ana.context.gas_value" - let exitstate v = S.exitstate v, get_int "ana.context.gas_value" (* TODO: probably doesn't matter*) + let exitstate v = S.exitstate v, get_int "ana.context.gas_value" let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = + (* only keep context if the context gas is not zero *) if i <= 0 then None else Some (S.context fd d) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = @@ -555,7 +556,8 @@ struct ; context = (fun () -> Option.get (ctx.context ()))} let enter ctx r f args = - let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in (* callee gas = caller gas - 1 *) + (* callee gas = caller gas - 1 *) + let liftmap_tup = List.map (fun (x,y) -> (x, cg_val ctx), (y, max 0 (cg_val ctx - 1))) in liftmap_tup (S.enter (conv ctx) r f args) let threadenter ctx ~multiple lval f args = From 52a507b6d23e556ccd729cec0d08aaa1b2e6eac8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 15 Apr 2024 21:41:46 +0200 Subject: [PATCH 123/128] updated comments, updated tests --- src/analyses/mCP.ml | 17 +++++------ src/framework/constraints.ml | 6 ++-- .../01-basic_tests_bound_sens.c | 6 ++-- .../80-context_gas/02-basic_tests_bound_ins.c | 5 ++-- .../80-context_gas/03-contextGas0.c | 1 + .../80-context_gas/04-contextGasNeg.c | 3 +- .../80-context_gas/05-circle_call_sens.c | 4 +-- .../80-context_gas/06-circle_call_ins.c | 1 - .../80-context_gas/07-main_recursion_sens.c | 20 ++----------- .../80-context_gas/08-main_recursion_ins.c | 2 +- .../80-context_gas/09-endless_loop.c | 2 +- .../80-context_gas/10-thread_handling_sens.c | 28 ++++++------------- .../80-context_gas/11-thread_handling_ins.c | 5 +++- .../12-multiple_function_chain_sens.c | 5 +++- .../13-multiple_function_chain_ins.c | 5 +++- .../regression/80-context_gas/14-ackermann.c | 2 +- .../80-context_gas/15-compl_loop_unrolling.c | 1 - .../80-context_gas/16-loop_unrolling_sens.c | 6 ++-- .../80-context_gas/17-loop_unrolling_ins.c | 2 +- .../18-loop_unrolling_big_loop.c | 3 +- .../80-context_gas/19-value_update_sens.c | 1 - .../80-context_gas/20-value_update_ins.c | 1 - .../01-loop_calling_sens.c | 2 +- .../02-loop_calling_ins.c | 2 +- .../81-loopfree_callstring/03-ackermann.c | 2 +- .../81-loopfree_callstring/04-endless_loop.c | 4 +-- .../05-multiple_calls_base_sens.c | 3 +- .../06-multiple_calls_sens.c | 3 +- .../07-multiple_calls_ins.c | 3 +- .../08-new_calling_set.c | 3 +- .../09-many_nested_loops.c | 3 +- .../81-loopfree_callstring/10-nested_loops.c | 3 +- .../11-value_update_sens.c | 3 +- .../12-value_update_ins.c | 3 +- .../13-circle_call_and_big_loop.c | 2 +- .../14-loop_unrolling.c | 2 +- .../81-loopfree_callstring/15-threads_sens.c | 3 +- .../81-loopfree_callstring/16-threads_ins.c | 3 +- .../01-multiple_tests_h5sens_cs.c | 2 +- .../02-multiple_tests_h5ins_cs.c | 2 +- .../03-multiple_tests_h2sens_cs.c | 2 +- .../82-callstring/04-endless_loop_cs.c | 4 +-- .../82-callstring/05-ackermann_cs.c | 2 +- .../regression/82-callstring/06-big_loop_cs.c | 2 +- .../82-callstring/07-loop_unrolling_cs.c | 2 +- .../82-callstring/08-threads_sens_cs.c | 2 +- .../82-callstring/09-threads_ins_cs.c | 2 +- .../82-callstring/10-inf_callstack_cs.c | 2 +- .../11-multiple_tests_h5sens_csi.c | 2 +- .../12-multiple_tests_h5ins_csi.c | 2 +- .../13-multiple_tests_h2sens_csi.c | 2 +- .../82-callstring/14-endless_loop_csi.c | 4 +-- .../82-callstring/15-ackermann_csi.c | 2 +- .../82-callstring/16-big_loop_csi.c | 2 +- .../82-callstring/17-loop_unrolling_csi.c | 2 +- .../82-callstring/18-threads_sens_csi.c | 2 +- .../82-callstring/19-threads_ins_csi.c | 2 +- .../82-callstring/20-inf_callstack_csi.c | 2 +- 58 files changed, 90 insertions(+), 124 deletions(-) diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 73579442b4..1ead43e7d8 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -36,7 +36,7 @@ struct let name () = "MCP2" let path_sens = ref [] - let cont_sens_ids = ref Set.empty + let act_cont_sens = ref Set.empty let base_id = ref (-1) @@ -65,6 +65,7 @@ struct let deps (x,_) = iter (check_dep x) @@ (find_spec x).dep in iter deps xs + type marshal = Obj.t list let init marshal = let map' f = @@ -90,7 +91,7 @@ struct let cont_sens = map' find_id @@ sens in activated_ctx_sens := List.filter (fun (n, _) -> List.mem n cont_sens) !activated; end; - cont_sens_ids := Set.of_list (List.map (fun (n,p) -> n) !activated_ctx_sens); + act_cont_sens := Set.of_list (List.map (fun (n,p) -> n) !activated_ctx_sens); activated_path_sens := List.filter (fun (n, _) -> List.mem n !path_sens) !activated; match marshal with | Some marshal -> @@ -115,7 +116,7 @@ struct let context fd x = let x = spec_list x in filter_map (fun (n,(module S:MCPSpec),d) -> - if Set.is_empty !cont_sens_ids || not (Set.mem n !cont_sens_ids) then (*n is insensitive*) + if Set.is_empty !act_cont_sens || not (Set.mem n !act_cont_sens) then (*n is insensitive*) None else Some (n, repr @@ S.context fd (obj d)) @@ -187,13 +188,13 @@ struct let octx = ctx in let ctx_with_local ctx local' = (* let rec ctx' = - { ctx with + { ctx with local = local'; ask = ask - } - and ask q = query ctx' q - in - ctx' *) + } + and ask q = query ctx' q + in + ctx' *) {ctx with local = local'} in let do_emit ctx = function diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 42232d2db1..1f2bf29f51 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -504,7 +504,7 @@ struct let names x = Format.asprintf "%d" x end -(** Lifts a [Spec] with the context gas variable. The gas variable limits the number of context-sensitively function calls in a call stack. +(** Lifts a [Spec] with the context gas variable. The gas variable limits the number of context-sensitively analyzed function calls in a call stack. For every function call the gas is reduced. If the gas is zero, the remaining function calls are analyzed without context-information *) module ContextGasLifter (S:Spec) : Spec with module D = Lattice.Prod (S.D) (Lattice.Chain (IntConf)) @@ -520,7 +520,7 @@ struct let printXml f (x,y) = BatPrintf.fprintf f "\n\n\n%s\n\n%a\nContext Gas Value\n\n%a\n\n" (XmlUtil.escape (Base1.name ())) Base1.printXml x Base2.printXml y end - module D = Context_Gas_Prod (S.D) (Lattice.Chain (IntConf)) (* Product of S.D and an integer tracking the context gas value *) + module D = Context_Gas_Prod (S.D) (Lattice.Chain (IntConf)) (* Product of S.D and an integer, tracking the context gas value *) module C = Printable.Option (S.C) (NoContext) module G = S.G module V = S.V @@ -543,7 +543,7 @@ struct let morphstate v (d,i) = S.morphstate v d, i let context fd (d,i) = - (* only keep context if the context gas is not zero *) + (* only keep context if the context gas is greater zero *) if i <= 0 then None else Some (S.context fd d) let conv (ctx:(D.t,G.t,C.t,V.t) ctx): (S.D.t,G.t,S.C.t,V.t)ctx = diff --git a/tests/regression/80-context_gas/01-basic_tests_bound_sens.c b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c index 03f5c78b53..409d86e1c2 100644 --- a/tests/regression/80-context_gas/01-basic_tests_bound_sens.c +++ b/tests/regression/80-context_gas/01-basic_tests_bound_sens.c @@ -1,6 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Basic examples - int f(int x, int y) { if (x == 0) @@ -12,5 +10,7 @@ int f(int x, int y) int main() { - __goblint_check(f(8, 8) == 0); // boundary (included) + // main -> f(8,8) -> f(7,7) -> g(6,6) -> f(5,5) -> f(4,4) -> f(3,3) -> f(2,2) -> f(1,1) -> f(0,0) -> return 0 + // 10 functions -> boundary (included) + __goblint_check(f(8, 8) == 0); } \ No newline at end of file diff --git a/tests/regression/80-context_gas/02-basic_tests_bound_ins.c b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c index 25b8ec34ad..95a110264b 100644 --- a/tests/regression/80-context_gas/02-basic_tests_bound_ins.c +++ b/tests/regression/80-context_gas/02-basic_tests_bound_ins.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Basic examples int f(int x, int y) { @@ -12,5 +11,7 @@ int f(int x, int y) int main() { - __goblint_check(f(9, 9) == 0); // UNKNOWN //boundary (excluded) + // main -> f(9,9) -> f(8,8) -> f(7,7) -> g(6,6) -> f(5,5) -> f(4,4) -> f(3,3) -> f(2,2) -> f(1,1) -> f(0,0) -> return 0 + // 11 functions -> boundary (excluded) + __goblint_check(f(9, 9) == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/03-contextGas0.c b/tests/regression/80-context_gas/03-contextGas0.c index daf60d2e60..d1dd99ca14 100644 --- a/tests/regression/80-context_gas/03-contextGas0.c +++ b/tests/regression/80-context_gas/03-contextGas0.c @@ -11,5 +11,6 @@ int f(int x, int y) int main() { + // is analyzed context-insensitive __goblint_check(f(1000, 1000) == 0); // UNKNOWN } \ No newline at end of file diff --git a/tests/regression/80-context_gas/04-contextGasNeg.c b/tests/regression/80-context_gas/04-contextGasNeg.c index 500228eb4c..5ee332eb9b 100644 --- a/tests/regression/80-context_gas/04-contextGasNeg.c +++ b/tests/regression/80-context_gas/04-contextGasNeg.c @@ -11,5 +11,6 @@ int f(int x, int y) int main() { - __goblint_check(f(20, 20) == 0); // is analyzed fully context sensitive + // Context Gas lifter is disabled -> fully context-sensitive + __goblint_check(f(20, 20) == 0); } \ No newline at end of file diff --git a/tests/regression/80-context_gas/05-circle_call_sens.c b/tests/regression/80-context_gas/05-circle_call_sens.c index 4cafc5bff0..1e0b4cc4d0 100644 --- a/tests/regression/80-context_gas/05-circle_call_sens.c +++ b/tests/regression/80-context_gas/05-circle_call_sens.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 15 -// Checks if recursion in loops is handled properly #include int f(int i); @@ -34,8 +33,7 @@ int main(void) { __goblint_check(f(0) == 2); __goblint_check(f(7) == 101); - // f(9) -> g(7) -> f(8) -> g(6) -> f(7) -> g(5) -> f(6) -> g(4) -> f(5) -> g(3) -> f(4) -> g(2) -> f(3) -> g(1) -> f(2) -> g(0) -> return - // f(9) -> g(6) -> f(7) -> g(4) -> f(5) -> g(2) -> f(3) -> g(0) + __goblint_check(f(9) == 265); __goblint_check(f(10) == 429); diff --git a/tests/regression/80-context_gas/06-circle_call_ins.c b/tests/regression/80-context_gas/06-circle_call_ins.c index f10ca6b6f7..c684b37235 100644 --- a/tests/regression/80-context_gas/06-circle_call_ins.c +++ b/tests/regression/80-context_gas/06-circle_call_ins.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 15 -// Checks if recursion in loops is handled properly #include int f(int i); diff --git a/tests/regression/80-context_gas/07-main_recursion_sens.c b/tests/regression/80-context_gas/07-main_recursion_sens.c index b538413700..43998e458a 100644 --- a/tests/regression/80-context_gas/07-main_recursion_sens.c +++ b/tests/regression/80-context_gas/07-main_recursion_sens.c @@ -1,24 +1,8 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Checks if only recursion in main works properly + boundary check -// TODO +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include -int num_iterat = 11; // WHY is context gas value + 1 the limit??? - -/* -main mit 11: 10 -> 9 -main mit 10: 9 -> 8 -main mit 9: 8 -> 7 -main mit 8: 7 -> 6 -main mit 7: 6 -> 5 -main mit 6: 5 -> 4 -main mit 5: 4 -> 3 -main mit 4: 3 -> 2 -main mit 3: 2 -> 1 -main mit 2: 1 -> 0 -main mit 1: 0 -> 0 -main mit 0: 0 -> 0 -*/ +int num_iterat = 11; int main(void) { diff --git a/tests/regression/80-context_gas/08-main_recursion_ins.c b/tests/regression/80-context_gas/08-main_recursion_ins.c index 825e5b0f4a..4e435669c7 100644 --- a/tests/regression/80-context_gas/08-main_recursion_ins.c +++ b/tests/regression/80-context_gas/08-main_recursion_ins.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Without context insensitive analysis: Stack Overflow +// Without context-insensitive analysis: Stack Overflow #include int num_iterat = 200000; diff --git a/tests/regression/80-context_gas/09-endless_loop.c b/tests/regression/80-context_gas/09-endless_loop.c index bf6e9052fd..73582e7571 100644 --- a/tests/regression/80-context_gas/09-endless_loop.c +++ b/tests/regression/80-context_gas/09-endless_loop.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Will result in an endless loop without context insensitive analysis +// Without context-insensitive analysis: endless loop #include int num_iterat = 2; diff --git a/tests/regression/80-context_gas/10-thread_handling_sens.c b/tests/regression/80-context_gas/10-thread_handling_sens.c index 533d27c0a1..14feb6915b 100644 --- a/tests/regression/80-context_gas/10-thread_handling_sens.c +++ b/tests/regression/80-context_gas/10-thread_handling_sens.c @@ -1,4 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include #include @@ -12,6 +13,7 @@ int f(int i) { return f(i - 1); } + return 11; } int g(int i) @@ -24,6 +26,7 @@ int g(int i) { return g(i - 1); } + return 12; } int h(int i) @@ -36,6 +39,7 @@ int h(int i) { return g(i - 1); } + return 13; } int procedure(int num_iterat) @@ -49,33 +53,17 @@ int procedure(int num_iterat) void *t_sens(void *arg) { - int result = procedure(0); - __goblint_check(result == 9); - - result = procedure(6); - __goblint_check(result == 7); - return NULL; -} - -void *t_sens2(void *arg) -{ - int result = procedure(1); - __goblint_check(result == 7); - - result = procedure(8); - __goblint_check(result == 7); + // main -> t_sens2 -> procedure -> f(8) -> ... -> f(0) + // main -> t_sens2 -> procedure -> g(8) -> ... -> g(0) + // main -> t_sens2 -> procedure -> h(8) -> g(7) -> ... -> g(0) + __goblint_check(procedure(8) == 7); return NULL; } int main() { pthread_t id; - pthread_t id2; - // Create the thread pthread_create(&id, NULL, t_sens, NULL); - - // Create the thread - pthread_create(&id2, NULL, t_sens2, NULL); return 0; } diff --git a/tests/regression/80-context_gas/11-thread_handling_ins.c b/tests/regression/80-context_gas/11-thread_handling_ins.c index 157fb282f4..1e08f88e80 100644 --- a/tests/regression/80-context_gas/11-thread_handling_ins.c +++ b/tests/regression/80-context_gas/11-thread_handling_ins.c @@ -1,4 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include #include @@ -12,6 +13,7 @@ int f(int i) { return f(i - 1); } + return 11; } int g(int i) @@ -24,6 +26,7 @@ int g(int i) { return g(i - 1); } + return 12; } int h(int i) @@ -36,6 +39,7 @@ int h(int i) { return g(i - 1); } + return 13; } int procedure(int num_iterat) @@ -61,7 +65,6 @@ int main() { pthread_t id; - // Create the thread pthread_create(&id, NULL, t_insens, NULL); return 0; } diff --git a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c index 106f5b73a2..98ae35ce03 100644 --- a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c +++ b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Tests multiple recursive function calls +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include int h(int i) @@ -12,6 +12,7 @@ int h(int i) { return h(i - 1); } + return 13; } int g(int i) @@ -24,6 +25,7 @@ int g(int i) { return h(i - 1); } + return 12; } int f(int i) @@ -36,6 +38,7 @@ int f(int i) { return g(i - 1); } + return 11; } int main(void) diff --git a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c index 65896f1b06..c677636db9 100644 --- a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c +++ b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Tests multiple recursive function calls +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include int h(int i) @@ -12,6 +12,7 @@ int h(int i) { return h(i - 1); } + return 13; } int g(int i) @@ -24,6 +25,7 @@ int g(int i) { return h(i - 1); } + return 12; } int f(int i) @@ -36,6 +38,7 @@ int f(int i) { return g(i - 1); } + return 11; } int main(void) diff --git a/tests/regression/80-context_gas/14-ackermann.c b/tests/regression/80-context_gas/14-ackermann.c index 6c725d54fa..1b80296bad 100644 --- a/tests/regression/80-context_gas/14-ackermann.c +++ b/tests/regression/80-context_gas/14-ackermann.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// This code would result in a StackOverflow if it is analyses fully context sensitive +// Without context-insensitive analysis: Stack Overflow #include int ack(int n, int m) diff --git a/tests/regression/80-context_gas/15-compl_loop_unrolling.c b/tests/regression/80-context_gas/15-compl_loop_unrolling.c index a28b9dcf26..05556276c8 100644 --- a/tests/regression/80-context_gas/15-compl_loop_unrolling.c +++ b/tests/regression/80-context_gas/15-compl_loop_unrolling.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// TODO #include int f(int i) diff --git a/tests/regression/80-context_gas/16-loop_unrolling_sens.c b/tests/regression/80-context_gas/16-loop_unrolling_sens.c index 93a4d01409..a4d4f7cc11 100644 --- a/tests/regression/80-context_gas/16-loop_unrolling_sens.c +++ b/tests/regression/80-context_gas/16-loop_unrolling_sens.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// TODO +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include int f(int i) @@ -20,7 +20,7 @@ int main(void) int res1 = 0; int res2 = 0; - // context sensitive analysis + // context-sensitive analysis for (int i = 5; i > 0; i--) { res1 = f(3); @@ -28,6 +28,4 @@ int main(void) __goblint_check(res1 == 11); __goblint_check(res2 == 11); } - __goblint_check(res1 == 11); - __goblint_check(res2 == 11); } diff --git a/tests/regression/80-context_gas/17-loop_unrolling_ins.c b/tests/regression/80-context_gas/17-loop_unrolling_ins.c index 5c702f43f7..70b327679a 100644 --- a/tests/regression/80-context_gas/17-loop_unrolling_ins.c +++ b/tests/regression/80-context_gas/17-loop_unrolling_ins.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// TODO +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include int f(int i) diff --git a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c index 1d95444a71..0b9713549d 100644 --- a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c +++ b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c @@ -1,5 +1,5 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// TODO +// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value #include int f(int i) @@ -17,7 +17,6 @@ int f(int i) int main(void) { - // high number of iterations for (int i = 500; i > 0; i--) { __goblint_check(f(i) == 11); // UNKNOWN diff --git a/tests/regression/80-context_gas/19-value_update_sens.c b/tests/regression/80-context_gas/19-value_update_sens.c index bddedb9737..7beec9d5d3 100644 --- a/tests/regression/80-context_gas/19-value_update_sens.c +++ b/tests/regression/80-context_gas/19-value_update_sens.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Basic example #include int a = 20; diff --git a/tests/regression/80-context_gas/20-value_update_ins.c b/tests/regression/80-context_gas/20-value_update_ins.c index 5435b0ea71..89a99e2529 100644 --- a/tests/regression/80-context_gas/20-value_update_ins.c +++ b/tests/regression/80-context_gas/20-value_update_ins.c @@ -1,5 +1,4 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Basic example #include int a = 20; diff --git a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c index 2b88d06c6d..6ad12ec7c8 100644 --- a/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c +++ b/tests/regression/81-loopfree_callstring/01-loop_calling_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set int f(int i); diff --git a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c index 96fb2fcc31..0d755f0a1c 100644 --- a/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c +++ b/tests/regression/81-loopfree_callstring/02-loop_calling_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Basic example #include diff --git a/tests/regression/81-loopfree_callstring/03-ackermann.c b/tests/regression/81-loopfree_callstring/03-ackermann.c index 52a55ae673..0e30943b6c 100644 --- a/tests/regression/81-loopfree_callstring/03-ackermann.c +++ b/tests/regression/81-loopfree_callstring/03-ackermann.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int ack(int n, int m) diff --git a/tests/regression/81-loopfree_callstring/04-endless_loop.c b/tests/regression/81-loopfree_callstring/04-endless_loop.c index 940d0d3a82..de62873a0f 100644 --- a/tests/regression/81-loopfree_callstring/04-endless_loop.c +++ b/tests/regression/81-loopfree_callstring/04-endless_loop.c @@ -1,5 +1,5 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Will result in an endless loop without context insensitive analysis +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// Without context-insensitive analysis: endless loop #include int num_iterat = 2; diff --git a/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c index a21df3d2b9..d34ef7876e 100644 --- a/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c +++ b/tests/regression/81-loopfree_callstring/05-multiple_calls_base_sens.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int f(int i) diff --git a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c index 3caa345108..4b689ca6a7 100644 --- a/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c +++ b/tests/regression/81-loopfree_callstring/06-multiple_calls_sens.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int f(int i) diff --git a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c index 0650f78418..73ac67b772 100644 --- a/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c +++ b/tests/regression/81-loopfree_callstring/07-multiple_calls_ins.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int f(int i) diff --git a/tests/regression/81-loopfree_callstring/08-new_calling_set.c b/tests/regression/81-loopfree_callstring/08-new_calling_set.c index bcb74d9799..9d3508de69 100644 --- a/tests/regression/81-loopfree_callstring/08-new_calling_set.c +++ b/tests/regression/81-loopfree_callstring/08-new_calling_set.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int f(int i) diff --git a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c index 9db0786268..51797bc946 100644 --- a/tests/regression/81-loopfree_callstring/09-many_nested_loops.c +++ b/tests/regression/81-loopfree_callstring/09-many_nested_loops.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int g(int i); diff --git a/tests/regression/81-loopfree_callstring/10-nested_loops.c b/tests/regression/81-loopfree_callstring/10-nested_loops.c index 7f7ef43dd4..5ba0a2fe1f 100644 --- a/tests/regression/81-loopfree_callstring/10-nested_loops.c +++ b/tests/regression/81-loopfree_callstring/10-nested_loops.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int h(int i) diff --git a/tests/regression/81-loopfree_callstring/11-value_update_sens.c b/tests/regression/81-loopfree_callstring/11-value_update_sens.c index c926a5c5a9..412bccf6ac 100644 --- a/tests/regression/81-loopfree_callstring/11-value_update_sens.c +++ b/tests/regression/81-loopfree_callstring/11-value_update_sens.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int a = 20; diff --git a/tests/regression/81-loopfree_callstring/12-value_update_ins.c b/tests/regression/81-loopfree_callstring/12-value_update_ins.c index fe5fd7ff2c..c7046867d5 100644 --- a/tests/regression/81-loopfree_callstring/12-value_update_ins.c +++ b/tests/regression/81-loopfree_callstring/12-value_update_ins.c @@ -1,5 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set -// Basic example +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include int a = 20; diff --git a/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c index 9da8f652da..4f2b8ac33f 100644 --- a/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c +++ b/tests/regression/81-loopfree_callstring/13-circle_call_and_big_loop.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed #include diff --git a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c index d422672f88..40a534fd55 100644 --- a/tests/regression/81-loopfree_callstring/14-loop_unrolling.c +++ b/tests/regression/81-loopfree_callstring/14-loop_unrolling.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set --set exp.unrolling-factor 3 +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set --set exp.unrolling-factor 3 #include diff --git a/tests/regression/81-loopfree_callstring/15-threads_sens.c b/tests/regression/81-loopfree_callstring/15-threads_sens.c index 66e7453125..0ca7dce02c 100644 --- a/tests/regression/81-loopfree_callstring/15-threads_sens.c +++ b/tests/regression/81-loopfree_callstring/15-threads_sens.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include #include #include @@ -77,7 +77,6 @@ int main() pthread_t id; pthread_t id2; - // Create the thread pthread_create(&id, NULL, t_sens, NULL); pthread_create(&id2, NULL, t_sens2, NULL); return 0; diff --git a/tests/regression/81-loopfree_callstring/16-threads_ins.c b/tests/regression/81-loopfree_callstring/16-threads_ins.c index 1593b6571e..bd4836ed81 100644 --- a/tests/regression/81-loopfree_callstring/16-threads_ins.c +++ b/tests/regression/81-loopfree_callstring/16-threads_ins.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set +// PARAM: --set "ana.activated[+]" loopfree_callstring --set ana.ctx_sens "['loopfree_callstring']" --enable ana.int.interval_set #include #include #include @@ -65,7 +65,6 @@ int main() { pthread_t id; - // Create the thread pthread_create(&id, NULL, t_ins, NULL); return 0; } diff --git a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c index 22e682bb3b..6f7aebc360 100644 --- a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c +++ b/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c index f28abe0e99..6881b2c58c 100644 --- a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c +++ b/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c index 51e5bdf16d..b8e7bbaf32 100644 --- a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c +++ b/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/04-endless_loop_cs.c b/tests/regression/82-callstring/04-endless_loop_cs.c index 0d0b2c0612..3804b29f97 100644 --- a/tests/regression/82-callstring/04-endless_loop_cs.c +++ b/tests/regression/82-callstring/04-endless_loop_cs.c @@ -1,5 +1,5 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set -// Will result in an endless loop without context insensitive analysis +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// Without context-insensitive analysis: endless loop int num_iterat = 2; diff --git a/tests/regression/82-callstring/05-ackermann_cs.c b/tests/regression/82-callstring/05-ackermann_cs.c index c6340a9dbb..746c221038 100644 --- a/tests/regression/82-callstring/05-ackermann_cs.c +++ b/tests/regression/82-callstring/05-ackermann_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/06-big_loop_cs.c b/tests/regression/82-callstring/06-big_loop_cs.c index e9ba61f324..2a6ce1c0ed 100644 --- a/tests/regression/82-callstring/06-big_loop_cs.c +++ b/tests/regression/82-callstring/06-big_loop_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/07-loop_unrolling_cs.c b/tests/regression/82-callstring/07-loop_unrolling_cs.c index cdbd6d49bb..8435de3060 100644 --- a/tests/regression/82-callstring/07-loop_unrolling_cs.c +++ b/tests/regression/82-callstring/07-loop_unrolling_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/08-threads_sens_cs.c b/tests/regression/82-callstring/08-threads_sens_cs.c index 3f046efad5..e892ac75ce 100644 --- a/tests/regression/82-callstring/08-threads_sens_cs.c +++ b/tests/regression/82-callstring/08-threads_sens_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/09-threads_ins_cs.c b/tests/regression/82-callstring/09-threads_ins_cs.c index d61954c767..1969a73cc7 100644 --- a/tests/regression/82-callstring/09-threads_ins_cs.c +++ b/tests/regression/82-callstring/09-threads_ins_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/10-inf_callstack_cs.c b/tests/regression/82-callstring/10-inf_callstack_cs.c index c52e1d0bb5..af1e2b24c1 100644 --- a/tests/regression/82-callstring/10-inf_callstack_cs.c +++ b/tests/regression/82-callstring/10-inf_callstack_cs.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set ana.context.callString_length -1 +// PARAM: --set "ana.activated[+]" call_string --set ana.ctx_sens "['call_string']" --enable ana.int.interval_set --set ana.context.callString_length -1 #include diff --git a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c index 1d6cb73dcc..9195472104 100644 --- a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c +++ b/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c index 815aaba148..2d62ce75b3 100644 --- a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c +++ b/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 5 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c index e4a085b7d7..e350706355 100644 --- a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c +++ b/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Test 1: int a(int i) diff --git a/tests/regression/82-callstring/14-endless_loop_csi.c b/tests/regression/82-callstring/14-endless_loop_csi.c index fd19e6a578..55637bed10 100644 --- a/tests/regression/82-callstring/14-endless_loop_csi.c +++ b/tests/regression/82-callstring/14-endless_loop_csi.c @@ -1,5 +1,5 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set -// Will result in an endless loop without context insensitive analysis +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// Without context-insensitive analysis: endless loop int num_iterat = 2; diff --git a/tests/regression/82-callstring/15-ackermann_csi.c b/tests/regression/82-callstring/15-ackermann_csi.c index f37de2d357..6ddf7fbea3 100644 --- a/tests/regression/82-callstring/15-ackermann_csi.c +++ b/tests/regression/82-callstring/15-ackermann_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set int ack(int n, int m) { diff --git a/tests/regression/82-callstring/16-big_loop_csi.c b/tests/regression/82-callstring/16-big_loop_csi.c index 7a993cfc5c..6a7f9afef7 100644 --- a/tests/regression/82-callstring/16-big_loop_csi.c +++ b/tests/regression/82-callstring/16-big_loop_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set // Checks proper handling of recursions in loops + shows that not all 200 iterations are analyzed int f(int i); diff --git a/tests/regression/82-callstring/17-loop_unrolling_csi.c b/tests/regression/82-callstring/17-loop_unrolling_csi.c index 2b37ad2af2..5f411a0c18 100644 --- a/tests/regression/82-callstring/17-loop_unrolling_csi.c +++ b/tests/regression/82-callstring/17-loop_unrolling_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set exp.unrolling-factor 2 +// PARAM: --set ana.context.callString_length 2 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set exp.unrolling-factor 2 int f(int i) { diff --git a/tests/regression/82-callstring/18-threads_sens_csi.c b/tests/regression/82-callstring/18-threads_sens_csi.c index 58b39addc6..cb889af1ed 100644 --- a/tests/regression/82-callstring/18-threads_sens_csi.c +++ b/tests/regression/82-callstring/18-threads_sens_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include diff --git a/tests/regression/82-callstring/19-threads_ins_csi.c b/tests/regression/82-callstring/19-threads_ins_csi.c index 51850988a9..bd93b5aac7 100644 --- a/tests/regression/82-callstring/19-threads_ins_csi.c +++ b/tests/regression/82-callstring/19-threads_ins_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set +// PARAM: --set ana.context.callString_length 10 --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set #include #include #include diff --git a/tests/regression/82-callstring/20-inf_callstack_csi.c b/tests/regression/82-callstring/20-inf_callstack_csi.c index 6007ab9b85..361211f4ce 100644 --- a/tests/regression/82-callstring/20-inf_callstack_csi.c +++ b/tests/regression/82-callstring/20-inf_callstack_csi.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set ana.context.callString_length -1 +// PARAM: --set "ana.activated[+]" call_site --set ana.ctx_sens "['call_site']" --enable ana.int.interval_set --set ana.context.callString_length -1 #include From af12e584d384a321aea385f3f6f1342139f1f21c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 15 Apr 2024 21:54:30 +0200 Subject: [PATCH 124/128] commit to make the indentation test pass... --- src/analyses/callstring.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/callstring.ml b/src/analyses/callstring.ml index ee3a1d8cd0..9ca103a85e 100644 --- a/src/analyses/callstring.ml +++ b/src/analyses/callstring.ml @@ -91,4 +91,4 @@ let _ = MCP.register_analysis (module Spec (Callstring) : MCPSpec); (* [call_string] *) (* call site approach *) - MCP.register_analysis (module Spec (Callsite) : MCPSpec); (* [call_site] *) \ No newline at end of file + MCP.register_analysis (module Spec (Callsite) : MCPSpec); (* [call_site] *) From d6a390d8dd1bf8b6a7673c9195843341592490ad Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 15 Apr 2024 22:19:07 +0200 Subject: [PATCH 125/128] renumbered call string tests to 79; update comments of tests --- .../01-multiple_tests_h5sens_cs.c | 0 .../02-multiple_tests_h5ins_cs.c | 0 .../03-multiple_tests_h2sens_cs.c | 0 .../{82-callstring => 79-callstring}/04-endless_loop_cs.c | 0 .../{82-callstring => 79-callstring}/05-ackermann_cs.c | 0 .../{82-callstring => 79-callstring}/06-big_loop_cs.c | 0 .../{82-callstring => 79-callstring}/07-loop_unrolling_cs.c | 0 .../{82-callstring => 79-callstring}/08-threads_sens_cs.c | 1 - .../{82-callstring => 79-callstring}/09-threads_ins_cs.c | 1 - .../{82-callstring => 79-callstring}/10-inf_callstack_cs.c | 0 .../11-multiple_tests_h5sens_csi.c | 0 .../12-multiple_tests_h5ins_csi.c | 6 ++---- .../13-multiple_tests_h2sens_csi.c | 0 .../{82-callstring => 79-callstring}/14-endless_loop_csi.c | 1 - .../{82-callstring => 79-callstring}/15-ackermann_csi.c | 1 - .../{82-callstring => 79-callstring}/16-big_loop_csi.c | 0 .../17-loop_unrolling_csi.c | 0 .../{82-callstring => 79-callstring}/18-threads_sens_csi.c | 1 - .../{82-callstring => 79-callstring}/19-threads_ins_csi.c | 1 - .../{82-callstring => 79-callstring}/20-inf_callstack_csi.c | 0 tests/regression/80-context_gas/07-main_recursion_sens.c | 3 ++- tests/regression/80-context_gas/10-thread_handling_sens.c | 3 ++- tests/regression/80-context_gas/11-thread_handling_ins.c | 3 ++- .../80-context_gas/12-multiple_function_chain_sens.c | 3 ++- .../80-context_gas/13-multiple_function_chain_ins.c | 3 ++- tests/regression/80-context_gas/16-loop_unrolling_sens.c | 3 ++- tests/regression/80-context_gas/17-loop_unrolling_ins.c | 3 ++- .../regression/80-context_gas/18-loop_unrolling_big_loop.c | 3 ++- 28 files changed, 18 insertions(+), 18 deletions(-) rename tests/regression/{82-callstring => 79-callstring}/01-multiple_tests_h5sens_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/02-multiple_tests_h5ins_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/03-multiple_tests_h2sens_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/04-endless_loop_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/05-ackermann_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/06-big_loop_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/07-loop_unrolling_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/08-threads_sens_cs.c (98%) rename tests/regression/{82-callstring => 79-callstring}/09-threads_ins_cs.c (98%) rename tests/regression/{82-callstring => 79-callstring}/10-inf_callstack_cs.c (100%) rename tests/regression/{82-callstring => 79-callstring}/11-multiple_tests_h5sens_csi.c (100%) rename tests/regression/{82-callstring => 79-callstring}/12-multiple_tests_h5ins_csi.c (87%) rename tests/regression/{82-callstring => 79-callstring}/13-multiple_tests_h2sens_csi.c (100%) rename tests/regression/{82-callstring => 79-callstring}/14-endless_loop_csi.c (96%) rename tests/regression/{82-callstring => 79-callstring}/15-ackermann_csi.c (95%) rename tests/regression/{82-callstring => 79-callstring}/16-big_loop_csi.c (100%) rename tests/regression/{82-callstring => 79-callstring}/17-loop_unrolling_csi.c (100%) rename tests/regression/{82-callstring => 79-callstring}/18-threads_sens_csi.c (98%) rename tests/regression/{82-callstring => 79-callstring}/19-threads_ins_csi.c (97%) rename tests/regression/{82-callstring => 79-callstring}/20-inf_callstack_csi.c (100%) diff --git a/tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c b/tests/regression/79-callstring/01-multiple_tests_h5sens_cs.c similarity index 100% rename from tests/regression/82-callstring/01-multiple_tests_h5sens_cs.c rename to tests/regression/79-callstring/01-multiple_tests_h5sens_cs.c diff --git a/tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c b/tests/regression/79-callstring/02-multiple_tests_h5ins_cs.c similarity index 100% rename from tests/regression/82-callstring/02-multiple_tests_h5ins_cs.c rename to tests/regression/79-callstring/02-multiple_tests_h5ins_cs.c diff --git a/tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c b/tests/regression/79-callstring/03-multiple_tests_h2sens_cs.c similarity index 100% rename from tests/regression/82-callstring/03-multiple_tests_h2sens_cs.c rename to tests/regression/79-callstring/03-multiple_tests_h2sens_cs.c diff --git a/tests/regression/82-callstring/04-endless_loop_cs.c b/tests/regression/79-callstring/04-endless_loop_cs.c similarity index 100% rename from tests/regression/82-callstring/04-endless_loop_cs.c rename to tests/regression/79-callstring/04-endless_loop_cs.c diff --git a/tests/regression/82-callstring/05-ackermann_cs.c b/tests/regression/79-callstring/05-ackermann_cs.c similarity index 100% rename from tests/regression/82-callstring/05-ackermann_cs.c rename to tests/regression/79-callstring/05-ackermann_cs.c diff --git a/tests/regression/82-callstring/06-big_loop_cs.c b/tests/regression/79-callstring/06-big_loop_cs.c similarity index 100% rename from tests/regression/82-callstring/06-big_loop_cs.c rename to tests/regression/79-callstring/06-big_loop_cs.c diff --git a/tests/regression/82-callstring/07-loop_unrolling_cs.c b/tests/regression/79-callstring/07-loop_unrolling_cs.c similarity index 100% rename from tests/regression/82-callstring/07-loop_unrolling_cs.c rename to tests/regression/79-callstring/07-loop_unrolling_cs.c diff --git a/tests/regression/82-callstring/08-threads_sens_cs.c b/tests/regression/79-callstring/08-threads_sens_cs.c similarity index 98% rename from tests/regression/82-callstring/08-threads_sens_cs.c rename to tests/regression/79-callstring/08-threads_sens_cs.c index e892ac75ce..a30cc7a742 100644 --- a/tests/regression/82-callstring/08-threads_sens_cs.c +++ b/tests/regression/79-callstring/08-threads_sens_cs.c @@ -87,7 +87,6 @@ int main() pthread_t id2; pthread_t id3; - // Create the thread pthread_create(&id, NULL, t_sens, NULL); pthread_create(&id2, NULL, t_sens2, NULL); pthread_create(&id3, NULL, t_sens3, NULL); diff --git a/tests/regression/82-callstring/09-threads_ins_cs.c b/tests/regression/79-callstring/09-threads_ins_cs.c similarity index 98% rename from tests/regression/82-callstring/09-threads_ins_cs.c rename to tests/regression/79-callstring/09-threads_ins_cs.c index 1969a73cc7..37878fee4b 100644 --- a/tests/regression/82-callstring/09-threads_ins_cs.c +++ b/tests/regression/79-callstring/09-threads_ins_cs.c @@ -67,7 +67,6 @@ int main() { pthread_t id; - // Create the thread pthread_create(&id, NULL, t_ins, NULL); return 0; } diff --git a/tests/regression/82-callstring/10-inf_callstack_cs.c b/tests/regression/79-callstring/10-inf_callstack_cs.c similarity index 100% rename from tests/regression/82-callstring/10-inf_callstack_cs.c rename to tests/regression/79-callstring/10-inf_callstack_cs.c diff --git a/tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c b/tests/regression/79-callstring/11-multiple_tests_h5sens_csi.c similarity index 100% rename from tests/regression/82-callstring/11-multiple_tests_h5sens_csi.c rename to tests/regression/79-callstring/11-multiple_tests_h5sens_csi.c diff --git a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c b/tests/regression/79-callstring/12-multiple_tests_h5ins_csi.c similarity index 87% rename from tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c rename to tests/regression/79-callstring/12-multiple_tests_h5ins_csi.c index 2d62ce75b3..ddd79d8079 100644 --- a/tests/regression/82-callstring/12-multiple_tests_h5ins_csi.c +++ b/tests/regression/79-callstring/12-multiple_tests_h5ins_csi.c @@ -114,13 +114,11 @@ int main(void) __goblint_check(e(7) == 6); // UNKNOWN // Test 3: - /* main -> k(10) -> ... -> k(2) -> h(1) -> h(0) -> return 1 - [main, k, k, k, k] and [k, k, k, k, k] (4 times) and [k, k, k, k, h] */ + /* main -> k(10) -> ... -> k(2) -> h(1) -> h(0) -> return 1 */ __goblint_check(k(10) == 2); // UNKNOWN // Test 4: - /* main -> o(6) -> o(5) -> ... o(0) - [main, o, o, o, o] and [o, o, o, o, o] (2 times) */ + /* main -> o(6) -> o(5) -> ... o(0) */ o(6); __goblint_check(m == 0); // UNKNOWN diff --git a/tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c b/tests/regression/79-callstring/13-multiple_tests_h2sens_csi.c similarity index 100% rename from tests/regression/82-callstring/13-multiple_tests_h2sens_csi.c rename to tests/regression/79-callstring/13-multiple_tests_h2sens_csi.c diff --git a/tests/regression/82-callstring/14-endless_loop_csi.c b/tests/regression/79-callstring/14-endless_loop_csi.c similarity index 96% rename from tests/regression/82-callstring/14-endless_loop_csi.c rename to tests/regression/79-callstring/14-endless_loop_csi.c index 55637bed10..440cf1fe85 100644 --- a/tests/regression/82-callstring/14-endless_loop_csi.c +++ b/tests/regression/79-callstring/14-endless_loop_csi.c @@ -4,7 +4,6 @@ int num_iterat = 2; // main -> main -> ... -// [main, main, ...] int main(void) { if (num_iterat > 0) diff --git a/tests/regression/82-callstring/15-ackermann_csi.c b/tests/regression/79-callstring/15-ackermann_csi.c similarity index 95% rename from tests/regression/82-callstring/15-ackermann_csi.c rename to tests/regression/79-callstring/15-ackermann_csi.c index 6ddf7fbea3..22d3d6077f 100644 --- a/tests/regression/82-callstring/15-ackermann_csi.c +++ b/tests/regression/79-callstring/15-ackermann_csi.c @@ -22,7 +22,6 @@ int ack(int n, int m) int main(void) { // main -> ack -> ack -> ... - // [main, ack, ...] ack(4, 1); __goblint_check(1); // reachable } \ No newline at end of file diff --git a/tests/regression/82-callstring/16-big_loop_csi.c b/tests/regression/79-callstring/16-big_loop_csi.c similarity index 100% rename from tests/regression/82-callstring/16-big_loop_csi.c rename to tests/regression/79-callstring/16-big_loop_csi.c diff --git a/tests/regression/82-callstring/17-loop_unrolling_csi.c b/tests/regression/79-callstring/17-loop_unrolling_csi.c similarity index 100% rename from tests/regression/82-callstring/17-loop_unrolling_csi.c rename to tests/regression/79-callstring/17-loop_unrolling_csi.c diff --git a/tests/regression/82-callstring/18-threads_sens_csi.c b/tests/regression/79-callstring/18-threads_sens_csi.c similarity index 98% rename from tests/regression/82-callstring/18-threads_sens_csi.c rename to tests/regression/79-callstring/18-threads_sens_csi.c index cb889af1ed..79f57889f4 100644 --- a/tests/regression/82-callstring/18-threads_sens_csi.c +++ b/tests/regression/79-callstring/18-threads_sens_csi.c @@ -83,7 +83,6 @@ int main() pthread_t id2; pthread_t id3; - // Create the thread pthread_create(&id, NULL, t_sens, NULL); pthread_create(&id2, NULL, t_sens2, NULL); pthread_create(&id3, NULL, t_sens3, NULL); diff --git a/tests/regression/82-callstring/19-threads_ins_csi.c b/tests/regression/79-callstring/19-threads_ins_csi.c similarity index 97% rename from tests/regression/82-callstring/19-threads_ins_csi.c rename to tests/regression/79-callstring/19-threads_ins_csi.c index bd93b5aac7..116d2a2b10 100644 --- a/tests/regression/82-callstring/19-threads_ins_csi.c +++ b/tests/regression/79-callstring/19-threads_ins_csi.c @@ -64,7 +64,6 @@ int main() { pthread_t id; - // Create the thread pthread_create(&id, NULL, t_ins, NULL); return 0; } diff --git a/tests/regression/82-callstring/20-inf_callstack_csi.c b/tests/regression/79-callstring/20-inf_callstack_csi.c similarity index 100% rename from tests/regression/82-callstring/20-inf_callstack_csi.c rename to tests/regression/79-callstring/20-inf_callstack_csi.c diff --git a/tests/regression/80-context_gas/07-main_recursion_sens.c b/tests/regression/80-context_gas/07-main_recursion_sens.c index 43998e458a..2e5327ee22 100644 --- a/tests/regression/80-context_gas/07-main_recursion_sens.c +++ b/tests/regression/80-context_gas/07-main_recursion_sens.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call value #include int num_iterat = 11; diff --git a/tests/regression/80-context_gas/10-thread_handling_sens.c b/tests/regression/80-context_gas/10-thread_handling_sens.c index 14feb6915b..5037dc75ab 100644 --- a/tests/regression/80-context_gas/10-thread_handling_sens.c +++ b/tests/regression/80-context_gas/10-thread_handling_sens.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include #include diff --git a/tests/regression/80-context_gas/11-thread_handling_ins.c b/tests/regression/80-context_gas/11-thread_handling_ins.c index 1e08f88e80..19739d0d34 100644 --- a/tests/regression/80-context_gas/11-thread_handling_ins.c +++ b/tests/regression/80-context_gas/11-thread_handling_ins.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include #include diff --git a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c index 98ae35ce03..c819f427de 100644 --- a/tests/regression/80-context_gas/12-multiple_function_chain_sens.c +++ b/tests/regression/80-context_gas/12-multiple_function_chain_sens.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include int h(int i) diff --git a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c index c677636db9..193895cdd0 100644 --- a/tests/regression/80-context_gas/13-multiple_function_chain_ins.c +++ b/tests/regression/80-context_gas/13-multiple_function_chain_ins.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include int h(int i) diff --git a/tests/regression/80-context_gas/16-loop_unrolling_sens.c b/tests/regression/80-context_gas/16-loop_unrolling_sens.c index a4d4f7cc11..bf89b3ba69 100644 --- a/tests/regression/80-context_gas/16-loop_unrolling_sens.c +++ b/tests/regression/80-context_gas/16-loop_unrolling_sens.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include int f(int i) diff --git a/tests/regression/80-context_gas/17-loop_unrolling_ins.c b/tests/regression/80-context_gas/17-loop_unrolling_ins.c index 70b327679a..bd740f9359 100644 --- a/tests/regression/80-context_gas/17-loop_unrolling_ins.c +++ b/tests/regression/80-context_gas/17-loop_unrolling_ins.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include int f(int i) diff --git a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c index 0b9713549d..ab63a697ad 100644 --- a/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c +++ b/tests/regression/80-context_gas/18-loop_unrolling_big_loop.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 3 --set ana.context.gas_value 10 -// Note: 11 function calls are possible and the analysis is still context-sensitive since the domain tracks the parameter value +// Note: 11 function calls are analyzed context-sensitively +// -> tracked parameter in domain enables one additional context-sensitively analyzed call #include int f(int i) From cefc1e253a6387ab9ccda12a533ad15afd9b1455 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 17 Apr 2024 14:36:01 +0200 Subject: [PATCH 126/128] update description: callString_length is only effective with activated analysis; fixed typo in loopfree callstring comment --- src/analyses/loopfreeCallstring.ml | 2 +- src/config/options.schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 0751e4e809..81b07bce6d 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -1,7 +1,7 @@ (** Loopfree Callstring analysis [loopfree_callstring] that reduces the call string length of the classical Call String approach for recursions The idea is to improve the Call String analysis by representing all detected call cycle of the call string in a set - In case no call cycle apprears, the call string is identical to the call string of the Call String approach + In case no call cycles appears, the call string is identical to the call string of the Call String approach For example: - call string [main, a, b, c, a] is represented as [main, {a, b, c}] - call string [main, a, a, b, b, b] is represented as [main, {a}, {b}] diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 90f6950a97..7bca4f1408 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -986,7 +986,7 @@ }, "callString_length": { "title": "ana.context.callString_length", - "description": "Length of the call string that should be used as context for the Call String analysis. In case the value is zero, the analysis is context-insensitive. For a negative value an infinite call string is used!", + "description": "Length of the call string that should be used as context for the call_string and/or call_site analyses. In case the value is zero, the analysis is context-insensitive. For a negative value, an infinite call string is used! For this option to be effective, one analysis of the `callstring.ml` file must be activated.", "type": "integer", "default": 2 } From 97d5ad249d79b5791365737b1da544e054bc4074 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 18 Apr 2024 17:31:02 +0200 Subject: [PATCH 127/128] Formatting suggestion by Simmo Co-authored-by: Simmo Saan --- src/analyses/loopfreeCallstring.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 81b07bce6d..6fbaf19234 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -6,7 +6,8 @@ - call string [main, a, b, c, a] is represented as [main, {a, b, c}] - call string [main, a, a, b, b, b] is represented as [main, {a}, {b}] - This approach is inspired by @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. + This approach is inspired by + @see Schwarz, M., Saan, S., Seidl, H., Erhard, J., Vojdani, V. Clustered Relational Thread-Modular Abstract Interpretation with Local Traces. Appendix F. *) open Analyses From c1165e189a79aa5bd63385a682178f35e4bb5f0c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 22 Apr 2024 23:18:39 +0200 Subject: [PATCH 128/128] cosmetic changes from Julian (on options, loopfree Callstring and callstring analyses) --- src/analyses/callstring.ml | 6 +++--- src/analyses/loopfreeCallstring.ml | 2 +- src/config/options.schema.json | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/analyses/callstring.ml b/src/analyses/callstring.ml index 9ca103a85e..a8734cdf1c 100644 --- a/src/analyses/callstring.ml +++ b/src/analyses/callstring.ml @@ -35,7 +35,7 @@ struct if get_int "ana.context.callString_length" < 0 then new_callstr (* infinite call string *) else (* maximum of k elements *) - match (BatDeque.size new_callstr - (get_int "ana.context.callString_length")) with + match BatDeque.size new_callstr - (get_int "ana.context.callString_length") with | 1 -> fst @@ Option.get (BatDeque.rear new_callstr) | x when x <= 0 -> new_callstr | _ -> failwith "CallString Error: It shouldn't happen that more than one element must be deleted to maintain the correct height!" @@ -67,7 +67,7 @@ struct end (* implementations of CallstringTypes*) -module Callstring:CallstringType = struct +module Callstring: CallstringType = struct include CilType.Fundec let ana_name = "string" let new_ele f ctx = @@ -77,7 +77,7 @@ module Callstring:CallstringType = struct else Some f' end -module Callsite:CallstringType = struct +module Callsite: CallstringType = struct include CilType.Stmt let ana_name = "site" let new_ele f ctx = diff --git a/src/analyses/loopfreeCallstring.ml b/src/analyses/loopfreeCallstring.ml index 6fbaf19234..172114d37c 100644 --- a/src/analyses/loopfreeCallstring.ml +++ b/src/analyses/loopfreeCallstring.ml @@ -20,7 +20,7 @@ struct module FundecSet = SetDomain.Make (CilType.Fundec) module Either = Printable.Either (CilType.Fundec) (FundecSet) - module D = Lattice.Flat (Printable.Liszt (Either)) (* should be a List containing Sets of Fundecs and Fundecs. Lattice.Flat is used to fulfill the type *) + module D = Lattice.Flat (Printable.Liszt (Either)) (* A domain element is a list containing fundecs and sets of fundecs.*) module C = D module V = EmptyV module G = Lattice.Unit diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 7bca4f1408..99c887ca53 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -356,14 +356,14 @@ }, "ctx_insens": { "title": "ana.ctx_insens", - "description": "List of context-insensitive analyses, which is ignored if `ctx_sens` is not empty.", + "description": "List of context-insensitive analyses. This setting is ignored if `ana.ctx_sens` contains elements.", "type": "array", "items": { "type": "string" }, "default": [ "stack_loc", "stack_trace_set" ] }, "ctx_sens": { "title": "ana.ctx_sens", - "description": "List of context-sensitive analyses. In case of an empty array `ctx_insens` is used, otherwise `ctx_insens` is ignored.", + "description": "List of context-sensitive analyses. In case this list is empty, `ana.ctx_insens` will be used to determine the set of context-insensitive analyses.", "type": "array", "items": { "type": "string" }, "default": [] @@ -980,13 +980,13 @@ }, "gas_value": { "title": "ana.context.gas_value", - "description": "x denotes the gas value for the ContextGasLifter. Negative value means deactivated, zero means context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitive, the remaining with no context.", + "description": "Denotes the gas value x for the ContextGasLifter. Negative values deactivate the context gas, zero yields a context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitively. Any calls deeper in the call stack are analyzed with the same (empty) context.", "type": "integer", "default": -1 }, "callString_length": { "title": "ana.context.callString_length", - "description": "Length of the call string that should be used as context for the call_string and/or call_site analyses. In case the value is zero, the analysis is context-insensitive. For a negative value, an infinite call string is used! For this option to be effective, one analysis of the `callstring.ml` file must be activated.", + "description": "Length of the call string that should be used as context for the call_string and/or call_site analyses. In case the value is zero, the analysis is context-insensitive. For a negative value, an infinite call string is used! For this option to have an effect, one of the analyses in `callstring.ml` must be activated.", "type": "integer", "default": 2 }