From 84b5207053a0f0149e07a961f9bdf33c5087efa7 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Thu, 4 May 2023 14:26:03 +0200 Subject: [PATCH 001/628] Create build_testing.yml Trying build test using github actions --- .github/workflows/build_testing.yml | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/build_testing.yml diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml new file mode 100644 index 0000000000..8ec9b340c3 --- /dev/null +++ b/.github/workflows/build_testing.yml @@ -0,0 +1,35 @@ +name: build_testing + +on: + - push + - pull_request + +jobs: + tests: + strategy: + fail-fast: false + matrix: + os: + - macos-latest + - ubuntu-latest + ocaml-compiler: + - 4.14.0 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup OCaml ${{ matrix.ocaml-compiler }} + env: + OPAMLOCKED: locked + uses: ocaml/setup-ocaml@v2 + with: + ocaml-compiler: ${{ matrix.ocaml-compiler }} + + - name: Install opam dependencies + run: opam install . --deps-only --locked + + - name: Build + run: ./make.sh nat From b5b7b5a34dddfa5f26d2cc3b6092ac3fc98dded6 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Thu, 4 May 2023 14:33:40 +0200 Subject: [PATCH 002/628] Update build_testing.yml Changed the ocaml compiler version to 4.12.0 --- .github/workflows/build_testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml index 8ec9b340c3..1b464043c7 100644 --- a/.github/workflows/build_testing.yml +++ b/.github/workflows/build_testing.yml @@ -13,7 +13,7 @@ jobs: - macos-latest - ubuntu-latest ocaml-compiler: - - 4.14.0 + - 4.12.0 runs-on: ${{ matrix.os }} From 0ee88d3836cc5e603b34f246ebc6244e0eba0c10 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 5 May 2023 19:51:19 +0200 Subject: [PATCH 003/628] Hint to run "make" in the tutorial --- docs/developer-guide/firstanalysis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/firstanalysis.md b/docs/developer-guide/firstanalysis.md index 38668c28da..21221c4a77 100644 --- a/docs/developer-guide/firstanalysis.md +++ b/docs/developer-guide/firstanalysis.md @@ -67,7 +67,7 @@ The key part now is to define transfer functions for assignment. We only handle There is no need to implement the transfer functions for branching for this example; it only relies on lattice join operations to correctly take both paths into account. The assignment relies on the function `eval`, which is almost there. It just needs you to fix the evaluation of constants! Unless you jumped straight to this line, it should not be too complicated to fix this. -With this in place, we should have sufficient information to tell Goblint that the assertion does hold. +With this in place, we should have sufficient information to tell Goblint that the assertion does hold (run `make` to compile the updated analysis in Goblint). ## Extending the domain From 5510982c7986b9d0c08c02bdc5e8823d05d29b23 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 11 May 2023 11:38:04 +0200 Subject: [PATCH 004/628] added comments to the termination.ml file; TODO: some things are still unclear and have to be added later --- src/analyses/termination.ml | 171 ++++++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 45 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 37ee8bc9ef..c5f2ca7f7d 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -4,6 +4,8 @@ open Prelude.Ana open Analyses module M = Messages +(* J: returns if a and b contain a value + if yes: return this x, otherwise nothing *) let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None module TermDomain = struct @@ -11,15 +13,22 @@ module TermDomain = struct end (* some kind of location string suitable for variable names? *) +(* J: returns a string_ "lineNr_columnNr" *) +(* J: for location (10,5) it evaluates to: 10_5*) let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column +(* J: the new variable is created here and inserted into the code + in the code the variable is set to 0 (before the loop) and incremented (after the loop) + is it ever checked if the newly created variable is really new???*) +(* J: ??? Who defines the Loop, what are the variables*) class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> (* insert loop counter variable *) + (* J: for location (10,5) it evaluates to: term10_5*) let name = "term"^show_location_id loc in let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in @@ -28,14 +37,20 @@ class loopCounterVisitor (fd : fundec) = object(self) (* increment it every iteration *) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* J: s.kind = Loop(b, loc, eloc, ...)*) s.skind <- Block nb; s | _ -> s in ChangeDoChildrenPost (s, action) end +(* J: creates a new hash table with size 13 for loop breaks*) +(* J: int: is a number which is unique in a function*) +(* J: ??? Why 13*) let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) +(* J: if there is some break associated with the loop (?) we add this break to the hash table + key = break.sid + data = location *) class loopBreaksVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -47,10 +62,15 @@ class loopBreaksVisitor (fd : fundec) = object(self) end (* if the given block contains a goto while_break.* we have the termination condition for a loop *) +(* J: returns binding from loopBreaks hash table associated with a number which is uniquely identifie with the statement + if there is a Goto, otherwise nothing*) +(* J: stmt.sid = A number (>= 0) that is unique in a function. *) +(* J: ???*) let exits = function | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid | _ -> None (* TODO handle return (need to find out what loop we are in) *) +(* J: ???*) let lvals_of_expr = let rec f a = function | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a @@ -60,125 +80,186 @@ let lvals_of_expr = | Question (c,t,e,_) -> f a c @ f a t @ f a e in f [] +(* J: create hash table of size 13 for variables*) let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) +(* J: adds the location and left varibale to the loopVars, if one block of the if statement contains a goto block*) class loopVarsVisitor (fd : fundec) = object inherit nopCilVisitor method! vstmt s = let add_exit_cond e loc = match lvals_of_expr e with + (* J: ??? Same as when isArithmeticType Cilfacade.typeOf e*) | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval + (* J : add lval to hash table when the expression on location loc is of arithmetic type*) | _ -> () in (match s.skind with + (* J: map_default f x (Some v) returns f v and map_default f x None returns x.*) + (* J: If there exists a goto statement: call add_exit_cond e (SOME exits tb ||? exits fb) + If e is of arithmetic type: add the location to the loopVars hash table *) | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) | _ -> ()); DoChildren end +(* J: ??? visits the expression e and removes all casts from the expression*) let stripCastsDeep e = let v = object inherit nopCilVisitor + (* J: ChangeTo: Replace the expression with the given one*) + (* J: Removes casts from this expression, but ignores casts within other expression constructs. + So we delete the (A) and (B) casts from "(A)(B)(x + (C)y)", but leave the (C) cast.*) method! vexpr e = ChangeTo (stripCasts e) end in visitCilExpr v e (* keep the enclosing loop for statements *) +(* J: store pointer pointing to Nothing for loops*) let cur_loop = ref None (* current loop *) let cur_loop' = ref None (* for nested loops *) +(* J: searches if the variable name___ for the given location is present in the function definition + if not: the variable is created and initialized to 0*) let makeVar fd loc name = + (* J: for location = (10,5) and name = "hi" the id evaluates to: hi__10_5*) let id = name ^ "__" ^ show_location_id loc in + (* J: fd.slocals = Locals of the function definition*) + (* J: returns the first element which is a local and which name is id (for example hi__10_5)*) try List.find (fun v -> v.vname = id) fd.slocals + (* J: when the variable is not found in the function definition then it is newly created and initialized with 0*) with Not_found -> let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) Goblintutil.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) +(* J: creates an empty function with name "__goblint_assume" and makes a lvalue out of it*) let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) +(* J: creates an empty function with name "__goblint_check" and makes a lvalue out of it*) let f_check = Lval (var (emptyFunction "__goblint_check").svar) +(* J: ??? Loop pointer handling: Why do we fist set cur_loop' = cur_loop and then reverse this operation???*) +(* J: inserts new variable t with init and increment and adds a check if t is bounded*) class loopInstrVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = (* TODO: use Loop eloc? *) (match s.skind with + (* J: if the statement is a loop adjust the loop pointer*) | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; - cur_loop := Some loc + cur_loop' := !cur_loop; (* J: set the nested loop to the current loop*) + cur_loop := Some loc (* J: set the newly found loop as current loop*) | _ -> ()); + (* J: adds the variable t to the loop, increments it and checks after the loop if it is bounded + adds also the variables d1 and d2, with incrementation, which affects t + depending on the structure, d1 and d2 are set differently*) let action s = (* first, restore old cur_loop *) + (* J: if the statement is a loop set the nested loop as the current loop*) (match s.skind with | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; + cur_loop := !cur_loop'; (* J: current loop is the nested loop*) | _ -> ()); + (* J: true if the current loop variable is set and this variable is bound in the hash table*) let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in + (* J: t is the new variable which should be bounded + if there is a loop with bounded variable: add code for init and increment (for t, d1, d2) + if there is a loop with unbounded variable: do nothing + if a loop ended: check if t is bounded + if there is an instruction with an assignment: increment d1 and d2 if the assignment affects the loop var + do this recursively for all children*) match s.skind with + (* J: if the statement is a loop, and when the location is bound in the hash table: + - add the creational and initializational code for t, d1, d2 before the loop + - add the incrementational code for t, d1, d2 in the loop + *) | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> (* find loop var for current loop *) let x = Hashtbl.find loopVars loc in (* insert loop counter and diff to loop var *) + (* J: create variables t, d1, d2 with names: t___, d1___, d2___*) let t = var @@ makeVar fd loc "t" in let d1 = var @@ makeVar fd loc "d1" in let d2 = var @@ makeVar fd loc "d2" in (* make init stmts *) + (* J: set t=0, d1, d2 = lvalue of x = value in the hashtable associated with the loop variable*) let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in (* increment/decrement in every iteration *) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in - let typ = intType in - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in - let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in + (* J: increment t and d2, decrement d1*) + let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in (* J: t = t + 1*) + let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in (* J: d1 = d1 - 1*) + let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in (* J: d2 = d2 + 1*) + let typ = intType in (* J: Note: x is the loop variable*) + let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in (* J: t = (x - d1) *) + let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in (* J: t = (d2 - x) *) + (* J: make a statement for e1 and e2*) + (* J: ??? what happens with the call*) + let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with + (match b.bstmts with (* J: we are still in a loop*) | cont :: cond :: ss -> (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in - s.skind <- Block nb; + (* from: cont :: cond :: ss + to: cont :: + cond :: + t = (x - d1) :: t = (d2 - x) :: (??? Is this correct with the call???) + d1 = d1 - 1 :: d2 = d2 + 1 :: t = t + 1 :: + ss + *) + b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; (* J: in the loop*) + let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in (* J: make a block out of the init statements before the loop*) + s.skind <- Block nb; | _ -> ()); - s + s (* J: return s with added code for init and increment*) + (* J: if the variable in the loops is not bounded, it is not possible to continue*) | Loop (b, loc, eloc, Some continue, Some break) -> print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; s + (* J: when the statement is not a loop and a loop ended: + - add t >= 0 in the code after the loop*) | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in - let t = var @@ makeVar fd loc "t" in - let e3 = BinOp (Ge, Lval t, zero, intType) in - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in - let nb = mkBlock [mkStmt s.skind; inv3] in + let loc = Hashtbl.find loopBreaks s.sid in (* J: holds the current binding of the number of the current function in the hash table*) + let t = var @@ makeVar fd loc "t" in (* J: get the name for variable t = t___*) + let e3 = BinOp (Ge, Lval t, zero, intType) in (* J: t >= 0*) + let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in (* J: make a statement to check t >= 0*) + let nb = mkBlock [mkStmt s.skind; inv3] in (* J: add the statement to the block*) s.skind <- Block nb; - s + s (* J: return s with the added check*) + (* J: If there is an instruction (containing an assignment) and it is in a loop: + If the loop variable and lvalue of Set are structural unequal + Do nothing + else + add an incrementation step for d1 and d2 (depending on the binOp)*) | Instr [Set (lval, e, loc, eloc)] when in_loop () -> (* find loop var for current loop *) let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in - if x <> lval then + let x = Hashtbl.find loopVars cur_loop in (* J: holds the current binding of the number of the current function in the hash table*) + if x <> lval then (* J: x and lval are structural unequal*) s else (* we only care about the loop var *) + (* J: create the variables d1 and d2 with name: d1___, d2___*) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: + - adds incrementation for d1 and d2 to the code*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in + let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) + let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in (* J: d2 = d2 + e2*) + let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in (* J: add the incrementation steps at the front*) s.skind <- Block nb; - s + s (* J: return s with the added incrementation*) | _ -> (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in - let te = Cilfacade.typeOf e in - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in + let t = makeVar fd cur_loop "t" in (* J: varibale name for t*) + let te = Cilfacade.typeOf e in (* J: type of e*) + let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d1 = x - t*) + let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d2 = x - t*) + let nb = mkBlock [mkStmt s.skind; dt1; dt2] in (* J: add the incrementation steps at the end*) s.skind <- Block nb; s ) | _ -> s in - ChangeDoChildrenPost (s, action) + ChangeDoChildrenPost (s, action) (* J: continue with the children*) end @@ -215,24 +296,24 @@ struct (* ctx.local *) (* | _ -> ctx.local *) - let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let startstate v = D.bot () (* J: start with bottom*) + let threadenter ctx lval f args = [D.bot ()] (* J: enter threads with bottom*) let exitstate v = D.bot () end class recomputeVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc fd = - computeCFGInfo fd true; - SkipChildren + computeCFGInfo fd true; (* J: make the cfg and return a list of statements with global statement number*) + SkipChildren (* J: don't visit children*) end let _ = (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); - Hashtbl.clear loopBreaks; (* because the sids are now different *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - MCP.register_analysis (module Spec : MCPSpec) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: fill hash table loopBreaks: containing breaks ?*) + Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); (* J: fill hash table loopVars: containing varibales identified with loops ?*) + Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); (* J: inserts new variable with init, increment, and bounded check to code*) + Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) + Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) From 8facb0c9ca8c382194a88bcdb4c01f14b051efd9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 11 May 2023 19:58:15 +0200 Subject: [PATCH 005/628] added preprocessing file for loop termination analysis: this file contains code adding before it is analyzed --- src/analyses/termination.ml | 4 +++- src/util/terminationPreprocessing.ml | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/util/terminationPreprocessing.ml diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index c5f2ca7f7d..8fa8a0ee12 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -240,6 +240,7 @@ class loopInstrVisitor (fd : fundec) = object(self) (match stripCastsDeep e with (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: - adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) @@ -259,6 +260,7 @@ class loopInstrVisitor (fd : fundec) = object(self) ) | _ -> s in + (* J: *) ChangeDoChildrenPost (s, action) (* J: continue with the children*) end @@ -316,4 +318,4 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) \ No newline at end of file diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml new file mode 100644 index 0000000000..73982cb0f1 --- /dev/null +++ b/src/util/terminationPreprocessing.ml @@ -0,0 +1,3 @@ +(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting + - check if overflow happend with new variable + - how do we deal with nested loops?*) \ No newline at end of file From 7fbb12ae3c72b2115846b694832e22955996b492 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Sun, 14 May 2023 23:21:19 +0200 Subject: [PATCH 006/628] Update termination.ml Indentations fix test --- src/analyses/termination.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 8fa8a0ee12..0040055e03 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -238,9 +238,8 @@ class loopInstrVisitor (fd : fundec) = object(self) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: - - adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) @@ -318,4 +317,4 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) From ff19371cf58c5d9d584ec2c8f78fcdb50611aecd Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Sun, 14 May 2023 23:24:39 +0200 Subject: [PATCH 007/628] Update termination.ml indentation test check --- src/analyses/termination.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 0040055e03..eb6c263870 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -238,8 +238,8 @@ class loopInstrVisitor (fd : fundec) = object(self) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) From cb3f49429d429b51a2fd27b1960103a895220ba5 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 11:16:48 +0200 Subject: [PATCH 008/628] One comment in old termination analysis --- src/analyses/termination.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index eb6c263870..f963d0d094 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -317,4 +317,5 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) + MCP.register_analysis (module Spec : MCPSpec) (* A: register this (termination) analysis withing the master control program, which + collects all active analyses and represents the combination of them as a new, single analysis to FromSpec *) From 20f0bbd5751b4a854361dd0c6f3724500d077eae Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 11:25:31 +0200 Subject: [PATCH 009/628] Create new termination analysis file --- src/analyses/termination_new.ml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/analyses/termination_new.ml diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml new file mode 100644 index 0000000000..afc2ea3ece --- /dev/null +++ b/src/analyses/termination_new.ml @@ -0,0 +1,12 @@ +open Prelude.Ana +open Analyses + +module Spec : Analyses.MCPSpec = +struct + + let query ctx (type a) (q: a Queries.t): a Queries.result = () + +end + +let _ = + MCP.register_analysis (module Spec : MCPSpec) From c4e92dba282891d8bd4e92d624cb26bb72b86abd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 12:15:06 +0200 Subject: [PATCH 010/628] Better dummy query --- src/analyses/termination_new.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index afc2ea3ece..9d1319119f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,12 +1,19 @@ +(** Work in progress *) + open Prelude.Ana open Analyses +let terminates loop = () (* TODO *) + module Spec : Analyses.MCPSpec = struct - let query ctx (type a) (q: a Queries.t): a Queries.result = () + let query ctx (type a) (q: a Queries.t): a Queries.result = + let open Queries in + Result.top q (* TODO *) end let _ = + (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 14f2bdd90c4f5fb1ad69913d87441feedb0ed4fe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 18:00:23 +0200 Subject: [PATCH 011/628] Add required functions and values --- src/analyses/termination_new.ml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 9d1319119f..e6b202b69e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -8,6 +8,17 @@ let terminates loop = () (* TODO *) module Spec : Analyses.MCPSpec = struct + let name () = "termination" + + module D = Lattice.Unit (* TODO *) + module C = D (* TODO *) + + let startstate _ = D.bot () (* TODO *) + let exitstate = startstate (* TODO *) + + (** Provides some default implementations *) + include Analyses.IdentitySpec + let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in Result.top q (* TODO *) @@ -15,5 +26,5 @@ struct end let _ = - (* Register this analysis within the master control program *) + (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 6fc9a1efe42f38f5ef2c2cef20c99c8523068726 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 18:19:30 +0200 Subject: [PATCH 012/628] Do not open the prelude --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e6b202b69e..c81ff72d71 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,6 +1,5 @@ (** Work in progress *) -open Prelude.Ana open Analyses let terminates loop = () (* TODO *) From ec89bc2be9b31350b4f7cd135ab8cb128bc3f8a9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 15:38:59 +0200 Subject: [PATCH 013/628] added code adding to terminationPreprocessing file in util; created sh script to execute the code easily and store the cil output in the output.txt file; NOTE: the signs.ml file does currently contain the termination analysis; signsOrig.ml contains the original signs analysis --- output.txt | 2167 ++++++++++++++++++++++++++ runningGob.sh | 3 + src/analyses/tutorials/signs.ml | 22 + src/analyses/tutorials/signsOrig.ml | 92 ++ src/util/terminationPreprocessing.ml | 42 +- 5 files changed, 2325 insertions(+), 1 deletion(-) create mode 100644 output.txt create mode 100755 runningGob.sh create mode 100644 src/analyses/tutorials/signsOrig.ml diff --git a/output.txt b/output.txt new file mode 100644 index 0000000000..d3b021a1f3 --- /dev/null +++ b/output.txt @@ -0,0 +1,2167 @@ +/* Generated by CIL v. 2.0.1-48-g4df989f */ +/* print_CIL_Input is true */ + +#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned char __u_char; +#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned short __u_short; +#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __u_int; +#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __u_long; +#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef signed char __int8_t; +#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned char __uint8_t; +#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef short __int16_t; +#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned short __uint16_t; +#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __int32_t; +#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __uint32_t; +#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __int64_t; +#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __uint64_t; +#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int8_t __int_least8_t; +#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint8_t __uint_least8_t; +#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int16_t __int_least16_t; +#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint16_t __uint_least16_t; +#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int32_t __int_least32_t; +#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint32_t __uint_least32_t; +#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int64_t __int_least64_t; +#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint64_t __uint_least64_t; +#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __quad_t; +#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __u_quad_t; +#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __intmax_t; +#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __uintmax_t; +#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __dev_t; +#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __uid_t; +#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __gid_t; +#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __ino_t; +#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __ino64_t; +#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __mode_t; +#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __nlink_t; +#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __off_t; +#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __off64_t; +#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __pid_t; +#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" +struct __anonstruct___fsid_t_109580352 { + int __val[2] ; +}; +#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef struct __anonstruct___fsid_t_109580352 __fsid_t; +#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __clock_t; +#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __rlim_t; +#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __rlim64_t; +#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __id_t; +#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __time_t; +#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __useconds_t; +#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __suseconds_t; +#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __suseconds64_t; +#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __daddr_t; +#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __key_t; +#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __clockid_t; +#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef void *__timer_t; +#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blksize_t; +#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blkcnt_t; +#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blkcnt64_t; +#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsblkcnt_t; +#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsblkcnt64_t; +#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsfilcnt_t; +#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsfilcnt64_t; +#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __fsword_t; +#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __ssize_t; +#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __syscall_slong_t; +#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __syscall_ulong_t; +#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __off64_t __loff_t; +#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef char *__caddr_t; +#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __intptr_t; +#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __socklen_t; +#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __sig_atomic_t; +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef unsigned long size_t; +#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" +typedef __time_t time_t; +#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" +struct timespec { + __time_t tv_sec ; + __syscall_slong_t tv_nsec ; +}; +#line 38 "/usr/include/sched.h" +typedef __pid_t pid_t; +#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" +struct sched_param { + int sched_priority ; +}; +#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +typedef unsigned long __cpu_mask; +#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +struct __anonstruct_cpu_set_t_826868708 { + __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; +}; +#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" +typedef __clock_t clock_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" +struct tm { + int tm_sec ; + int tm_min ; + int tm_hour ; + int tm_mday ; + int tm_mon ; + int tm_year ; + int tm_wday ; + int tm_yday ; + int tm_isdst ; + long tm_gmtoff ; + char const *tm_zone ; +}; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" +typedef __clockid_t clockid_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" +typedef __timer_t timer_t; +#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" +struct itimerspec { + struct timespec it_interval ; + struct timespec it_value ; +}; +#line 49 "/usr/include/time.h" +struct sigevent ; +#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +struct __locale_data ; +#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +struct __locale_struct { + struct __locale_data *__locales[13] ; + unsigned short const *__ctype_b ; + int const *__ctype_tolower ; + int const *__ctype_toupper ; + char const *__names[13] ; +}; +#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +typedef struct __locale_struct *__locale_t; +#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" +typedef __locale_t locale_t; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +struct __anonstruct___value32_817613185 { + unsigned int __low ; + unsigned int __high ; +}; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +union __anonunion___atomic_wide_counter_643133811 { + unsigned long long __value64 ; + struct __anonstruct___value32_817613185 __value32 ; +}; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_internal_list { + struct __pthread_internal_list *__prev ; + struct __pthread_internal_list *__next ; +}; +#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __pthread_internal_list __pthread_list_t; +#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_internal_slist { + struct __pthread_internal_slist *__next ; +}; +#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __pthread_internal_slist __pthread_slist_t; +#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" +struct __pthread_mutex_s { + int __lock ; + unsigned int __count ; + int __owner ; + unsigned int __nusers ; + int __kind ; + short __spins ; + short __elision ; + __pthread_list_t __list ; +}; +#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" +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 ; + int __cur_writer ; + int __shared ; + signed char __rwelision ; + unsigned char __pad1[7] ; + unsigned long __pad2 ; + unsigned int __flags ; +}; +#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_cond_s { + __atomic_wide_counter __wseq ; + __atomic_wide_counter __g1_start ; + unsigned int __g_refs[2] ; + unsigned int __g_size[2] ; + unsigned int __g1_orig_size ; + unsigned int __wrefs ; + unsigned int __g_signals[2] ; +}; +#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef unsigned int __tss_t; +#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef unsigned long __thrd_t; +#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __anonstruct___once_flag_826868709 { + int __data ; +}; +#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __anonstruct___once_flag_826868709 __once_flag; +#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef unsigned long pthread_t; +#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_mutexattr_t_488594144 { + char __size[4] ; + int __align ; +}; +#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; +#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_condattr_t_488594145 { + char __size[4] ; + int __align ; +}; +#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; +#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef unsigned int pthread_key_t; +#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef int pthread_once_t; +#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union pthread_attr_t { + char __size[56] ; + long __align ; +}; +#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union pthread_attr_t pthread_attr_t; +#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_mutex_t_335460617 { + struct __pthread_mutex_s __data ; + char __size[40] ; + long __align ; +}; +#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; +#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_cond_t_951761805 { + struct __pthread_cond_s __data ; + char __size[48] ; + long long __align ; +}; +#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; +#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_rwlock_t_656928968 { + struct __pthread_rwlock_arch_t __data ; + char __size[56] ; + long __align ; +}; +#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; +#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_rwlockattr_t_145707745 { + char __size[8] ; + long __align ; +}; +#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; +#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef int volatile pthread_spinlock_t; +#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_barrier_t_145707746 { + char __size[32] ; + long __align ; +}; +#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; +#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_barrierattr_t_951761806 { + char __size[4] ; + int __align ; +}; +#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; +#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" +typedef long __jmp_buf[8]; +#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" +struct __anonstruct___sigset_t_764561023 { + unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; +}; +#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" +typedef struct __anonstruct___sigset_t_764561023 __sigset_t; +#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" +struct __jmp_buf_tag { + __jmp_buf __jmpbuf ; + int __mask_was_saved ; + __sigset_t __saved_mask ; +}; +#line 37 "/usr/include/pthread.h" +enum __anonenum_34415463 { + PTHREAD_CREATE_JOINABLE = 0, + PTHREAD_CREATE_DETACHED = 1 +} ; +#line 47 +enum __anonenum_508643754 { + PTHREAD_MUTEX_TIMED_NP = 0, + PTHREAD_MUTEX_RECURSIVE_NP = 1, + PTHREAD_MUTEX_ERRORCHECK_NP = 2, + PTHREAD_MUTEX_ADAPTIVE_NP = 3, + PTHREAD_MUTEX_NORMAL = 0, + PTHREAD_MUTEX_RECURSIVE = 1, + PTHREAD_MUTEX_ERRORCHECK = 2, + PTHREAD_MUTEX_DEFAULT = 0 +} ; +#line 69 +enum __anonenum_931900394 { + PTHREAD_MUTEX_STALLED = 0, + PTHREAD_MUTEX_STALLED_NP = 0, + PTHREAD_MUTEX_ROBUST = 1, + PTHREAD_MUTEX_ROBUST_NP = 1 +} ; +#line 81 +enum __anonenum_205214487 { + PTHREAD_PRIO_NONE = 0, + PTHREAD_PRIO_INHERIT = 1, + PTHREAD_PRIO_PROTECT = 2 +} ; +#line 104 +enum __anonenum_25043950 { + PTHREAD_RWLOCK_PREFER_READER_NP = 0, + PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, + PTHREAD_RWLOCK_DEFAULT_NP = 0 +} ; +#line 124 +enum __anonenum_436439511 { + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1 +} ; +#line 134 +enum __anonenum_998661166 { + PTHREAD_SCOPE_SYSTEM = 0, + PTHREAD_SCOPE_PROCESS = 1 +} ; +#line 144 +enum __anonenum_146137331 { + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1 +} ; +#line 159 "/usr/include/pthread.h" +struct _pthread_cleanup_buffer { + void (*__routine)(void * ) ; + void *__arg ; + int __canceltype ; + struct _pthread_cleanup_buffer *__prev ; +}; +#line 168 +enum __anonenum_53396917 { + PTHREAD_CANCEL_ENABLE = 0, + PTHREAD_CANCEL_DISABLE = 1 +} ; +#line 175 +enum __anonenum_904563783 { + PTHREAD_CANCEL_DEFERRED = 0, + PTHREAD_CANCEL_ASYNCHRONOUS = 1 +} ; +#line 538 "/usr/include/pthread.h" +struct __cancel_jmp_buf_tag { + __jmp_buf __cancel_jmp_buf ; + int __mask_was_saved ; +}; +#line 544 "/usr/include/pthread.h" +struct __anonstruct___pthread_unwind_buf_t_530692248 { + struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; + void *__pad[4] ; +}; +#line 544 "/usr/include/pthread.h" +typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; +#line 557 "/usr/include/pthread.h" +struct __pthread_cleanup_frame { + void (*__cancel_routine)(void * ) ; + void *__cancel_arg ; + int __do_it ; + int __cancel_type ; +}; +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef long ptrdiff_t; +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef int wchar_t; +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +struct __anonstruct_max_align_t_896270833 { + long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; + long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; +}; +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef struct __anonstruct_max_align_t_896270833 max_align_t; +/* compiler builtin: + void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ +/* compiler builtin: + void *__builtin_frob_return_address(void * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ +/* compiler builtin: + int __builtin_popcountll(unsigned long long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ +/* compiler builtin: + float __builtin_atanf(float ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + unsigned long __builtin_strcspn(char const * , char const * ) ; */ +/* compiler builtin: + float __builtin_asinf(float ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + double __builtin_acos(double ) ; */ +/* compiler builtin: + int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ +/* compiler builtin: + double __builtin_cosh(double ) ; */ +/* compiler builtin: + float __builtin_tanhf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ +/* compiler builtin: + void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ +/* compiler builtin: + long double __builtin_sqrtl(long double ) ; */ +/* compiler builtin: + int __builtin_parity(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ +/* compiler builtin: + long double __builtin_coshl(long double ) ; */ +/* compiler builtin: + long double __builtin_cosl(long double ) ; */ +/* compiler builtin: + float __builtin_cosf(float ) ; */ +/* compiler builtin: + void __sync_synchronize(...) ; */ +/* compiler builtin: + long double __builtin_acosl(long double ) ; */ +/* compiler builtin: + void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ +/* compiler builtin: + int __builtin_clz(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ +/* compiler builtin: + double __builtin_log10(double ) ; */ +/* compiler builtin: + char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_modff(float , float * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_n(...) ; */ +/* compiler builtin: + double __builtin_sin(double ) ; */ +/* compiler builtin: + double __builtin_frexp(double , int * ) ; */ +/* compiler builtin: + float __builtin_acosf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ +/* compiler builtin: + long double __builtin_sinhl(long double ) ; */ +/* compiler builtin: + char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __atomic_signal_fence(int ) ; */ +/* compiler builtin: + double __builtin_fabs(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ +/* compiler builtin: + void __atomic_thread_fence(int ) ; */ +/* compiler builtin: + void __atomic_store_16(...) ; */ +/* compiler builtin: + void __builtin_va_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ +/* compiler builtin: + short __builtin_bswap16(short ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ +/* compiler builtin: + _Bool __atomic_test_and_set(void * , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ +/* compiler builtin: + int __builtin_ctz(unsigned int ) ; */ +/* compiler builtin: + char *__builtin_strpbrk(char const * , char const * ) ; */ +/* compiler builtin: + char *__builtin_strcpy(char * , char const * ) ; */ +/* compiler builtin: + double __builtin_sqrt(double ) ; */ +/* compiler builtin: + __builtin_va_list __builtin_next_arg(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ +/* compiler builtin: + void __atomic_clear(_Bool * , int ) ; */ +/* compiler builtin: + void __atomic_store(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ +/* compiler builtin: + float __builtin_log10f(float ) ; */ +/* compiler builtin: + long double __builtin_fabsl(long double ) ; */ +/* compiler builtin: + long double __builtin_floorl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ +/* compiler builtin: + float __builtin_floorf(float ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_4(...) ; */ +/* compiler builtin: + void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + int __builtin_parityll(unsigned long long ) ; */ +/* compiler builtin: + void __builtin_va_end(__builtin_va_list ) ; */ +/* compiler builtin: + void __builtin_bzero(void * , unsigned long ) ; */ +/* compiler builtin: + _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ +/* compiler builtin: + int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ +/* compiler builtin: + int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , + __builtin_va_list ) ; */ +/* compiler builtin: + float __builtin_sqrtf(float ) ; */ +/* compiler builtin: + double __builtin_nans(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ +/* compiler builtin: + double __builtin_exp(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ +/* compiler builtin: + int __builtin_strcmp(char const * , char const * ) ; */ +/* compiler builtin: + float __builtin_ldexpf(float , int ) ; */ +/* compiler builtin: + float __builtin_powif(float , int ) ; */ +/* compiler builtin: + long double __builtin_log10l(long double ) ; */ +/* compiler builtin: + void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ +/* compiler builtin: + void *__builtin_return_address(unsigned int ) ; */ +/* compiler builtin: + void __atomic_feraiseexcept(int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ +/* compiler builtin: + float __builtin_fabsf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ +/* compiler builtin: + unsigned long __builtin_object_size(void * , int ) ; */ +/* compiler builtin: + void *__builtin_alloca(unsigned long ) ; */ +/* compiler builtin: + int __builtin_va_arg_pack_len(void) ; */ +/* compiler builtin: + long double __builtin_tanl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ +/* compiler builtin: + void __sync_lock_release(...) ; */ +/* compiler builtin: + long double __builtin_modfl(long double , long double * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ +/* compiler builtin: + char *__builtin_stpcpy(char * , char const * ) ; */ +/* compiler builtin: + long double __builtin_sinl(long double ) ; */ +/* compiler builtin: + double __builtin_asin(double ) ; */ +/* compiler builtin: + float __builtin_sinhf(float ) ; */ +/* compiler builtin: + int __builtin_ctzl(unsigned long ) ; */ +/* compiler builtin: + long double __builtin_tanhl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ +/* compiler builtin: + long __builtin_bswap64(long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + double __builtin_tan(double ) ; */ +/* compiler builtin: + char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_inff(void) ; */ +/* compiler builtin: + void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ +/* compiler builtin: + double __builtin_huge_val(void) ; */ +/* compiler builtin: + int __builtin_clzl(unsigned long ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_16(...) ; */ +/* compiler builtin: + float __builtin_frexpf(float , int * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ +/* compiler builtin: + long double __builtin_fmodl(long double ) ; */ +/* compiler builtin: + double __builtin_atan(double ) ; */ +/* compiler builtin: + int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ +/* compiler builtin: + float __builtin_ceilf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ +/* compiler builtin: + void __builtin_return(void const * ) ; */ +/* compiler builtin: + long double __builtin_asinl(long double ) ; */ +/* compiler builtin: + int __builtin_ffsll(unsigned long long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ +/* compiler builtin: + int __builtin_va_arg_pack(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ +/* compiler builtin: + char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + double __builtin_powi(double , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ +/* compiler builtin: + char *__builtin_strchr(char * , int ) ; */ +/* compiler builtin: + char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __atomic_store_2(...) ; */ +/* compiler builtin: + long double __builtin_huge_vall(void) ; */ +/* compiler builtin: + int __builtin_ffsl(unsigned long ) ; */ +/* compiler builtin: + int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + char *__builtin_strncat(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + int __builtin_ctzll(unsigned long long ) ; */ +/* compiler builtin: + void __builtin_stdarg_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ +/* compiler builtin: + long double __builtin_frexpl(long double , int * ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange(...) ; */ +/* compiler builtin: + float __builtin_tanf(float ) ; */ +/* compiler builtin: + long double __builtin_logl(long double ) ; */ +/* compiler builtin: + void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ +/* compiler builtin: + long __builtin_expect(long , long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_1(...) ; */ +/* compiler builtin: + int __builtin___printf_chk(int , char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ +/* compiler builtin: + int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ +/* compiler builtin: + void __builtin_prefetch(void const * , ...) ; */ +/* compiler builtin: + long double __builtin_nansl(char const * ) ; */ +/* compiler builtin: + double __builtin_fmod(double ) ; */ +/* compiler builtin: + void __atomic_load(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ +/* compiler builtin: + void __atomic_store_4(...) ; */ +/* compiler builtin: + double __builtin_tanh(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ +/* compiler builtin: + void __builtin_unreachable(void) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_2(...) ; */ +/* compiler builtin: + long double __builtin_ldexpl(long double , int ) ; */ +/* compiler builtin: + void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_sinf(float ) ; */ +/* compiler builtin: + double __builtin_ceil(double ) ; */ +/* compiler builtin: + void __atomic_exchange(...) ; */ +/* compiler builtin: + long double __builtin_powil(long double , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ +/* compiler builtin: + long double __builtin_expl(long double ) ; */ +/* compiler builtin: + int __builtin_constant_p(int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ +/* compiler builtin: + double __builtin_log(double ) ; */ +/* compiler builtin: + float __builtin_expf(float ) ; */ +/* compiler builtin: + int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ +/* compiler builtin: + long double __builtin_atan2l(long double , long double ) ; */ +/* compiler builtin: + void *__builtin_apply_args(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ +/* compiler builtin: + float __builtin_logf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ +/* compiler builtin: + unsigned long __builtin_strlen(char const * ) ; */ +/* compiler builtin: + int __builtin_ffs(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ +/* compiler builtin: + double __builtin_inf(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ +/* compiler builtin: + void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ +/* compiler builtin: + void __atomic_store_n(...) ; */ +/* compiler builtin: + void __builtin_trap(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ +/* compiler builtin: + int __builtin_parityl(unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ +/* compiler builtin: + unsigned long __builtin_strspn(char const * , char const * ) ; */ +/* compiler builtin: + void __builtin_varargs_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ +/* compiler builtin: + double __builtin_nan(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ +/* compiler builtin: + int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , + char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ +/* compiler builtin: + long double __builtin_atanl(long double ) ; */ +/* compiler builtin: + int __builtin_clzll(unsigned long long ) ; */ +/* compiler builtin: + float __builtin_huge_valf(void) ; */ +/* compiler builtin: + float __builtin_coshf(float ) ; */ +/* compiler builtin: + float __builtin_nansf(char const * ) ; */ +/* compiler builtin: + void __atomic_store_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ +/* compiler builtin: + int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , + char const * , __builtin_va_list ) ; */ +/* compiler builtin: + float __builtin_nanf(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ +/* compiler builtin: + _Bool __sync_bool_compare_and_swap(...) ; */ +/* compiler builtin: + double __builtin_atan2(double , double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ +/* compiler builtin: + int __builtin_popcountl(unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ +/* compiler builtin: + long double __builtin_ceill(long double ) ; */ +/* compiler builtin: + void __atomic_store_1(...) ; */ +/* compiler builtin: + char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ +/* compiler builtin: + double __builtin_floor(double ) ; */ +/* compiler builtin: + double __builtin_cos(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ +/* compiler builtin: + void *__builtin_memset(void * , int , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ +/* compiler builtin: + long double __builtin_nanl(char const * ) ; */ +/* compiler builtin: + float __builtin_atan2f(float , float ) ; */ +/* compiler builtin: + _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ +/* compiler builtin: + int __builtin_popcount(unsigned int ) ; */ +/* compiler builtin: + double __builtin_sinh(double ) ; */ +/* compiler builtin: + void __builtin_bcopy(void const * , void * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ +/* compiler builtin: + void *__builtin_extract_return_addr(void * ) ; */ +/* compiler builtin: + int __builtin_bswap32(int ) ; */ +/* compiler builtin: + double __builtin_ldexp(double , int ) ; */ +/* compiler builtin: + long double __builtin_infl(void) ; */ +/* compiler builtin: + float __builtin_fmodf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ +/* compiler builtin: + void *__builtin_frame_address(unsigned int ) ; */ +#line 1 "lib/goblint/runtime/include/goblint.h" +extern void __goblint_check(int exp ) ; +#line 2 +extern void __goblint_assume(int exp ) ; +#line 3 +extern void __goblint_assert(int exp ) ; +#line 5 +extern void __goblint_assume_join() ; +#line 7 +extern void __goblint_split_begin(int exp ) ; +#line 8 +extern void __goblint_split_end(int exp ) ; +#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int global ; +#line 8 +void example1(void) ; +#line 9 +void example2(void) ; +#line 10 +void example3(void) ; +#line 11 +void example4(void) ; +#line 12 +void example5(void) ; +#line 13 +void example6(void) ; +#line 14 +void example7(void) ; +#line 15 +void example8(void) ; +#line 16 +void example9(void) ; +#line 17 +void example10(void) ; +#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int main(void) +{ + + + { +#line 8 + example1(); +#line 9 + example2(); +#line 10 + example3(); +#line 11 + example4(); +#line 12 + example5(); +#line 13 + example6(); +#line 14 + example7(); +#line 15 + example8(); +#line 16 + example9(); +#line 17 + example10(); +#line 18 + return (0); +} +} +#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example1(void) +{ + int a[5] ; + int i ; + int term27_5 = 0; + + { +#line 25 + i = 0; + { + { +#line 27 + while (1) { +#line 27 + term27_5 ++; + while_continue: /* CIL Label */ ; +#line 27 + if (! (i < 5)) { +#line 27 + goto while_break; + } +#line 28 + a[i] = i; +#line 29 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 32 + __goblint_check(a[0] == 0); +#line 33 + __goblint_check(a[3] == 3); +#line 34 + return; +} +} +#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example2(void) +{ + int a[5] ; + int i ; + int term42_5 = 0; + + { +#line 40 + i = 0; + { + { +#line 42 + while (1) { +#line 42 + term42_5 ++; + while_continue: /* CIL Label */ ; +#line 43 + a[i] = i; +#line 44 + i ++; +#line 42 + if (! (i <= 5)) { +#line 42 + goto while_break; + } + } + } + while_break: /* CIL Label */ ; + } +#line 47 + __goblint_check(a[0] == 0); +#line 48 + __goblint_check(a[3] == 3); +#line 49 + return; +} +} +#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example3(void) +{ + int a[10] ; + int i ; + int term57_5 = 0; + + { +#line 55 + i = 0; + { + { +#line 57 + while (1) { +#line 57 + term57_5 ++; + while_continue: /* CIL Label */ ; +#line 57 + if (! (i < 5)) { +#line 57 + goto while_break; + } +#line 58 + a[i] = i; +#line 59 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 62 + __goblint_check(a[0] == 0); +#line 63 + __goblint_check(a[3] == 0); +#line 64 + __goblint_check(a[7] == 0); +#line 65 + return; +} +} +#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example4(void) +{ + int a[10] ; + int i ; + int first_iteration ; + int term74_5 = 0; + + { +#line 71 + i = 0; +#line 72 + first_iteration = 1; + { + { +#line 74 + while (1) { +#line 74 + term74_5 ++; + while_continue: /* CIL Label */ ; +#line 74 + if (! (i < 10)) { +#line 74 + goto while_break; + } +#line 75 + if (first_iteration == 1) { +#line 75 + __goblint_check(i == 0); + } else +#line 76 + if (i > 5) { +#line 76 + __goblint_check(i == 6); + } +#line 77 + first_iteration = 0; +#line 78 + a[i] = 0; +#line 79 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 82 + __goblint_check(a[0] == 0); +#line 83 + __goblint_check(first_iteration == 0); +#line 84 + return; +} +} +#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example5(void) +{ + int a[4] ; + int i ; + int top ; + int term95_5 = 0; + + { +#line 92 + i = 0; +#line 93 + top = 0; + { + { +#line 95 + while (1) { +#line 95 + term95_5 ++; + while_continue: /* CIL Label */ ; +#line 95 + if (! (i < 4)) { +#line 95 + goto while_break; + } +#line 96 + a[i] = 0; +#line 97 + top += i; +#line 98 + if (i == 2) { +#line 99 + __goblint_check(top == 3); + } else { +#line 102 + __goblint_check(top == 3); + } +#line 104 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 107 + __goblint_check(a[0] == 0); +#line 108 + __goblint_check(a[3] == 0); +#line 109 + __goblint_check(top == 6); +#line 110 + return; +} +} +#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example6(void) +{ + int a[5] ; + int i ; + int top ; + int term119_5 = 0; + + { +#line 116 + i = 0; +#line 117 + top = 0; + { + { +#line 119 + while (1) { +#line 119 + term119_5 ++; + while_continue: /* CIL Label */ ; +#line 119 + if (! (i < 3)) { +#line 119 + goto while_break; + } +#line 120 + a[i] = 0; +#line 121 + __goblint_check(a[0] == 0); +#line 122 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 125 + __goblint_check(a[0] == 0); +#line 126 + __goblint_check(a[3] == 0); +#line 127 + __goblint_check(top == 6); +#line 128 + return; +} +} +#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int update(int i ) +{ + + + { +#line 132 + if (i > 5) { +#line 133 + return (0); + } else { +#line 136 + return (1); + } +} +} +#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example7(void) +{ + int a[10] ; + int i ; + int tmp ; + int term143_2 = 0; + + { +#line 142 + i = 0; + { + { +#line 143 + while (1) { +#line 143 + term143_2 ++; + while_continue: /* CIL Label */ ; +#line 143 + tmp = update(i); +#line 143 + if (! tmp) { +#line 143 + goto while_break; + } +#line 144 + a[i] = i; +#line 145 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 147 + __goblint_check(a[0] == 0); +#line 148 + __goblint_check(a[6] == 0); +#line 149 + return; +} +} +#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example8(void) +{ + int a[5] ; + int b[5] ; + int i ; + int j ; + int term160_9 = 0; + int term157_2 = 0; + + { +#line 155 + b[0] = 0; +#line 155 + b[1] = 0; +#line 155 + b[2] = 0; +#line 155 + b[3] = 0; +#line 155 + b[4] = 0; +#line 156 + i = 0; + { + { +#line 157 + while (1) { +#line 157 + term157_2 ++; + while_continue: /* CIL Label */ ; +#line 157 + if (! (i < 5)) { +#line 157 + goto while_break; + } +#line 158 + a[i] = i; +#line 159 + j = 0; + { + { +#line 160 + while (1) { +#line 160 + term160_9 ++; + while_continue___0: /* CIL Label */ ; +#line 160 + if (! (j < 5)) { +#line 160 + goto while_break___0; + } +#line 161 + b[j] += a[i]; +#line 162 + j ++; + } + } + while_break___0: /* CIL Label */ ; + } +#line 164 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 166 + return; +} +} +#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example9(void) +{ + int a[5] ; + int i ; + int term174_2 = 0; + + { +#line 173 + i = 0; + { + { +#line 174 + while (1) { +#line 174 + term174_2 ++; + while_continue: /* CIL Label */ ; +#line 174 + if (! 1) { +#line 174 + goto while_break; + } +#line 175 + a[i] = i; +#line 176 + i ++; +#line 177 + if (i == 5) { +#line 177 + goto while_break; + } + } + } + while_break: /* CIL Label */ ; + } +#line 179 + return; +} +} +#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example10(void) +{ + int a[5] ; + int i ; + int term187_2 = 0; + + { +#line 186 + i = 0; + { + { +#line 187 + while (1) { +#line 187 + term187_2 ++; + while_continue: /* CIL Label */ ; +#line 187 + if (! (i < 5)) { +#line 187 + goto while_break; + } +#line 188 + if (i == 3) { +#line 189 + i ++; +#line 190 + goto while_continue; + } +#line 192 + a[i] = i; +#line 193 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 195 + return; +} +} +#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; +#line 119 +extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; +#line 120 +extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; +#line 54 "/usr/include/sched.h" +extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 58 +extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; +#line 61 +extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , + struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 65 +extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; +#line 68 +extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; +#line 71 +extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; +#line 74 +extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; +#line 78 +extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; +#line 72 "/usr/include/time.h" +extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; +#line 76 +extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; +#line 79 +extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, +__const__)) ; +#line 83 +extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 100 +extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , + char const * __restrict __format , + struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 116 +extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , + char const * __restrict __format , + struct tm const * __restrict __tp , + locale_t __loc ) __attribute__((__nothrow__)) ; +#line 132 +extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 136 +extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 154 +extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , + struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 159 +extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , + struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 179 +extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; +#line 183 +extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 197 +extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , + char * __restrict __buf ) __attribute__((__nothrow__)) ; +#line 202 +extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , + char * __restrict __buf ) __attribute__((__nothrow__)) ; +#line 217 +extern char *__tzname[2] ; +#line 218 +extern int __daylight ; +#line 219 +extern long __timezone ; +#line 224 +extern char *tzname[2] ; +#line 228 +extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; +#line 232 +extern int daylight ; +#line 233 +extern long timezone ; +#line 249 +extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 251 +extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 262 +extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, +__const__)) ; +#line 272 +extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; +#line 276 +extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; +#line 279 +extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 282 +extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 311 +extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , + struct timespec *__rem ) ; +#line 326 +extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; +#line 331 +extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , + timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; +#line 336 +extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; +#line 340 +extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , + struct itimerspec const * __restrict __value , + struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; +#line 345 +extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; +#line 364 +extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; +#line 371 +extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , + int __base ) __attribute__((__nothrow__)) ; +#line 202 "/usr/include/pthread.h" +extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , + pthread_attr_t const * __restrict __attr , + void *(*__start_routine)(void * ) , + void * __restrict __arg ) __attribute__((__nothrow__)) ; +#line 211 +extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; +#line 219 +extern int pthread_join(pthread_t __th , void **__thread_return ) ; +#line 269 +extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; +#line 273 +extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, +__const__)) ; +#line 276 +extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, +__const__)) ; +#line 285 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; +#line 288 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , + int *__detachstate ) __attribute__((__nothrow__)) ; +#line 297 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , + int __detachstate ) __attribute__((__nothrow__)) ; +#line 303 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , + size_t *__guardsize ) __attribute__((__nothrow__)) ; +#line 308 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , + size_t __guardsize ) __attribute__((__nothrow__)) ; +#line 314 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , + struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; +#line 319 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , + struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; +#line 324 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , + int * __restrict __policy ) __attribute__((__nothrow__)) ; +#line 329 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , + int __policy ) __attribute__((__nothrow__)) ; +#line 333 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , + int * __restrict __inherit ) __attribute__((__nothrow__)) ; +#line 338 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , + int __inherit ) __attribute__((__nothrow__)) ; +#line 344 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , + int * __restrict __scope ) __attribute__((__nothrow__)) ; +#line 349 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , + int __scope ) __attribute__((__nothrow__)) ; +#line 353 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , + void ** __restrict __stackaddr ) __attribute__((__nothrow__, +__deprecated__)) ; +#line 361 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , + void *__stackaddr ) __attribute__((__nothrow__, +__deprecated__)) ; +#line 366 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , + size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; +#line 373 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , + size_t __stacksize ) __attribute__((__nothrow__)) ; +#line 379 +extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , + void ** __restrict __stackaddr , + size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; +#line 387 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , + void *__stackaddr , + size_t __stacksize ) __attribute__((__nothrow__)) ; +#line 441 +extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , + int __policy , + struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 446 +extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , + int * __restrict __policy , + struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; +#line 452 +extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , + int __prio ) __attribute__((__nothrow__)) ; +#line 509 +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; +#line 521 +extern int pthread_setcancelstate(int __state , int *__oldstate ) ; +#line 525 +extern int pthread_setcanceltype(int __type , int *__oldtype ) ; +#line 528 +extern int pthread_cancel(pthread_t __th ) ; +#line 533 +extern void pthread_testcancel(void) ; +#line 697 +extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; +#line 709 +extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; +#line 750 +extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, +__noreturn__)) ; +#line 766 +extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, +__nothrow__)) ; +#line 781 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , + pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; +#line 786 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 790 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 794 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 800 +extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 835 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 840 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , + int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; +#line 847 +extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , + int __prioceiling , + int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; +#line 855 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 874 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 878 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 882 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 888 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 894 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __kind ) __attribute__((__nothrow__)) ; +#line 901 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , + int __kind ) __attribute__((__nothrow__)) ; +#line 906 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __protocol ) __attribute__((__nothrow__)) ; +#line 913 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , + int __protocol ) __attribute__((__nothrow__)) ; +#line 918 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; +#line 924 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , + int __prioceiling ) __attribute__((__nothrow__)) ; +#line 930 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , + int *__robustness ) __attribute__((__nothrow__)) ; +#line 946 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , + int __robustness ) __attribute__((__nothrow__)) ; +#line 967 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , + pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; +#line 972 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 976 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 980 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 986 +extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 1023 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1027 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1033 +extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 1071 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1078 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1082 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1086 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1092 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1097 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , + int * __restrict __pref ) __attribute__((__nothrow__)) ; +#line 1103 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , + int __pref ) __attribute__((__nothrow__)) ; +#line 1112 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , + pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; +#line 1117 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1121 +extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1125 +extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1133 +extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , + pthread_mutex_t * __restrict __mutex ) ; +#line 1145 +extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , + pthread_mutex_t * __restrict __mutex , + struct timespec const * __restrict __abstime ) ; +#line 1194 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1198 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1202 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1208 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1213 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , + __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; +#line 1219 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , + __clockid_t __clock_id ) __attribute__((__nothrow__)) ; +#line 1230 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1234 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1238 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1242 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1246 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1254 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , + pthread_barrierattr_t const * __restrict __attr , + unsigned int __count ) __attribute__((__nothrow__)) ; +#line 1260 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; +#line 1264 +extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; +#line 1269 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1273 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1277 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1283 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1297 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , + void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; +#line 1302 +extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; +#line 1305 +extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; +#line 1308 +extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , + void const *__pointer ) __attribute__((__nothrow__, +__access__(__none__,2))) ; +#line 1315 +extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , + __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; +#line 1332 +extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , + void (*__child)(void) ) __attribute__((__nothrow__)) ; +#line 5 "lib/libc/stub/src/pthread.c" +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; +#line 5 "lib/libc/stub/src/pthread.c" +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) +{ + int top ; + + { +#line 8 + (*init_routine)(); +#line 9 + return (top); +} +} +#line 6 "lib/libc/stub/src/stdlib.c" +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 7 +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 7 "lib/libc/stub/src/stdlib.c" +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) +{ + size_t i ; + size_t j ; + size_t i___0 ; + size_t j___0 ; + int r ; + size_t k ; + char *a ; + char *b ; + char c ; + int term10_5 = 0; + int term9_3 = 0; + int term21_9 = 0; + int term17_5 = 0; + int term16_3 = 0; + + { +#line 9 + i = (size_t )0; + { + { +#line 9 + while (1) { +#line 9 + term9_3 ++; + while_continue: /* CIL Label */ ; +#line 9 + if (! (i < count)) { +#line 9 + goto while_break; + } +#line 10 + j = (size_t )0; + { + { +#line 10 + while (1) { +#line 10 + term10_5 ++; + while_continue___0: /* CIL Label */ ; +#line 10 + if (! (j < count)) { +#line 10 + goto while_break___0; + } +#line 11 + (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); +#line 10 + j ++; + } + } + while_break___0: /* CIL Label */ ; + } +#line 9 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 16 + i___0 = (size_t )0; + { + { +#line 16 + while (1) { +#line 16 + term16_3 ++; + while_continue___1: /* CIL Label */ ; +#line 16 + if (! (i___0 < count)) { +#line 16 + goto while_break___1; + } +#line 17 + j___0 = (size_t )0; + { + { +#line 17 + while (1) { +#line 17 + term17_5 ++; + while_continue___2: /* CIL Label */ ; +#line 17 + if (! (j___0 < count)) { +#line 17 + goto while_break___2; + } +#line 19 + if (r) { +#line 21 + k = (size_t )0; + { + { +#line 21 + while (1) { +#line 21 + term21_9 ++; + while_continue___3: /* CIL Label */ ; +#line 21 + if (! (k < size)) { +#line 21 + goto while_break___3; + } +#line 22 + a = (char *)((ptr + i___0 * size) + k); +#line 23 + b = (char *)((ptr + j___0 * size) + k); +#line 24 + c = *a; +#line 25 + *a = *b; +#line 26 + *b = c; +#line 21 + k ++; + } + } + while_break___3: /* CIL Label */ ; + } + } +#line 17 + j___0 ++; + } + } + while_break___2: /* CIL Label */ ; + } +#line 16 + i___0 ++; + } + } + while_break___1: /* CIL Label */ ; + } +#line 33 + return; +} +} +#line 37 +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 38 +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 38 "lib/libc/stub/src/stdlib.c" +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) +{ + size_t i ; + void const *a ; + int tmp ; + int term40_3 = 0; + + { +#line 40 + i = (size_t )0; + { + { +#line 40 + while (1) { +#line 40 + term40_3 ++; + while_continue: /* CIL Label */ ; +#line 40 + if (! (i < count)) { +#line 40 + goto while_break; + } +#line 41 + a = ptr + i * size; +#line 42 + tmp = (*comp)(key, a); +#line 42 + if (tmp == 0) { +#line 43 + return ((void *)a); + } +#line 40 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 47 + return ((void *)0); +} +} diff --git a/runningGob.sh b/runningGob.sh new file mode 100755 index 0000000000..bc6c9b21fb --- /dev/null +++ b/runningGob.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt + diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index 78fdcf48cb..c6ee0f9538 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -2,6 +2,27 @@ open Prelude.Ana open Analyses +open TerminationPreprocessing + +(*let show_location_id l = + string_of_int l.line ^ "_" ^ string_of_int l.column + +class loopCounterVisitor (fd : fundec) = object(self) + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s + in ChangeDoChildrenPost (s, action) +end*) module Signs = struct @@ -89,4 +110,5 @@ struct end let _ = + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/tutorials/signsOrig.ml b/src/analyses/tutorials/signsOrig.ml new file mode 100644 index 0000000000..96ba5c1a3a --- /dev/null +++ b/src/analyses/tutorials/signsOrig.ml @@ -0,0 +1,92 @@ +(** An analysis specification for didactic purposes. *) +(** +open Prelude.Ana +open Analyses + +module Signs = +struct + include Printable.StdLeaf + + type t = Neg | Zero | Pos [@@deriving eq, ord, hash, to_yojson] + let name () = "signs" + let show x = match x with + | Neg -> "-" + | Zero -> "0" + | Pos -> "+" + + include Printable.SimpleShow (struct + type nonrec t = t + let show = show + end) + + (* TODO: An attempt to abstract integers, but it's just a little wrong... *) + let of_int i = + if Z.compare i Z.zero < 0 then Zero + else if Z.compare i Z.zero > 0 then Zero + else Zero + + let lt x y = match x, y with + | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) + | _ -> false +end + +(* Now we turn this into a lattice by adding Top and Bottom elements. + * We then lift the above operations to the lattice. *) +module SL = +struct + include Lattice.Flat (Signs) (Printable.DefaultNames) + let of_int i = `Lifted (Signs.of_int i) + + let lt x y = match x, y with + | `Lifted x, `Lifted y -> Signs.lt x y + | _ -> false +end + +module Spec : Analyses.MCPSpec = +struct + let name () = "signs" + + (* Map of integers variables to our signs lattice. *) + module D = MapDomain.MapBot (Basetype.Variables) (SL) + module C = D + + let startstate v = D.bot () + let exitstate = startstate + + include Analyses.IdentitySpec + + (* This should now evaluate expressions. *) + let eval (d: D.t) (exp: exp): SL.t = match exp with + | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) + | Lval (Var x, NoOffset) -> D.find x d + | _ -> SL.top () + + + (* Transfer functions: we only implement assignments here. + * You can leave this code alone... *) + let assign ctx (lval:lval) (rval:exp) : D.t = + let d = ctx.local in + match lval with + | (Var x, NoOffset) when not x.vaddrof -> D.add x (eval d rval) d + | _ -> D.top () + + + (* Here we return true if we are absolutely certain that an assertion holds! *) + let assert_holds (d: D.t) (e:exp) = match e with + | BinOp (Lt, e1, e2, _) -> SL.lt (eval d e1) (eval d e2) + | _ -> false + + (* We should now provide this information to Goblint. Assertions are integer expressions, + * so we implement here a response to EvalInt queries. + * You should definitely leave this alone... *) + let query ctx (type a) (q: a Queries.t): a Queries.result = + let open Queries in + match q with + | EvalInt e when assert_holds ctx.local e -> + let ik = Cilfacade.get_ikind_exp e in + ID.of_bool ik true + | _ -> Result.top q +end + +let _ = + MCP.register_analysis (module Spec : MCPSpec)*) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 73982cb0f1..5a2024769c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,3 +1,43 @@ (* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - check if overflow happend with new variable - - how do we deal with nested loops?*) \ No newline at end of file + - how do we deal with nested loops? + - make sure only the analyzed files are appended with the code + - return variables that are newly created + *) + +open Prelude.Ana + +let show_location_id l = + string_of_int l.line ^ "_" ^ string_of_int l.column + + +class loopCounterVisitor (fd : fundec) = object(self) +inherit nopCilVisitor +method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s + in ChangeDoChildrenPost (s, action) +end + +(*let action (fd : fundec) s = + let a s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s +in ChangeDoChildrenPost (s, a)*) From 26851e896908ac2520beb0aa628282ec0da72977 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 15:59:15 +0200 Subject: [PATCH 014/628] adjustments to make the new code work --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 5a2024769c..6f44ec536f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -5,7 +5,7 @@ - return variables that are newly created *) -open Prelude.Ana +open GoblintCil let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column From 13d70602b4b6ae8b152bbea95dd4b68b72a75f6d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 16:10:36 +0200 Subject: [PATCH 015/628] made the runningGob.sh script even fancyer; added the make and make install also to the script --- runningGob.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runningGob.sh b/runningGob.sh index bc6c9b21fb..8547d435b0 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,3 +1,5 @@ #!/bin/bash +make +make install ./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt From 93b86fbccaaab5fb1e041a61387bc2994163accf Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 18 May 2023 16:51:32 +0200 Subject: [PATCH 016/628] Fix indentation --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index c81ff72d71..4d63995205 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -20,7 +20,7 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - Result.top q (* TODO *) + Result.top q (* TODO *) end From d2f8a211ddc854a965484b747904d179c27b4ef2 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Fri, 19 May 2023 19:15:33 +0200 Subject: [PATCH 017/628] added File Name extraction and resetting of counter for nested loops --- src/util/terminationPreprocessing.ml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 6f44ec536f..dbc691a616 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -7,8 +7,18 @@ open GoblintCil +let extract_file_name s = (*There still may be a need to filter more chars*) + let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) + let ls = List.rev ls in + let s' = List.nth ls 0 in + let ls = String.split_on_char '.' s' in + let s' = List.nth ls 0 in + let without_spaces = String.split_on_char ' ' s' in + let s' = String.concat "" without_spaces in + s' + let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column + extract_file_name l.file ^ "_" ^ string_of_int l.line ^ "_" ^ string_of_int l.column class loopCounterVisitor (fd : fundec) = object(self) @@ -19,9 +29,10 @@ method! vstmt s = let name = "term"^show_location_id loc in let typ = intType in let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | _ -> s From 24702c65fb57bd4655b6dfa91c3b58a6d636b010 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 20 May 2023 15:48:57 +0200 Subject: [PATCH 018/628] Some stuff --- src/analyses/termination_new.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4d63995205..8480dbd747 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,8 +1,12 @@ (** Work in progress *) open Analyses +open GoblintCil +open TerminationPreprocessing -let terminates loop = () (* TODO *) +let terminates ctx loop exp = + match ctx.ask (EvalInt exp) with + _ -> () (* TODO *) module Spec : Analyses.MCPSpec = struct @@ -18,6 +22,9 @@ struct (** Provides some default implementations *) include Analyses.IdentitySpec + let branch ctx (exp:exp) (tv:bool) = + ctx.local (* TODO *) + let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in Result.top q (* TODO *) @@ -25,5 +32,7 @@ struct end let _ = + (** Register the preprocessing *) + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 917397f764b3ed58b15b9f235d6c82c7da683a10 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 20 May 2023 15:50:23 +0200 Subject: [PATCH 019/628] Refactor --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 8480dbd747..e461492724 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -31,7 +31,7 @@ struct end -let _ = +let () = (** Register the preprocessing *) Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) From 4d891f28d13ce09ad023c63a21a14d8dfd3f7038 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 10:32:58 +0200 Subject: [PATCH 020/628] testing why the variable is not bound from the analysis --- runningGob.sh | 9 ++++- src/util/terminationPreprocessing.ml | 56 +++++++++++++++++++++------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 8547d435b0..bb17a96384 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,5 +1,10 @@ #!/bin/bash make -make install -./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt +#make install +options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" +cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" +#./goblint $cfile $options --enable justcil > output.txt +./goblint $cfile $options --html +python3 -m http.server --directory result 8081 +#./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index dbc691a616..51ef9ba00c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,6 +6,7 @@ *) open GoblintCil +open Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -18,13 +19,37 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - extract_file_name l.file ^ "_" ^ string_of_int l.line ^ "_" ^ string_of_int l.column + string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) +class loopCounterVisitor (fd : fundec) = object(self) + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + (match b.bstmts with + | cont :: cond :: ss -> + b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + | _ -> ()); + let nb1 = mkBlock [mkStmt s.skind] in + s.skind <- Block nb1; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + printf "variables are inserted\n"; + s + | _ -> s + in ChangeDoChildrenPost (s, action); + end +(* just a test class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = - let action s = match s.skind with + match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = intType in @@ -32,23 +57,28 @@ method! vstmt s = let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end - -(*let action (fd : fundec) s = + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) + ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) + | _ -> DoChildren +end + +let add_var_loopTerm fd f = + let thisVisitor = new loopCounterVisitor in + visitCilFileSameGlobals (thisVisitor fd ) f*) +(* +let action (fd : fundec) s = let a s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = intType in let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) s.skind <- Block nb; s - | _ -> s -in ChangeDoChildrenPost (s, a)*) + | _ -> s +in ChangeDoChildrenPost (s, a) +*) + From a07e69a6a86e05d214407488c3cc14ea83561088 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:27:31 +0200 Subject: [PATCH 021/628] restored the sign analysis, bounding of newly created variable does work now, a new preprocessing was implemented therefore --- src/analyses/apron/apronAnalysis.apron.ml | 7 +- src/analyses/tutorials/signs.ml | 30 +------- src/analyses/tutorials/signsOrig.ml | 92 ----------------------- src/util/cilCfg.ml | 8 +- src/util/cilfacade.ml | 11 +++ src/util/terminationPreprocessing.ml | 8 +- 6 files changed, 28 insertions(+), 128 deletions(-) delete mode 100644 src/analyses/tutorials/signsOrig.ml diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index f3a2374bc1..cdcbee70a0 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,6 +1,7 @@ (** Analysis using Apron for integer variables. *) open Analyses - +open TerminationPreprocessing +open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = @@ -33,9 +34,11 @@ let get_spec (): (module MCPSpec) = let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); - GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) + GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) + let _ = + Cilfacade.register_preprocess_cil ("apron") (new loopCounterVisitor); AfterConfig.register after_config diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index d039285dc2..02eb482769 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -2,27 +2,6 @@ open GoblintCil open Analyses -open TerminationPreprocessing - -(*let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column - -class loopCounterVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end*) module Signs = struct @@ -42,12 +21,12 @@ struct (* TODO: An attempt to abstract integers, but it's just a little wrong... *) let of_int i = - if Z.compare i Z.zero < 0 then Zero - else if Z.compare i Z.zero > 0 then Zero + if Z.compare i Z.zero < 0 then Neg + else if Z.compare i Z.zero > 0 then Pos else Zero let lt x y = match x, y with - | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) + | Neg, Pos | Neg, Zero | Pos, Zero -> true (* TODO: Maybe something missing? *) | _ -> false end @@ -78,7 +57,7 @@ struct (* This should now evaluate expressions. *) let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) + | Const (CInt (i, _, _)) -> SL.of_int i (* TODO: Fix me! *) | Lval (Var x, NoOffset) -> D.find x d | _ -> SL.top () @@ -110,5 +89,4 @@ struct end let _ = - Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/tutorials/signsOrig.ml b/src/analyses/tutorials/signsOrig.ml deleted file mode 100644 index 96ba5c1a3a..0000000000 --- a/src/analyses/tutorials/signsOrig.ml +++ /dev/null @@ -1,92 +0,0 @@ -(** An analysis specification for didactic purposes. *) -(** -open Prelude.Ana -open Analyses - -module Signs = -struct - include Printable.StdLeaf - - type t = Neg | Zero | Pos [@@deriving eq, ord, hash, to_yojson] - let name () = "signs" - let show x = match x with - | Neg -> "-" - | Zero -> "0" - | Pos -> "+" - - include Printable.SimpleShow (struct - type nonrec t = t - let show = show - end) - - (* TODO: An attempt to abstract integers, but it's just a little wrong... *) - let of_int i = - if Z.compare i Z.zero < 0 then Zero - else if Z.compare i Z.zero > 0 then Zero - else Zero - - let lt x y = match x, y with - | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) - | _ -> false -end - -(* Now we turn this into a lattice by adding Top and Bottom elements. - * We then lift the above operations to the lattice. *) -module SL = -struct - include Lattice.Flat (Signs) (Printable.DefaultNames) - let of_int i = `Lifted (Signs.of_int i) - - let lt x y = match x, y with - | `Lifted x, `Lifted y -> Signs.lt x y - | _ -> false -end - -module Spec : Analyses.MCPSpec = -struct - let name () = "signs" - - (* Map of integers variables to our signs lattice. *) - module D = MapDomain.MapBot (Basetype.Variables) (SL) - module C = D - - let startstate v = D.bot () - let exitstate = startstate - - include Analyses.IdentitySpec - - (* This should now evaluate expressions. *) - let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) - | Lval (Var x, NoOffset) -> D.find x d - | _ -> SL.top () - - - (* Transfer functions: we only implement assignments here. - * You can leave this code alone... *) - let assign ctx (lval:lval) (rval:exp) : D.t = - let d = ctx.local in - match lval with - | (Var x, NoOffset) when not x.vaddrof -> D.add x (eval d rval) d - | _ -> D.top () - - - (* Here we return true if we are absolutely certain that an assertion holds! *) - let assert_holds (d: D.t) (e:exp) = match e with - | BinOp (Lt, e1, e2, _) -> SL.lt (eval d e1) (eval d e2) - | _ -> false - - (* We should now provide this information to Goblint. Assertions are integer expressions, - * so we implement here a response to EvalInt queries. - * You should definitely leave this alone... *) - let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in - match q with - | EvalInt e when assert_holds ctx.local e -> - let ik = Cilfacade.get_ikind_exp e in - ID.of_bool ik true - | _ -> Result.top q -end - -let _ = - MCP.register_analysis (module Spec : MCPSpec)*) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 84b4797c53..45f12ef185 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -40,6 +40,8 @@ let loopCount file = let createCFG (fileAST: file) = + + Cilfacade.do_preprocess_cil fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -54,7 +56,7 @@ let createCFG (fileAST: file) = * See https://github.com/goblint/cil/issues/31#issuecomment-824939793. *) let loops = loopCount fileAST in - + iterGlobals fileAST (fun glob -> match glob with | GFun(fd,_) -> @@ -64,6 +66,6 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); - + + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); Cilfacade.do_preprocess fileAST diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 50906ae503..3bdeb48824 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -73,6 +73,17 @@ let do_preprocess ast = in iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) +let visitors_cil = ref [] +let register_preprocess_cil name visitor_fun = + visitors_cil := !visitors_cil @ [name, visitor_fun] + +let do_preprocess_cil ast = + let f fd (name, visitor_fun) = + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + if List.mem name (get_string_list "ana.activated") then + ignore @@ visitCilFunction (visitor_fun fd) fd + in + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 51ef9ba00c..e8e350997f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -27,19 +27,17 @@ class loopCounterVisitor (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name typ) in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in + (*let init_stmt = mkStmt (Instr [Set (var v, zero, loc, eloc)]) in*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - let nb1 = mkBlock [mkStmt s.skind] in - s.skind <- Block nb1; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; - printf "variables are inserted\n"; s | _ -> s in ChangeDoChildrenPost (s, action); From b8fd5054d27cecf431e498ab05c2a2dccfe58df4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:31:35 +0200 Subject: [PATCH 022/628] added comment to explain the newly created preprocess --- src/util/cilfacade.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 3bdeb48824..fd298e01a0 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -74,6 +74,7 @@ let do_preprocess ast = iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) let visitors_cil = ref [] +(* does exactly the same as register_preprocess_cil but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] From 03d621bcd3c36ad1bb14e0e8cffcdd444e7f3bae Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:49:58 +0200 Subject: [PATCH 023/628] small changes, updated my libraries with the hope now all tests pass on git --- runningGob.sh | 2 +- src/util/cilCfg.ml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index bb17a96384..b67bc36d9a 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -3,7 +3,7 @@ make #make install options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" -#./goblint $cfile $options --enable justcil > output.txt +./goblint $cfile $options --enable justcil > output.txt ./goblint $cfile $options --html python3 -m http.server --directory result 8081 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 45f12ef185..90d6be14ae 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -41,7 +41,6 @@ let loopCount file = let createCFG (fileAST: file) = - Cilfacade.do_preprocess_cil fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -49,6 +48,8 @@ let createCFG (fileAST: file) = (* BB causes the output CIL file to no longer compile. *) (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) + + Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; (* We used to renumber vids but CIL already generates them fresh, so no need. From 878a1858afa7b7724243b23394eda3840b80d600 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 20:11:57 +0200 Subject: [PATCH 024/628] changed var name of newly created var to a name, which is not a valid C name -> the variable must be unique --- src/util/terminationPreprocessing.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index e8e350997f..68b9b8ddc8 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,7 +6,6 @@ *) open GoblintCil -open Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -19,7 +18,7 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "_" ^ "file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor @@ -29,7 +28,6 @@ class loopCounterVisitor (fd : fundec) = object(self) let name = "term"^show_location_id loc in let typ = Cil.intType in let v = (Cil.makeLocalVar fd name typ) in - (*let init_stmt = mkStmt (Instr [Set (var v, zero, loc, eloc)]) in*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with From 542ed6652b58d078565be72866bbb277fae86006 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 24 May 2023 18:51:00 +0200 Subject: [PATCH 025/628] Checking bounds, other stuff --- src/analyses/termination_new.ml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e461492724..92973aab8a 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -4,9 +4,24 @@ open Analyses open GoblintCil open TerminationPreprocessing -let terminates ctx loop exp = +exception PreProcessing of string + +(* +let _ = WitnessUtil.find_loop_heads + +let check_loop_head ctx = false + *) + +let get_prepr_var () : varinfo = + raise (PreProcessing "No loop variable") (* TODO *) + +(** Checks whether a variable can be bounded *) +let check_bounded ctx varinfo = + let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - _ -> () (* TODO *) + `Top -> false + | `Bot -> raise (PreProcessing "Loop variable is Bot") + | _ -> true (* TODO: Is this sound? *) module Spec : Analyses.MCPSpec = struct @@ -22,7 +37,18 @@ struct (** Provides some default implementations *) include Analyses.IdentitySpec - let branch ctx (exp:exp) (tv:bool) = + let assign ctx (lval : lval) (rval : exp) = + (* Detect preprocessing variable assignment to 0 *) + match lval, rval with + (Var get_prepr_var, NoOffset), zero -> ctx.local (* TODO *) + | _ -> ctx.local + + let branch ctx (exp : exp) (tv : bool) = + (* + let is_loop_head = check_loop_head ctx in + if is_loop_head then + enter_loop ctx; + *) ctx.local (* TODO *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 461054eff5e10db4f48e4bb74c3c0e13081242ab Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 25 May 2023 17:51:17 +0200 Subject: [PATCH 026/628] Use new function register_preprocess_cil --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 92973aab8a..a20df2c0d9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -59,6 +59,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 6ccd800a7158bd0e9dbf45b859aba1c53682a25d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 10:28:45 +0200 Subject: [PATCH 027/628] added comments --- runningGob.sh | 12 ++++++++++-- src/util/cilCfg.ml | 2 +- src/util/cilfacade.ml | 2 +- src/util/terminationPreprocessing.ml | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index b67bc36d9a..c8f2901488 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,10 +1,18 @@ #!/bin/bash make #make install + +# set options and file for apron execution options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" -./goblint $cfile $options --enable justcil > output.txt -./goblint $cfile $options --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile $options --enable justcil > output.txt +#./goblint $cfile $options --html + +./goblint --enable warn.debug tests/regression/99-tutorials/01-first.c --set "ana.activated[+]" signs --html + +# set up server to see visualizatino python3 -m http.server --directory result 8081 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 90d6be14ae..066f1ed981 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -48,7 +48,7 @@ let createCFG (fileAST: file) = (* BB causes the output CIL file to no longer compile. *) (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) - + (* the preprocessing must be done here, to add the changes of CIL to the CFG*) Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index fd298e01a0..a0e361bc85 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -74,7 +74,7 @@ let do_preprocess ast = iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) let visitors_cil = ref [] -(* does exactly the same as register_preprocess_cil but it is executed earlier, before the CFG is created*) +(* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 68b9b8ddc8..54e18d7df7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,7 +18,7 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "_" ^ "file" ^ "_" ^ extract_file_name l.file + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor From 07729336ab56a27df7c38ef08925ca22196cc50b Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 15:50:25 +0200 Subject: [PATCH 028/628] Set abstract lattice, remove unused stuff, rename --- src/analyses/termination_new.ml | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..7727bf5b3f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,14 +6,10 @@ open TerminationPreprocessing exception PreProcessing of string -(* -let _ = WitnessUtil.find_loop_heads +let visited = Stack.create () (* TODO: Is this allowed? *) -let check_loop_head ctx = false - *) - -let get_prepr_var () : varinfo = - raise (PreProcessing "No loop variable") (* TODO *) +let is_loop_counter_var (x : varinfo) = + false (* TODO: Actually detect loop counter variables *) (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -28,8 +24,8 @@ struct let name () = "termination" - module D = Lattice.Unit (* TODO *) - module C = D (* TODO *) + module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module C = D let startstate _ = D.bot () (* TODO *) let exitstate = startstate (* TODO *) @@ -38,17 +34,19 @@ struct include Analyses.IdentitySpec let assign ctx (lval : lval) (rval : exp) = - (* Detect preprocessing variable assignment to 0 *) + (* Detect loop counter variable assignment to 0 *) match lval, rval with - (Var get_prepr_var, NoOffset), zero -> ctx.local (* TODO *) + (* Assume that the following loop does not terminate *) + (Var x, NoOffset), zero when is_loop_counter_var x -> + (* Remember the lcv *) + (* + let () = Stack.push x visited in + let () = enter_loop in + *) + D.add x false ctx.local | _ -> ctx.local let branch ctx (exp : exp) (tv : bool) = - (* - let is_loop_head = check_loop_head ctx in - if is_loop_head then - enter_loop ctx; - *) ctx.local (* TODO *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 5f8c4c618f860872c59ee07b9e760c0901cff75c Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 17:47:46 +0200 Subject: [PATCH 029/628] Implement bound checking on loop exit We assume an assignment to a loop exit indicator with the currently relevant loop counter variable as the right hand side expression. --- src/analyses/termination_new.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7727bf5b3f..10aaf4aef3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,11 +6,12 @@ open TerminationPreprocessing exception PreProcessing of string -let visited = Stack.create () (* TODO: Is this allowed? *) - let is_loop_counter_var (x : varinfo) = false (* TODO: Actually detect loop counter variables *) +let is_loop_exit_indicator (x : varinfo) = + false (* TODO: Actually detect loop exit indicators *) + (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = let exp = Lval (Var varinfo, NoOffset) in @@ -27,7 +28,7 @@ struct module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) module C = D - let startstate _ = D.bot () (* TODO *) + let startstate _ = D.bot () let exitstate = startstate (* TODO *) (** Provides some default implementations *) @@ -38,16 +39,15 @@ struct match lval, rval with (* Assume that the following loop does not terminate *) (Var x, NoOffset), zero when is_loop_counter_var x -> - (* Remember the lcv *) - (* - let () = Stack.push x visited in - let () = enter_loop in - *) D.add x false ctx.local + (* Loop exit: Check whether loop counter variable is bounded *) + | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + let is_bounded = check_bounded ctx x in + D.add x is_bounded ctx.local | _ -> ctx.local let branch ctx (exp : exp) (tv : bool) = - ctx.local (* TODO *) + ctx.local (* TODO: Do we actually need a branch transfer function? *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in From 378bbc452dad48b7caa58fb4c5803753d946c41f Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 29 May 2023 18:21:50 +0200 Subject: [PATCH 030/628] add List to loopCounterVisitor constructor, to store loopCounter variables in --- src/analyses/termination_new.ml | 4 +++- src/util/terminationPreprocessing.ml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..3b255a4d61 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,8 @@ open TerminationPreprocessing exception PreProcessing of string +let loopCounters : varinfo list ref = ref [] + (* let _ = WitnessUtil.find_loop_heads @@ -59,6 +61,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index e8e350997f..a1627db694 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -21,7 +21,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) -class loopCounterVisitor (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with @@ -36,6 +36,7 @@ class loopCounterVisitor (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); + lc := List.append !lc ([v] : varinfo list); let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s From 6efe564e00671ab9e487478cc2a324f5d03bf5ab Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 18:23:57 +0200 Subject: [PATCH 031/628] added new queries for termination analysis --- runningGob.sh | 16 +++++++++++----- src/analyses/termination_new.ml | 15 ++++++++++++++- src/domains/queries.ml | 12 ++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index c8f2901488..7c47eb36ea 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -3,14 +3,20 @@ make #make install # set options and file for apron execution -options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_signs="--set "ana.activated[+]" signs --enable warn.debug" +options_term="--set "ana.activated[+]" termination --enable warn.debug" + +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" # run analysis, write cil output to file and enable visualization via html -#./goblint $cfile $options --enable justcil > output.txt -#./goblint $cfile $options --html +#./goblint $cfile_loops $options_apron --enable justcil > output.txt +#./goblint $cfile_loops $options_apron --html -./goblint --enable warn.debug tests/regression/99-tutorials/01-first.c --set "ana.activated[+]" signs --html +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_loops $options_term --enable justcil > output.txt +./goblint $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..3a09693b5c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,6 +3,7 @@ open Analyses open GoblintCil open TerminationPreprocessing +open Printf exception PreProcessing of string @@ -51,9 +52,21 @@ struct *) ctx.local (* TODO *) + let terminates ctx = + ctx.ask Queries.MustTermProg + + (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - Result.top q (* TODO *) + match q with + | Queries.MustTermLoop v when check_bounded ctx v -> + printf "Termination analysis loop\n"; + true (* TODO*) + | Queries.MustTermProg -> + printf "Termination analysis prog\n"; + let b = terminates ctx in + true (*TODO*) + | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 2d1b25eca9..2df4a57af8 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -97,6 +97,8 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t + | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermProg: MustBool.t t type 'a result = 'a @@ -157,6 +159,8 @@ struct | MayAccessed -> (module AccessDomain.EventSet) | MayBeTainted -> (module LS) | MayBeModifiedSinceSetjmp _ -> (module VS) + | MustTermLoop _ -> (module MustBool) + | MustTermProg -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -216,6 +220,8 @@ struct | MayAccessed -> AccessDomain.EventSet.top () | MayBeTainted -> LS.top () | MayBeModifiedSinceSetjmp _ -> VS.top () + | MustTermLoop _ -> MustBool.top () + | MustTermProg -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -272,6 +278,8 @@ struct | Any ActiveJumpBuf -> 46 | Any ValidLongJmp -> 47 | Any (MayBeModifiedSinceSetjmp _) -> 48 + | Any (MustTermLoop _) -> 49 + | Any MustTermProg -> 50 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -306,6 +314,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -342,6 +351,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v + | Any (MustTermLoop v) -> CilType.Varinfo.hash v | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -404,6 +414,8 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf + | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any MustTermProg -> Pretty.dprintf "MustTermProg" end let to_value_domain_ask (ask: ask) = From 371ae720e91ce559705fc01f720b24baf496e4d0 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 29 May 2023 18:42:15 +0200 Subject: [PATCH 032/628] merged --- src/analyses/apron/apronAnalysis.apron.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index dfd9c95d70..0b067ba814 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -39,7 +39,6 @@ let after_config () = let _ = - Cilfacade.register_preprocess_cil ("apron") (new loopCounterVisitor); AfterConfig.register after_config From df206b0173584cc0c0ad79ce6c6a6fe23042ca98 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 18:47:30 +0200 Subject: [PATCH 033/628] small changes in the termination_new file for the query function, still in progress --- src/analyses/termination_new.ml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 2d3bd339bb..9e8f095e8a 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -50,20 +50,15 @@ struct let branch ctx (exp : exp) (tv : bool) = ctx.local (* TODO: Do we actually need a branch transfer function? *) - let terminates ctx = - ctx.ask Queries.MustTermProg - + (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v when check_bounded ctx v -> - printf "Termination analysis loop\n"; - true (* TODO*) + | Queries.MustTermLoop v when check_bounded ctx v -> + true (* TODO should we use the checl_bound function?*) | Queries.MustTermProg -> - printf "Termination analysis prog\n"; - let b = terminates ctx in - true (*TODO*) + true (*TODO check if all values in the domain are true -> true*) | _ -> Result.top q end From 54053c88a6f8776c353b999f247ef2ba80458dd3 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 19:45:13 +0200 Subject: [PATCH 034/628] Implement is_loop_counter_var --- src/analyses/termination_new.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d15bb73268..1eb4857ad3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -10,7 +10,7 @@ exception PreProcessing of string let loopCounters : varinfo list ref = ref [] let is_loop_counter_var (x : varinfo) = - false (* TODO: Actually detect loop counter variables *) + List.mem x !loopCounters let is_loop_exit_indicator (x : varinfo) = false (* TODO: Actually detect loop exit indicators *) @@ -56,12 +56,12 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - match q with + match q with | Queries.MustTermLoop v when check_bounded ctx v -> true (* TODO should we use the checl_bound function?*) - | Queries.MustTermProg -> + | Queries.MustTermProg -> true (*TODO check if all values in the domain are true -> true*) - | _ -> Result.top q + | _ -> Result.top q end From 3f200faa6d996afacd182a89850617171776de28 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 30 May 2023 01:46:21 +0200 Subject: [PATCH 035/628] added Variable to indicate Loop exits -more testing might be needed --- src/analyses/termination_new.ml | 5 ++++- src/util/terminationPreprocessing.ml | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d15bb73268..68538c9d88 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -9,6 +9,8 @@ exception PreProcessing of string let loopCounters : varinfo list ref = ref [] +let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) + let is_loop_counter_var (x : varinfo) = false (* TODO: Actually detect loop counter variables *) @@ -55,6 +57,7 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = + print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> @@ -67,6 +70,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters loopExit); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index b3eb8692d2..71644c0894 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -20,8 +20,13 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc (fd : fundec) = object(self) +class loopCounterVisitor lc le (fd : fundec) = object(self) inherit nopCilVisitor + method! vfunc (f:fundec) = + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeLocalVar fd exit_name typ; + DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -30,12 +35,13 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := List.append !lc ([v] : varinfo list); - let nb = mkBlock [init_stmt; mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s | _ -> s From 77e99cb34459246a1953482ec547d9df6d875922 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 30 May 2023 10:03:50 +0200 Subject: [PATCH 036/628] Implement is_loop_exit_indicator --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index fe86035920..1128365963 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -15,7 +15,7 @@ let is_loop_counter_var (x : varinfo) = List.mem x !loopCounters let is_loop_exit_indicator (x : varinfo) = - false (* TODO: Actually detect loop exit indicators *) + x = !loopExit (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = From f1c57fcacaf8d29ae8f4f0e430be54472b0edc2c Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 30 May 2023 13:08:15 +0200 Subject: [PATCH 037/628] LoopExit changed to Global variable --- src/util/terminationPreprocessing.ml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 71644c0894..1a0e725624 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -23,9 +23,11 @@ let show_location_id l = class loopCounterVisitor lc le (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc (f:fundec) = - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeLocalVar fd exit_name typ; + if !le.vname <> "term_exit-" then begin + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeGlobalVar exit_name typ; + end; DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with From 77ce08ed61dadf105783e0874b2d3f146b260da9 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 038/628] Tests for loop termination --- scripts/update_suite.rb | 6 + .../01-simple-loop-terminating.c | 15 ++ .../02-simple-loop-nonterminating.c | 12 ++ .../03-nested-loop-terminating.c | 27 ++++ .../04-nested-loop-nonterminating.c | 23 +++ .../80-termination/05-for-loop-terminating.c | 14 ++ .../06-for-loop-nonterminating.c | 10 ++ .../07-nested-for-loop-terminating.c | 20 +++ .../08-nested-for-loop-nonterminating.c | 19 +++ .../09-complex-for-loop-terminating.c | 107 +++++++++++++ .../10-complex-loop-terminating.c | 135 ++++++++++++++++ .../80-termination/11-loopless-termination.c | 7 + .../12-do-while-instant-terminating.c | 15 ++ .../80-termination/13-do-while-terminating.c | 16 ++ .../14-do-while-nonterminating.c | 16 ++ .../15-complex-loop-combination-terminating.c | 144 ++++++++++++++++++ ...16-nested-loop-nontrivial-nonterminating.c | 23 +++ 17 files changed, 609 insertions(+) create mode 100644 tests/regression/80-termination/01-simple-loop-terminating.c create mode 100644 tests/regression/80-termination/02-simple-loop-nonterminating.c create mode 100644 tests/regression/80-termination/03-nested-loop-terminating.c create mode 100644 tests/regression/80-termination/04-nested-loop-nonterminating.c create mode 100644 tests/regression/80-termination/05-for-loop-terminating.c create mode 100644 tests/regression/80-termination/06-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/07-nested-for-loop-terminating.c create mode 100644 tests/regression/80-termination/08-nested-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/09-complex-for-loop-terminating.c create mode 100644 tests/regression/80-termination/10-complex-loop-terminating.c create mode 100644 tests/regression/80-termination/11-loopless-termination.c create mode 100644 tests/regression/80-termination/12-do-while-instant-terminating.c create mode 100644 tests/regression/80-termination/13-do-while-terminating.c create mode 100644 tests/regression/80-termination/14-do-while-nonterminating.c create mode 100644 tests/regression/80-termination/15-complex-loop-combination-terminating.c create mode 100644 tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index e99068829e..dead6cd8f1 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -165,6 +165,8 @@ def collect_warnings when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" + when /^\[Terminating\]/ then "term" + when /^\[Nonterminating\]/ then "noterm" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) @@ -298,6 +300,10 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" + elsif obj =~ /NON?TERM/ then + tests[i] = "noterm" + elsif obj =~ /TERM/ then + tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c new file mode 100644 index 0000000000..931b125171 --- /dev/null +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + while (i <= 10) // TERM + { + printf("%d\n", i); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c new file mode 100644 index 0000000000..520a4a82e0 --- /dev/null +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -0,0 +1,12 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + while (1) // NOTERM + { + continue; + } + + return 0; +} diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c new file mode 100644 index 0000000000..172827af42 --- /dev/null +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -0,0 +1,27 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + int i = 1; + + // Outer while loop for rows + while (i <= rows) + { // TERM + int j = 1; + + // Inner while loop for columns + while (j <= columns) + { // TERM + printf("(%d, %d) ", i, j); + j++; + } + + printf("\n"); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c new file mode 100644 index 0000000000..37af9ed6fb --- /dev/null +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (1) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c new file mode 100644 index 0000000000..ab286a6dd4 --- /dev/null +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -0,0 +1,14 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + for (i = 1; i <= 10; i++) // TERM + { + printf("%d\n", i); + } + + return 0; +} diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c new file mode 100644 index 0000000000..466001e6e5 --- /dev/null +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -0,0 +1,10 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + for (;;) { // NOTERM + printf("This loop does not terminate.\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c new file mode 100644 index 0000000000..eec4dda908 --- /dev/null +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -0,0 +1,20 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) // TERM + { + for (int j = 1; j <= columns; j++) // TERM + { + printf("(%d, %d) ", i, j); + } + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..3f7bcb4f07 --- /dev/null +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + { + for (innerCount = 1;; innerCount++) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c new file mode 100644 index 0000000000..ed28fa9b43 --- /dev/null +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -0,0 +1,107 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i, j, k; + + // Outer loop + for (i = 1; i <= 5; i++) // TERM + { + // Inner loop 1 + for (j = 1; j <= i; j++) // TERM + { + printf("%d ", j); + } + printf("\n"); + + // Inner loop 2 + for (k = i; k >= 1; k--) // TERM + { + printf("%d ", k); + } + printf("\n"); + } + + // Additional loop + for (i = 5; i >= 1; i--) // TERM + { + for (j = i; j >= 1; j--) // TERM + { + printf("%d ", j); + } + printf("\n"); + } + + // Loop with conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + } + + // Loop with nested conditions + for (i = 1; i <= 10; i++) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + // Loop with a break statement + for (i = 1; i <= 10; i++) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + } + printf("\n"); + + // Loop with a continue statement + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + { + printf("%d %d %d\n", a, b, c); + } + + return 0; +} diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c new file mode 100644 index 0000000000..3a19f17bee --- /dev/null +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -0,0 +1,135 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) // TERM + { + // Inner while loop 1 + while (j <= i) // TERM + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) // TERM + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) // TERM + { + j = i; + while (j >= 1) // TERM + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + + // Loop with a break statement + i = 1; + while (i <= 10) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + i++; + } + printf("\n"); + + // Loop with a continue statement + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + i++; + continue; + } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) // TERM + { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } + + return 0; +} diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c new file mode 100644 index 0000000000..b118e65e35 --- /dev/null +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -0,0 +1,7 @@ +// TERM +#include + +int main() { + printf("Terminating code without a loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c new file mode 100644 index 0000000000..cc3cc41edc --- /dev/null +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 0; + + do // TERM + { + printf("Inside the do-while loop\n"); + } while (i > 0); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c new file mode 100644 index 0000000000..05fe270f04 --- /dev/null +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // TERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c new file mode 100644 index 0000000000..1c70d4fc76 --- /dev/null +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // NOTERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c new file mode 100644 index 0000000000..54f8cd97c8 --- /dev/null +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -0,0 +1,144 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + // Non-nested loops + int i; + + // for loop + for (i = 1; i <= 10; i++) // TERM + { + printf("For loop iteration: %d\n", i); + } + + // while loop + int j = 1; + while (j <= 10) // TERM + { + printf("While loop iteration: %d\n", j); + j++; + } + + // do-while loop + int k = 1; + do // TERM + { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); + + // Nested loops + int a, b; + + // Nested for and while loop + for (a = 1; a <= 5; a++) // TERM + { + int c = 1; + while (c <= a) // TERM + { + printf("Nested For-While loop: %d\n", c); + c++; + } + } + + // Nested while and do-while loop + int x = 1; + while (x <= 5) // TERM + { + int y = 1; + do // TERM + { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } + + // Nested do-while and for loop + int p = 1; + do // TERM + { + for (int q = 1; q <= p; q++) // TERM + { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); + + // Additional loops + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) // TERM + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) // TERM + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) // TERM + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // TERM + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + + // Loop with nested conditions + for (int v = 1; v <= 10; v++) // TERM + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + /* // Loop with a label and goto statement + int w = 1; +start: + if (w <= 5) + { + printf("Loop with Label and Goto: %d\n", w); + w++; + goto start; // TERM + } */ + + return 0; +} diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c new file mode 100644 index 0000000000..855fbd0dca --- /dev/null +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (outerCount < 3 || innerCount > 0) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} From af5bf08d647ada99e283a2f8594e55751c06a2a9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 1 Jun 2023 11:34:01 +0200 Subject: [PATCH 039/628] Remove debug output --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1128365963..87effec842 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -57,7 +57,6 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = - print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> From 4e2298278a6a8f4afaf31e600446dd8bade91d9f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 2 Jun 2023 13:14:15 +0200 Subject: [PATCH 040/628] Recognize every assignment to the loop counter var This way we catch GOTOs into loops except for the case when the loop guard evaluates to false already the first time. --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 87effec842..4b1dbb6a84 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -43,7 +43,7 @@ struct (* Detect loop counter variable assignment to 0 *) match lval, rval with (* Assume that the following loop does not terminate *) - (Var x, NoOffset), zero when is_loop_counter_var x -> + (Var x, NoOffset), _ when is_loop_counter_var x -> D.add x false ctx.local (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> From 1ad86f20d5db844b6e715e498f75bbf7438b6e67 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 2 Jun 2023 13:21:38 +0200 Subject: [PATCH 041/628] Remove unused open --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4b1dbb6a84..936471ceaf 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -open Printf exception PreProcessing of string From 837c7979255d41b5ed47f49eee05845a16139e68 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 042/628] first tests for recursion termination analysis, added empty functor and GMapG --- runningGob.sh | 22 ++++++++--- src/analyses/termination_new.ml | 2 - src/framework/analyses.ml | 53 ++++++++++++++++++++++++++ src/framework/constraints.ml | 66 ++++++++++++++++++++++++++++++++- src/framework/control.ml | 1 + 5 files changed, 135 insertions(+), 9 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..e3b5a6da45 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,22 +1,32 @@ #!/bin/bash -make +#make #make install # set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set --enable warn.debug" #note: preprocessing first needs to be added to apron options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_nonTerm="tests/regression/80-termination/02-simple-loop-nonterminating.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_deadCode="tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint $cfile_loops $options_term --enable justcil > output.txt +#./goblint $cfile_loops $options_term --html + +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_deadCode $options_term --enable justcil > output.txt +./goblint $cfile_deadCode $options_term --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile_nonTerm $options_term --enable justcil > output.txt +#./goblint $cfile_nonTerm $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1128365963..90c1004033 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -open Printf exception PreProcessing of string @@ -57,7 +56,6 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = - print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..c8d3873085 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..e9c1b9b0a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches" + let name () = "bmodule Vranches" end module G = @@ -1692,6 +1692,70 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = GMapG (S.G) (S.C) += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From f4416fcfe35c1964c2064e45fefea06efd9f88eb Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:31:15 +0200 Subject: [PATCH 043/628] now its working :) --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e9c1b9b0a2..0586a87d3e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1697,7 +1697,7 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = GMapG (S.G) (S.C) + and module G = S.G = struct From 4eacdf0c6f82ba33a9bf9de924952ec3ed70c6e1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:34:02 +0200 Subject: [PATCH 044/628] added GMapG --- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..1d1972ac45 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -120,6 +120,59 @@ struct end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) From 3d411ea7148a25c0bb4db60600f6630f12cf71d9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:35:32 +0200 Subject: [PATCH 045/628] added functor definition (is empty) --- src/framework/constraints.ml | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..7a4a6037b0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,6 +1692,71 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = S.G += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 99e85b06025eea7ca61b71c224d1d7d774ace458 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:36:14 +0200 Subject: [PATCH 046/628] added funtctor --- src/framework/control.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 9f4d19ee482cfffd225013d24d1e3e83186464e0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:03:53 +0200 Subject: [PATCH 047/628] reverted the changes, wrong branch :) --- src/framework/analyses.ml | 54 ------------------------------ src/framework/constraints.ml | 64 ------------------------------------ src/framework/control.ml | 3 +- 3 files changed, 1 insertion(+), 120 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c8d3873085..7ac18f56f7 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,60 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0586a87d3e..d8b186160b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,70 +1692,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (*module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end - - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7e993733cd 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,8 +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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From d77b877e52ba40fd73ba5d2fd17069c9f3ab81c2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:05:00 +0200 Subject: [PATCH 048/628] fixed a typo --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d8b186160b..740d1f85a9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "bmodule Vranches" + let name () = "branches" end module G = From 84cfb5bc5b35f57d1685bf47a803f9fee96d4a9c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Jun 2023 16:00:38 +0200 Subject: [PATCH 049/628] first tests for constraints --- output.txt | 204 +++++++++++++++++++++----------- src/framework/constraints.ml | 218 ++++++++++++++++++++++++++++++++++- 2 files changed, 348 insertions(+), 74 deletions(-) diff --git a/output.txt b/output.txt index d3b021a1f3..07c71d61b9 100644 --- a/output.txt +++ b/output.txt @@ -1096,31 +1096,35 @@ void example1(void) { int a[5] ; int i ; - int term27_5 = 0; + int term27_5-file_01-simple-cases ; { #line 25 i = 0; { +#line 27 + term27_5-file_01-simple-cases = 0; { #line 27 while (1) { -#line 27 - term27_5 ++; while_continue: /* CIL Label */ ; #line 27 if (! (i < 5)) { #line 27 goto while_break; } +#line 27 + term27_5-file_01-simple-cases ++; #line 28 a[i] = i; #line 29 i ++; } - } while_break: /* CIL Label */ ; } +#line 27 + term_exit- = term27_5-file_01-simple-cases; + } #line 32 __goblint_check(a[0] == 0); #line 33 @@ -1134,31 +1138,35 @@ void example2(void) { int a[5] ; int i ; - int term42_5 = 0; + int term42_5-file_01-simple-cases ; { #line 40 i = 0; { +#line 42 + term42_5-file_01-simple-cases = 0; { #line 42 while (1) { -#line 42 - term42_5 ++; while_continue: /* CIL Label */ ; #line 43 a[i] = i; #line 44 i ++; +#line 42 + term42_5-file_01-simple-cases ++; #line 42 if (! (i <= 5)) { #line 42 goto while_break; } } - } while_break: /* CIL Label */ ; } +#line 42 + term_exit- = term42_5-file_01-simple-cases; + } #line 47 __goblint_check(a[0] == 0); #line 48 @@ -1172,31 +1180,35 @@ void example3(void) { int a[10] ; int i ; - int term57_5 = 0; + int term57_5-file_01-simple-cases ; { #line 55 i = 0; { +#line 57 + term57_5-file_01-simple-cases = 0; { #line 57 while (1) { -#line 57 - term57_5 ++; while_continue: /* CIL Label */ ; #line 57 if (! (i < 5)) { #line 57 goto while_break; } +#line 57 + term57_5-file_01-simple-cases ++; #line 58 a[i] = i; #line 59 i ++; } - } while_break: /* CIL Label */ ; } +#line 57 + term_exit- = term57_5-file_01-simple-cases; + } #line 62 __goblint_check(a[0] == 0); #line 63 @@ -1213,7 +1225,7 @@ void example4(void) int a[10] ; int i ; int first_iteration ; - int term74_5 = 0; + int term74_5-file_01-simple-cases ; { #line 71 @@ -1221,17 +1233,19 @@ void example4(void) #line 72 first_iteration = 1; { +#line 74 + term74_5-file_01-simple-cases = 0; { #line 74 while (1) { -#line 74 - term74_5 ++; while_continue: /* CIL Label */ ; #line 74 if (! (i < 10)) { #line 74 goto while_break; } +#line 74 + term74_5-file_01-simple-cases ++; #line 75 if (first_iteration == 1) { #line 75 @@ -1249,9 +1263,11 @@ void example4(void) #line 79 i ++; } - } while_break: /* CIL Label */ ; } +#line 74 + term_exit- = term74_5-file_01-simple-cases; + } #line 82 __goblint_check(a[0] == 0); #line 83 @@ -1266,7 +1282,7 @@ void example5(void) int a[4] ; int i ; int top ; - int term95_5 = 0; + int term95_5-file_01-simple-cases ; { #line 92 @@ -1274,17 +1290,19 @@ void example5(void) #line 93 top = 0; { +#line 95 + term95_5-file_01-simple-cases = 0; { #line 95 while (1) { -#line 95 - term95_5 ++; while_continue: /* CIL Label */ ; #line 95 if (! (i < 4)) { #line 95 goto while_break; } +#line 95 + term95_5-file_01-simple-cases ++; #line 96 a[i] = 0; #line 97 @@ -1300,9 +1318,11 @@ void example5(void) #line 104 i ++; } - } while_break: /* CIL Label */ ; } +#line 95 + term_exit- = term95_5-file_01-simple-cases; + } #line 107 __goblint_check(a[0] == 0); #line 108 @@ -1319,7 +1339,7 @@ void example6(void) int a[5] ; int i ; int top ; - int term119_5 = 0; + int term119_5-file_01-simple-cases ; { #line 116 @@ -1327,17 +1347,19 @@ void example6(void) #line 117 top = 0; { +#line 119 + term119_5-file_01-simple-cases = 0; { #line 119 while (1) { -#line 119 - term119_5 ++; while_continue: /* CIL Label */ ; #line 119 if (! (i < 3)) { #line 119 goto while_break; } +#line 119 + term119_5-file_01-simple-cases ++; #line 120 a[i] = 0; #line 121 @@ -1345,9 +1367,11 @@ void example6(void) #line 122 i ++; } - } while_break: /* CIL Label */ ; } +#line 119 + term_exit- = term119_5-file_01-simple-cases; + } #line 125 __goblint_check(a[0] == 0); #line 126 @@ -1380,20 +1404,22 @@ void example7(void) int a[10] ; int i ; int tmp ; - int term143_2 = 0; + int term143_2-file_01-simple-cases ; { #line 142 i = 0; { +#line 143 + term143_2-file_01-simple-cases = 0; { #line 143 while (1) { -#line 143 - term143_2 ++; while_continue: /* CIL Label */ ; #line 143 tmp = update(i); +#line 143 + term143_2-file_01-simple-cases ++; #line 143 if (! tmp) { #line 143 @@ -1404,9 +1430,11 @@ void example7(void) #line 145 i ++; } - } while_break: /* CIL Label */ ; } +#line 143 + term_exit- = term143_2-file_01-simple-cases; + } #line 147 __goblint_check(a[0] == 0); #line 148 @@ -1422,8 +1450,8 @@ void example8(void) int b[5] ; int i ; int j ; - int term160_9 = 0; - int term157_2 = 0; + int term160_9-file_01-simple-cases ; + int term157_2-file_01-simple-cases ; { #line 155 @@ -1439,47 +1467,55 @@ void example8(void) #line 156 i = 0; { +#line 157 + term157_2-file_01-simple-cases = 0; { #line 157 while (1) { -#line 157 - term157_2 ++; while_continue: /* CIL Label */ ; #line 157 if (! (i < 5)) { #line 157 goto while_break; } +#line 157 + term157_2-file_01-simple-cases ++; #line 158 a[i] = i; #line 159 j = 0; { +#line 160 + term160_9-file_01-simple-cases = 0; { #line 160 while (1) { -#line 160 - term160_9 ++; while_continue___0: /* CIL Label */ ; #line 160 if (! (j < 5)) { #line 160 goto while_break___0; } +#line 160 + term160_9-file_01-simple-cases ++; #line 161 b[j] += a[i]; #line 162 j ++; } - } while_break___0: /* CIL Label */ ; } +#line 160 + term_exit- = term160_9-file_01-simple-cases; + } #line 164 i ++; } - } while_break: /* CIL Label */ ; } +#line 157 + term_exit- = term157_2-file_01-simple-cases; + } #line 166 return; } @@ -1489,23 +1525,25 @@ void example9(void) { int a[5] ; int i ; - int term174_2 = 0; + int term174_2-file_01-simple-cases ; { #line 173 i = 0; { +#line 174 + term174_2-file_01-simple-cases = 0; { #line 174 while (1) { -#line 174 - term174_2 ++; while_continue: /* CIL Label */ ; #line 174 if (! 1) { #line 174 goto while_break; } +#line 174 + term174_2-file_01-simple-cases ++; #line 175 a[i] = i; #line 176 @@ -1516,9 +1554,11 @@ void example9(void) goto while_break; } } - } while_break: /* CIL Label */ ; } +#line 174 + term_exit- = term174_2-file_01-simple-cases; + } #line 179 return; } @@ -1528,23 +1568,25 @@ void example10(void) { int a[5] ; int i ; - int term187_2 = 0; + int term187_2-file_01-simple-cases ; { #line 186 i = 0; { +#line 187 + term187_2-file_01-simple-cases = 0; { #line 187 while (1) { -#line 187 - term187_2 ++; while_continue: /* CIL Label */ ; #line 187 if (! (i < 5)) { #line 187 goto while_break; } +#line 187 + term187_2-file_01-simple-cases ++; #line 188 if (i == 3) { #line 189 @@ -1557,9 +1599,11 @@ void example10(void) #line 193 i ++; } - } while_break: /* CIL Label */ ; } +#line 187 + term_exit- = term187_2-file_01-simple-cases; + } #line 195 return; } @@ -1990,99 +2034,113 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , char *a ; char *b ; char c ; - int term10_5 = 0; - int term9_3 = 0; - int term21_9 = 0; - int term17_5 = 0; - int term16_3 = 0; + int term10_5-file_stdlib ; + int term9_3-file_stdlib ; + int term21_9-file_stdlib ; + int term17_5-file_stdlib ; + int term16_3-file_stdlib ; { #line 9 i = (size_t )0; { +#line 9 + term9_3-file_stdlib = 0; { #line 9 while (1) { -#line 9 - term9_3 ++; while_continue: /* CIL Label */ ; #line 9 if (! (i < count)) { #line 9 goto while_break; } +#line 9 + term9_3-file_stdlib ++; #line 10 j = (size_t )0; { +#line 10 + term10_5-file_stdlib = 0; { #line 10 while (1) { -#line 10 - term10_5 ++; while_continue___0: /* CIL Label */ ; #line 10 if (! (j < count)) { #line 10 goto while_break___0; } +#line 10 + term10_5-file_stdlib ++; #line 11 (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); #line 10 j ++; } - } while_break___0: /* CIL Label */ ; } +#line 10 + term_exit- = term10_5-file_stdlib; + } #line 9 i ++; } - } while_break: /* CIL Label */ ; } +#line 9 + term_exit- = term9_3-file_stdlib; + } #line 16 i___0 = (size_t )0; { +#line 16 + term16_3-file_stdlib = 0; { #line 16 while (1) { -#line 16 - term16_3 ++; while_continue___1: /* CIL Label */ ; #line 16 if (! (i___0 < count)) { #line 16 goto while_break___1; } +#line 16 + term16_3-file_stdlib ++; #line 17 j___0 = (size_t )0; { +#line 17 + term17_5-file_stdlib = 0; { #line 17 while (1) { -#line 17 - term17_5 ++; while_continue___2: /* CIL Label */ ; #line 17 if (! (j___0 < count)) { #line 17 goto while_break___2; } +#line 17 + term17_5-file_stdlib ++; #line 19 if (r) { #line 21 k = (size_t )0; { +#line 21 + term21_9-file_stdlib = 0; { #line 21 while (1) { -#line 21 - term21_9 ++; while_continue___3: /* CIL Label */ ; #line 21 if (! (k < size)) { #line 21 goto while_break___3; } +#line 21 + term21_9-file_stdlib ++; #line 22 a = (char *)((ptr + i___0 * size) + k); #line 23 @@ -2096,22 +2154,28 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , #line 21 k ++; } - } while_break___3: /* CIL Label */ ; } +#line 21 + term_exit- = term21_9-file_stdlib; + } } #line 17 j___0 ++; } - } while_break___2: /* CIL Label */ ; } +#line 17 + term_exit- = term17_5-file_stdlib; + } #line 16 i___0 ++; } - } while_break___1: /* CIL Label */ ; } +#line 16 + term_exit- = term16_3-file_stdlib; + } #line 33 return; } @@ -2129,23 +2193,25 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size size_t i ; void const *a ; int tmp ; - int term40_3 = 0; + int term40_3-file_stdlib ; { #line 40 i = (size_t )0; { +#line 40 + term40_3-file_stdlib = 0; { #line 40 while (1) { -#line 40 - term40_3 ++; while_continue: /* CIL Label */ ; #line 40 if (! (i < count)) { #line 40 goto while_break; } +#line 40 + term40_3-file_stdlib ++; #line 41 a = ptr + i * size; #line 42 @@ -2158,9 +2224,11 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size #line 40 i ++; } - } while_break: /* CIL Label */ ; } +#line 40 + term_exit- = term40_3-file_stdlib; + } #line 47 return ((void *)0); } diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 7a4a6037b0..0177f3ea85 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 @@ -562,7 +563,7 @@ struct let side_context sideg f c = if !AnalysisState.postsolving then sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c)) - + let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t) list ref = let r = ref [] in let spawns = ref [] in @@ -1692,6 +1693,194 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** +module RecursionTermLifter (S: Spec): Spec = +struct + include S + + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + (* global invariant: + - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) + + module V = + struct + include Printable.Option (S.V) (struct let name = "RecursionTerm" end) + let name () = "RecursionTerm" + let is_write_only t = true + let s x = `Left x + end + + module C = + struct + include S.C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + + (*module Tuple = struct + type t = (fundec, S.C) [@@deriving eq, ord, hash] + let equal t1 t2 = false + let compare t1 t3 = 0 + let show t = "t" + let pretty () (x: t) = match x with _ -> . + + let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + let name u = "recursion" + let to_yojson (x: t) = match x with _ -> . + + let tag t = 1 + let arbitrary () = failwith "Printable.Empty.arbitrary" + + let relift t = t + end +*) + module Tupel (S:Spec) = + struct + include Printable.Std + type t = fundec * S.C.t [@@deriving eq, ord, hash] + + let equal_fundec = false + let hash_fundec = false + + let name () = "recursion" + + let pretty () (x: t) = match x with _ -> . + + let relift (f, c) = + (f, c) + + let equal t1 t2 = false + let compare t1 t3 = 0 + let show t = "t" + + let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) + + let name u = "recursion" + let to_yojson (x: t) = match x with _ -> . + + let tag t = 1 + let arbitrary () = failwith "Printable.Empty.arbitrary" + end + + module T = + struct + include SetDomain.Make (Tupel (S)) + end + + module EM = + struct + include MapDomain.MapBot (C) (T) + let name () = "recursions" + end + + module G = + struct + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + let name () = "recursionTerm" + let node = function + | `Bot -> EM.bot () + | `Lifted2 x -> x + | _ -> failwith "DeadBranchLifter.node" + let create_s s = `Lifted1 s + let create_node node = `Lifted2 node + + let printXml f = function + | `Lifted1 x -> S.G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + let em = G.node (ctx.global (V.node g)) in + EM.iter (fun exp tv -> + match tv with + | `Lifted tv -> + let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) + let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in + M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv + | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) + M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp + | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) + | `Top -> (* may be both true and false *) + () + ) em; + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | IterSysVars (vq, vf) -> + (* vars for S *) + let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in + S.query (conv ctx) (IterSysVars (vq, vf')); + + (* node vars for dead branches *) + begin match vq with + | Node {node; _} -> + vf (Obj.repr (V.node node)) + | _ -> + () + end + | _ -> + S.query (conv ctx) q + + + let branch ctx = S.branch (conv ctx) + + let branch ctx exp tv = + if !AnalysisState.postsolving then ( + try + let r = branch ctx exp tv in + (* branch is live *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) + r + with Deadcode -> + (* branch is dead *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) + raise Deadcode + ) + else ( + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) + branch ctx exp tv + ) + + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) + let enter ctx = S.enter (conv ctx) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) +end + (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1711,7 +1900,10 @@ struct So: g -> {c' -> f, c} in case f, c --> g, c' *) - (*module CVal = + (* + + + module CVal = struct include C include Printable.Std (* To make it Groupable *) @@ -1719,8 +1911,15 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) + module V = (*TODO: do I need to change V???*) + struct + include Printable.Option (S.V) (struct let name = "RecursionTerm" end) + let name () = "RecursionTerm" + let is_write_only t = true + let s x = `Left x + end + module G = S.G + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m @@ -1737,11 +1936,18 @@ struct let context = S.context + (**let side_context sideg f c = + if !AnalysisState.postsolving then + sideg (f) (G.create_contexts (G.CSet.singleton c))*) + let query ctx = S.query (ctx) let branch ctx = S.branch (ctx) let assign ctx = S.assign (ctx) let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) + let enter ctx = + if !AnalysisState.postsolving then + printf "hallo hallo"; + S.enter (ctx) (*TODO*) let paths_as_set ctx = S.paths_as_set (ctx) let body ctx = S.body (ctx) let return ctx = S.return (ctx) @@ -1755,7 +1961,7 @@ struct let asm ctx = S.asm (ctx) let event ctx e octx = S.event (ctx) e (octx) end - +*) module CompareGlobSys (SpecSys: SpecSys) = struct From 936e7a76bdfb7b6607d5a721fef727e6c24bf4a1 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 050/628] Loop termination tests extended --- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 ++-- .../80-termination/17-goto-terminating.c | 18 +++++++++++ .../80-termination/18-goto-nonterminating.c | 15 +++++++++ .../80-termination/19-rand-terminating.c | 31 +++++++++++++++++++ .../80-termination/20-rand-nonterminating.c | 31 +++++++++++++++++++ 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/regression/80-termination/17-goto-terminating.c create mode 100644 tests/regression/80-termination/18-goto-nonterminating.c create mode 100644 tests/regression/80-termination/19-rand-terminating.c create mode 100644 tests/regression/80-termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c new file mode 100644 index 0000000000..10aa729837 --- /dev/null +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -0,0 +1,18 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // TERM + printf("Current number: %d\n", num); + num++; + + if (num <= 10) + { + goto loop; + } + + return 0; +} diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c new file mode 100644 index 0000000000..dbb7a3df59 --- /dev/null +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // NOTERM + printf("Current number: %d\n", num); + num++; + + goto loop; + + return 0; +} diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c new file mode 100644 index 0000000000..1d226f0df2 --- /dev/null +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 5; i++) // TERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j <= 5) // TERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c new file mode 100644 index 0000000000..6639e5bc76 --- /dev/null +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 0; i++) // NOTERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j < 5) // NOTERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} From 3818086469416a606ee38cde87324bd1d2ee2535 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 051/628] Tests for loop termination --- scripts/update_suite.rb | 6 + .../01-simple-loop-terminating.c | 15 ++ .../02-simple-loop-nonterminating.c | 12 ++ .../03-nested-loop-terminating.c | 27 ++++ .../04-nested-loop-nonterminating.c | 23 +++ .../80-termination/05-for-loop-terminating.c | 14 ++ .../06-for-loop-nonterminating.c | 10 ++ .../07-nested-for-loop-terminating.c | 20 +++ .../08-nested-for-loop-nonterminating.c | 19 +++ .../09-complex-for-loop-terminating.c | 107 +++++++++++++ .../10-complex-loop-terminating.c | 135 ++++++++++++++++ .../80-termination/11-loopless-termination.c | 7 + .../12-do-while-instant-terminating.c | 15 ++ .../80-termination/13-do-while-terminating.c | 16 ++ .../14-do-while-nonterminating.c | 16 ++ .../15-complex-loop-combination-terminating.c | 144 ++++++++++++++++++ ...16-nested-loop-nontrivial-nonterminating.c | 23 +++ 17 files changed, 609 insertions(+) create mode 100644 tests/regression/80-termination/01-simple-loop-terminating.c create mode 100644 tests/regression/80-termination/02-simple-loop-nonterminating.c create mode 100644 tests/regression/80-termination/03-nested-loop-terminating.c create mode 100644 tests/regression/80-termination/04-nested-loop-nonterminating.c create mode 100644 tests/regression/80-termination/05-for-loop-terminating.c create mode 100644 tests/regression/80-termination/06-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/07-nested-for-loop-terminating.c create mode 100644 tests/regression/80-termination/08-nested-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/09-complex-for-loop-terminating.c create mode 100644 tests/regression/80-termination/10-complex-loop-terminating.c create mode 100644 tests/regression/80-termination/11-loopless-termination.c create mode 100644 tests/regression/80-termination/12-do-while-instant-terminating.c create mode 100644 tests/regression/80-termination/13-do-while-terminating.c create mode 100644 tests/regression/80-termination/14-do-while-nonterminating.c create mode 100644 tests/regression/80-termination/15-complex-loop-combination-terminating.c create mode 100644 tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index e99068829e..dead6cd8f1 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -165,6 +165,8 @@ def collect_warnings when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" + when /^\[Terminating\]/ then "term" + when /^\[Nonterminating\]/ then "noterm" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) @@ -298,6 +300,10 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" + elsif obj =~ /NON?TERM/ then + tests[i] = "noterm" + elsif obj =~ /TERM/ then + tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c new file mode 100644 index 0000000000..931b125171 --- /dev/null +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + while (i <= 10) // TERM + { + printf("%d\n", i); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c new file mode 100644 index 0000000000..520a4a82e0 --- /dev/null +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -0,0 +1,12 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + while (1) // NOTERM + { + continue; + } + + return 0; +} diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c new file mode 100644 index 0000000000..172827af42 --- /dev/null +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -0,0 +1,27 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + int i = 1; + + // Outer while loop for rows + while (i <= rows) + { // TERM + int j = 1; + + // Inner while loop for columns + while (j <= columns) + { // TERM + printf("(%d, %d) ", i, j); + j++; + } + + printf("\n"); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c new file mode 100644 index 0000000000..37af9ed6fb --- /dev/null +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (1) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c new file mode 100644 index 0000000000..ab286a6dd4 --- /dev/null +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -0,0 +1,14 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + for (i = 1; i <= 10; i++) // TERM + { + printf("%d\n", i); + } + + return 0; +} diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c new file mode 100644 index 0000000000..466001e6e5 --- /dev/null +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -0,0 +1,10 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + for (;;) { // NOTERM + printf("This loop does not terminate.\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c new file mode 100644 index 0000000000..eec4dda908 --- /dev/null +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -0,0 +1,20 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) // TERM + { + for (int j = 1; j <= columns; j++) // TERM + { + printf("(%d, %d) ", i, j); + } + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..3f7bcb4f07 --- /dev/null +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + { + for (innerCount = 1;; innerCount++) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c new file mode 100644 index 0000000000..ed28fa9b43 --- /dev/null +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -0,0 +1,107 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i, j, k; + + // Outer loop + for (i = 1; i <= 5; i++) // TERM + { + // Inner loop 1 + for (j = 1; j <= i; j++) // TERM + { + printf("%d ", j); + } + printf("\n"); + + // Inner loop 2 + for (k = i; k >= 1; k--) // TERM + { + printf("%d ", k); + } + printf("\n"); + } + + // Additional loop + for (i = 5; i >= 1; i--) // TERM + { + for (j = i; j >= 1; j--) // TERM + { + printf("%d ", j); + } + printf("\n"); + } + + // Loop with conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + } + + // Loop with nested conditions + for (i = 1; i <= 10; i++) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + // Loop with a break statement + for (i = 1; i <= 10; i++) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + } + printf("\n"); + + // Loop with a continue statement + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + { + printf("%d %d %d\n", a, b, c); + } + + return 0; +} diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c new file mode 100644 index 0000000000..3a19f17bee --- /dev/null +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -0,0 +1,135 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) // TERM + { + // Inner while loop 1 + while (j <= i) // TERM + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) // TERM + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) // TERM + { + j = i; + while (j >= 1) // TERM + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + + // Loop with a break statement + i = 1; + while (i <= 10) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + i++; + } + printf("\n"); + + // Loop with a continue statement + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + i++; + continue; + } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) // TERM + { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } + + return 0; +} diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c new file mode 100644 index 0000000000..b118e65e35 --- /dev/null +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -0,0 +1,7 @@ +// TERM +#include + +int main() { + printf("Terminating code without a loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c new file mode 100644 index 0000000000..cc3cc41edc --- /dev/null +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 0; + + do // TERM + { + printf("Inside the do-while loop\n"); + } while (i > 0); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c new file mode 100644 index 0000000000..05fe270f04 --- /dev/null +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // TERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c new file mode 100644 index 0000000000..1c70d4fc76 --- /dev/null +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // NOTERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c new file mode 100644 index 0000000000..54f8cd97c8 --- /dev/null +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -0,0 +1,144 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + // Non-nested loops + int i; + + // for loop + for (i = 1; i <= 10; i++) // TERM + { + printf("For loop iteration: %d\n", i); + } + + // while loop + int j = 1; + while (j <= 10) // TERM + { + printf("While loop iteration: %d\n", j); + j++; + } + + // do-while loop + int k = 1; + do // TERM + { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); + + // Nested loops + int a, b; + + // Nested for and while loop + for (a = 1; a <= 5; a++) // TERM + { + int c = 1; + while (c <= a) // TERM + { + printf("Nested For-While loop: %d\n", c); + c++; + } + } + + // Nested while and do-while loop + int x = 1; + while (x <= 5) // TERM + { + int y = 1; + do // TERM + { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } + + // Nested do-while and for loop + int p = 1; + do // TERM + { + for (int q = 1; q <= p; q++) // TERM + { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); + + // Additional loops + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) // TERM + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) // TERM + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) // TERM + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // TERM + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + + // Loop with nested conditions + for (int v = 1; v <= 10; v++) // TERM + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + /* // Loop with a label and goto statement + int w = 1; +start: + if (w <= 5) + { + printf("Loop with Label and Goto: %d\n", w); + w++; + goto start; // TERM + } */ + + return 0; +} diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c new file mode 100644 index 0000000000..855fbd0dca --- /dev/null +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (outerCount < 3 || innerCount > 0) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} From 9f60dca36bfc5cf7628d6ba5d3f03d2109db4a57 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 052/628] first tests for recursion termination analysis, added empty functor and GMapG --- runningGob.sh | 22 ++++++++---- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++ src/framework/constraints.ml | 66 +++++++++++++++++++++++++++++++++++- src/framework/control.ml | 1 + 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..e3b5a6da45 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,22 +1,32 @@ #!/bin/bash -make +#make #make install # set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set --enable warn.debug" #note: preprocessing first needs to be added to apron options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_nonTerm="tests/regression/80-termination/02-simple-loop-nonterminating.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_deadCode="tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint $cfile_loops $options_term --enable justcil > output.txt +#./goblint $cfile_loops $options_term --html + +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_deadCode $options_term --enable justcil > output.txt +./goblint $cfile_deadCode $options_term --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile_nonTerm $options_term --enable justcil > output.txt +#./goblint $cfile_nonTerm $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..c8d3873085 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..e9c1b9b0a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches" + let name () = "bmodule Vranches" end module G = @@ -1692,6 +1692,70 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = GMapG (S.G) (S.C) += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 40128b7eb28855a9f79f649caf5f8e3288f6f7ab Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:31:15 +0200 Subject: [PATCH 053/628] now its working :) --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e9c1b9b0a2..0586a87d3e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1697,7 +1697,7 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = GMapG (S.G) (S.C) + and module G = S.G = struct From b35766b44e2b5002a0bf5f78b5a533fc6087b4d5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:03:53 +0200 Subject: [PATCH 054/628] reverted the changes, wrong branch :) --- src/framework/analyses.ml | 54 ------------------------------ src/framework/constraints.ml | 64 ------------------------------------ src/framework/control.ml | 3 +- 3 files changed, 1 insertion(+), 120 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c8d3873085..7ac18f56f7 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,60 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0586a87d3e..d8b186160b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,70 +1692,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (*module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end - - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7e993733cd 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,8 +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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From e67ea327f230250553ec621691142f6edb6acaf3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:05:00 +0200 Subject: [PATCH 055/628] fixed a typo --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d8b186160b..740d1f85a9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "bmodule Vranches" + let name () = "branches" end module G = From ff5377b4413168b21808da54305ffa5311f29e7e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 056/628] Loop termination tests extended --- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 ++-- .../80-termination/17-goto-terminating.c | 18 +++++++++++ .../80-termination/18-goto-nonterminating.c | 15 +++++++++ .../80-termination/19-rand-terminating.c | 31 +++++++++++++++++++ .../80-termination/20-rand-nonterminating.c | 31 +++++++++++++++++++ 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/regression/80-termination/17-goto-terminating.c create mode 100644 tests/regression/80-termination/18-goto-nonterminating.c create mode 100644 tests/regression/80-termination/19-rand-terminating.c create mode 100644 tests/regression/80-termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c new file mode 100644 index 0000000000..10aa729837 --- /dev/null +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -0,0 +1,18 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // TERM + printf("Current number: %d\n", num); + num++; + + if (num <= 10) + { + goto loop; + } + + return 0; +} diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c new file mode 100644 index 0000000000..dbb7a3df59 --- /dev/null +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // NOTERM + printf("Current number: %d\n", num); + num++; + + goto loop; + + return 0; +} diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c new file mode 100644 index 0000000000..1d226f0df2 --- /dev/null +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 5; i++) // TERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j <= 5) // TERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c new file mode 100644 index 0000000000..6639e5bc76 --- /dev/null +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 0; i++) // NOTERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j < 5) // NOTERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} From 69cee5fb397bd3523ffe25534218ac28790e50ee Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:52:59 +0200 Subject: [PATCH 057/628] Added testcases with randomness --- .../21-no-exit-on-rand-unproofable.c | 19 +++++++++++++++++++ .../22-exit-on-rand-unproofable.c | 15 +++++++++++++++ .../23-exit-on-rand-terminating.c | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 tests/regression/80-termination/21-no-exit-on-rand-unproofable.c create mode 100644 tests/regression/80-termination/22-exit-on-rand-unproofable.c create mode 100644 tests/regression/80-termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c new file mode 100644 index 0000000000..4510ac1bb7 --- /dev/null +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int forever, i = 0; + + while (i < 4 || forever == 1) + { + i++; + if (i == 4) + { + if (rand()) + { + forever = 1; + } + } + } +} \ No newline at end of file diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c new file mode 100644 index 0000000000..97b18ed5fc --- /dev/null +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int forever = 1; + + while (forever == 1) + { + if (rand()) //May exit, may not + { + forever = 0; + } + } +} \ No newline at end of file diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c new file mode 100644 index 0000000000..5e2be62637 --- /dev/null +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int shortrun, i = 0; + + while (i < 90 || shortrun == 1) + { + i++; + if (rand()) + { + shortrun = 1; + } + } +} \ No newline at end of file From 4f45a89d0bbade25f5c102bfc376b933984147c2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 5 Jun 2023 17:10:44 +0200 Subject: [PATCH 058/628] added upjumping goto statement --- runningGob.sh | 1 + src/analyses/termination_new.ml | 14 +++++++++++++- src/framework/control.ml | 2 +- src/util/terminationPreprocessing.ml | 10 +++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..52d0830b81 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -9,6 +9,7 @@ options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 936471ceaf..a380532afe 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,10 +3,12 @@ open Analyses open GoblintCil open TerminationPreprocessing +include Printf exception PreProcessing of string let loopCounters : varinfo list ref = ref [] +let upjumpingGotos : location list ref = ref [] (*contains the locations of the upjumping gotos*) let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) @@ -16,6 +18,14 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loopExit +(* checks if at the current location (=loc) of the analysis an upjumping goto was already reached + true: no upjumping goto was reached till now*) +let currrently_no_upjumping_gotos (loc : location) = + List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents + +let no_upjumping_gotos () = + (List.length upjumpingGotos.contents) <= 0 + (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = let exp = Lval (Var varinfo, NoOffset) in @@ -43,10 +53,12 @@ struct match lval, rval with (* Assume that the following loop does not terminate *) (Var x, NoOffset), _ when is_loop_counter_var x -> + if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> let is_bounded = check_bounded ctx x in + if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local @@ -68,6 +80,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters loopExit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7722621d5a 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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) + (*|> lift true (module RecursionTermLifter)*)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1a0e725624..684733c05f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,6 +6,7 @@ *) open GoblintCil +include Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -20,7 +21,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc le (fd : fundec) = object(self) +class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc (f:fundec) = if !le.vname <> "term_exit-" then begin @@ -46,6 +47,13 @@ class loopCounterVisitor lc le (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s | _ -> s in ChangeDoChildrenPost (s, action); end From a820c31ff07dcf5849b231663c0bca553bba42cf Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 10:15:07 +0200 Subject: [PATCH 059/628] plain functor --- src/framework/constraints.ml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..8132e6a1d7 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,7 +1693,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** +(* module RecursionTermLifter (S: Spec): Spec = struct include S @@ -1711,7 +1711,7 @@ struct let s x = `Left x end - module C = + module C_ = struct include S.C include Printable.Std (* To make it Groupable *) @@ -1772,13 +1772,13 @@ struct module EM = struct - include MapDomain.MapBot (C) (T) + include MapDomain.MapBot (C_) (T) let name () = "recursions" end module G = struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) (*Todo: do we need lift2?*) let name () = "recursionTerm" let node = function | `Bot -> EM.bot () @@ -1793,6 +1793,8 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.s v))); @@ -1880,7 +1882,7 @@ struct let asm ctx = S.asm (conv ctx) let event ctx e octx = S.event (conv ctx) e (conv octx) end - +*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1911,13 +1913,14 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = (*TODO: do I need to change V???*) + module V = S.V + (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x - end + end*) module G = S.G (*GMapG (S.G) (S.C)*) (*struct @@ -1961,7 +1964,7 @@ struct let asm ctx = S.asm (ctx) let event ctx e octx = S.event (ctx) e (octx) end -*) + module CompareGlobSys (SpecSys: SpecSys) = struct From f298efa3e087d32ee2608a55b74d1d291c5e56a0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 11:44:02 +0200 Subject: [PATCH 060/628] added tuple; problem: fundec is just a type and not a module --- src/framework/constraints.ml | 41 +++++++++++++++++++++++++++++++++--- src/framework/control.ml | 2 +- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 8132e6a1d7..37cf9a5f51 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1904,7 +1904,6 @@ struct (* - module CVal = struct include C @@ -1921,8 +1920,44 @@ struct let is_write_only t = true let s x = `Left x end*) - module G = S.G - (*GMapG (S.G) (S.C)*) + + module C_ = + struct + include S.C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + + module type FundecType = + sig + type t = fundec + + val getFundec: t -> fundec + (* Define any other values or types exposed by the module *) + end + + module Fundec (F:fundec) : FundecType = + struct + let getFundec = F + let fname = F.fname + end + + (* Tuple of fundec and S.C*) + module T = (*Todo: is this Printable.S or S.C*) + struct + include Printable.Std + type t = (fundec * S.C.t) + + let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let show () = " " + end + + (* Set of Tuples*) + module TSet = SetDomain.Make (T) + + module G = S.G(*Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*)*) + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m diff --git a/src/framework/control.ml b/src/framework/control.ml index 7722621d5a..bd26fa7129 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 RecursionTermLifter)*)(*TODO: should we really always evaluate it???*) + |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 2fe92c6889ce7b383e79a7e48629734289eee975 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 12:52:16 +0200 Subject: [PATCH 061/628] added definition of V --- src/framework/constraints.ml | 52 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 37cf9a5f51..14b0126325 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1889,7 +1889,6 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = S.G = struct @@ -1912,7 +1911,8 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = S.V + + module V = GVarF(S.V) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) @@ -1929,7 +1929,7 @@ struct end - module type FundecType = + (*module type FundecType = sig type t = fundec @@ -1941,7 +1941,7 @@ struct struct let getFundec = F let fname = F.fname - end + end*) (* Tuple of fundec and S.C*) module T = (*Todo: is this Printable.S or S.C*) @@ -1950,7 +1950,9 @@ struct type t = (fundec * S.C.t) let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false - let show () = " " + let show (a, b) = a.fname ^ b.vname + let name () = "Tuple" + let to_yojson x = `String (show x) end (* Set of Tuples*) @@ -1962,6 +1964,7 @@ struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" type marshal = S.marshal @@ -1978,26 +1981,31 @@ struct if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) + let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = (*TODO Change the body*) + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + let query ctx = S.query (conv ctx) + let branch ctx = S.branch (conv ctx) + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) let enter ctx = if !AnalysisState.postsolving then printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) + S.enter (conv ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) end From cbf31335fb1341cabe90f982e80b6db6b5c71c1f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 6 Jun 2023 16:50:45 +0200 Subject: [PATCH 062/628] WIP on check_bounded --- src/analyses/termination_new.ml | 8 +++++--- src/cdomains/intDomain.ml | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 936471ceaf..34e25d49d3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -18,11 +18,13 @@ let is_loop_exit_indicator (x : varinfo) = (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = + let open IntDomain.IntDomTuple in (* TODO: Remove *) + let open Cil in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - `Top -> false - | `Bot -> raise (PreProcessing "Loop variable is Bot") - | _ -> true (* TODO: Is this sound? *) + `Top -> print_endline (varinfo.vname ^ " is TOP"); false + | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") + | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); not (is_top v) (* TODO: Is this sound? *) module Spec : Analyses.MCPSpec = struct diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 3b1eecc27d..dea3daecd8 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -219,6 +219,7 @@ sig val ending : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t val of_int: Cil.ikind -> int_t -> t val of_bool: Cil.ikind -> bool -> t + val to_interval: t -> (int_t * int_t) option val of_interval: ?suppress_ovwarn:bool -> Cil.ikind -> int_t * int_t -> t val of_congruence: Cil.ikind -> int_t * int_t -> t val is_top_of: Cil.ikind -> t -> bool @@ -349,6 +350,8 @@ struct with Failure _ -> top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) + let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik let ending ?(suppress_ovwarn=false) ik x = @@ -428,6 +431,7 @@ struct let of_excl_list ikind is = {v = I.of_excl_list ikind is; ikind} let is_excl_list x = I.is_excl_list x.v let to_incl_list x = I.to_incl_list x.v + let to_interval x = I.to_interval x.v let of_interval ?(suppress_ovwarn=false) ikind (lb,ub) = {v = I.of_interval ~suppress_ovwarn ikind (lb,ub); ikind} let of_congruence ikind (c,m) = {v = I.of_congruence ikind (c,m); ikind} let starting ?(suppress_ovwarn=false) ikind i = {v = I.starting ~suppress_ovwarn ikind i; ikind} @@ -708,6 +712,7 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) + let to_interval x = x let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1265,6 +1270,8 @@ struct let of_bool _ = function true -> one | false -> zero + let to_interval = failwith "Not implemented!" (* FIXME *) + let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) let of_int ik (x: int_t) = of_interval ik (x, x) @@ -2137,6 +2144,7 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2529,6 +2537,7 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3263,6 +3272,8 @@ struct let refine_with_incl_list ik a b = a let project ik p t = t + + let to_interval = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct @@ -3495,6 +3506,8 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) + let to_interval (_, i, _, _, _) = I2.to_interval i + let to_excl_list x = let merge ps = let (vs, rs) = List.split ps in From 6d7ec8cd8ec52c994ba6419048ffa0798645e204 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 15:52:11 +0200 Subject: [PATCH 063/628] IT's wOrkingggg :)git status; hopefully V and G are correct now... some functions definitely must be redefined --- src/framework/analyses.ml | 76 +++++++++++++++++++++++++++++++ src/framework/constraints.ml | 86 ++++++++++++++++-------------------- 2 files changed, 114 insertions(+), 48 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..286c33870d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -120,6 +120,82 @@ struct end +module C_ (C: Printable.S)= + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + +(* Tuple of fundec and S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +struct + include Printable.Std + type t = (CilType.Fundec.t * C.t) + + let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let show (a,b) = (Base1.show a) ^ (Base2.show b) + let name () = "Tuple" + let to_yojson x = `String (show x) + let relift (a,b) = (a,b) (*Todo: is this correct?*) + let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) + let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) + (*let a = Base1.compare a1 a2 in + let b = Base2.compare b1 b2 in + *) + let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) + + let hash (a,b) = 2 (*Todo: what do we have to put here?*) + +end + +module GVarGG (G: Lattice.S) (C: Printable.S) = + struct + module CSet = + struct + include SetDomain.Make ( + struct + include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + end + ) + let name () = "contexts" + end + + module CMap = + struct + include MapDomain.MapBot (C_ (C)) (CSet) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) + end + + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarGG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarGG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let s = function (*TODO: does this work? copied from DeadBranch*) + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + + let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + end + + module GMapG (G: Lattice.S) (C: Printable.S) = struct module CVal = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 14b0126325..93aa636847 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1887,20 +1887,34 @@ end (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D - and module G = S.G and module C = S.C + and module G = GVarGG (S.G) (S.C) = struct module C = S.C module P = S.P module D = S.D + (*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) + + (*module type FundecType = + sig + type t = fundec + + val getFundec: t -> fundec + (* Define any other values or types exposed by the module *) + end + module Fundec (F:fundec) : FundecType = + struct + let getFundec = F + let fname = F.fname + end*) (* module CVal = @@ -1910,61 +1924,36 @@ struct let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) end module M = MapDomain.MapBot (CVal) (CVal) -*) - - module V = GVarF(S.V) - (*(*TODO: do I need to change V???*) +*) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x end*) + (*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) + let s = function + | `Bot -> S.G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + end*) - module C_ = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module type FundecType = - sig - type t = fundec - - val getFundec: t -> fundec - (* Define any other values or types exposed by the module *) - end - module Fundec (F:fundec) : FundecType = + module V = struct - let getFundec = F - let fname = F.fname - end*) - - (* Tuple of fundec and S.C*) - module T = (*Todo: is this Printable.S or S.C*) - struct - include Printable.Std - type t = (fundec * S.C.t) - - let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false - let show (a, b) = a.fname ^ b.vname - let name () = "Tuple" - let to_yojson x = `String (show x) + include GVarF(S.V) + let s x = `Left x end - (* Set of Tuples*) - module TSet = SetDomain.Make (T) - module G = S.G(*Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*)*) - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + module G = GVarGG (S.G) (S.C) + + let name () = "RecursionTerm (" ^ S.name () ^ ")" type marshal = S.marshal @@ -1981,7 +1970,8 @@ struct if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) - let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = (*TODO Change the body*) + (*TODO Change the body??*) + let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.s v))); sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); From aa1c30a3a7ce2482155dcf682fdfd6420dbca72e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 16:12:15 +0200 Subject: [PATCH 064/628] changed indentation --- src/framework/analyses.ml | 92 ++++++++++++++-------------- src/framework/constraints.ml | 25 ++++---- src/util/terminationPreprocessing.ml | 1 + 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 286c33870d..550adb7b16 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -121,12 +121,12 @@ end module C_ (C: Printable.S)= - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end +struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + +end (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) @@ -142,7 +142,7 @@ struct let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in - let b = Base2.compare b1 b2 in + let b = Base2.compare b1 b2 in *) let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) @@ -151,49 +151,49 @@ struct end module GVarGG (G: Lattice.S) (C: Printable.S) = +struct + module CSet = struct - module CSet = - struct - include SetDomain.Make ( - struct - include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) - end - ) - let name () = "contexts" - end + include SetDomain.Make ( + struct + include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + end + ) + let name () = "contexts" + end - module CMap = - struct - include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) - let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) - end + module CMap = + struct + include MapDomain.MapBot (C_ (C)) (CSet) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) + end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarGG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarGG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - - let s = function (*TODO: does this work? copied from DeadBranch*) - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) - end + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarGG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarGG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let s = function (*TODO: does this work? copied from DeadBranch*) + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + + let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) +end module GMapG (G: Lattice.S) (C: Printable.S) = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 93aa636847..fde22c4c20 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1883,19 +1883,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end *) - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module C = S.C - and module G = GVarGG (S.G) (S.C) -= - -struct - module C = S.C - module P = S.P - module D = S.D - (*GMapG (S.G) (S.C)*) + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m @@ -1938,7 +1926,18 @@ struct | _ -> failwith "RecursionTerm.s" end*) +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module C = S.C + and module G = GVarGG (S.G) (S.C) += +struct + module C = S.C + module P = S.P + module D = S.D + module V = struct include GVarF(S.V) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..5f96483af4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,6 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in + (* NOT tested for TODOOOOO*) let v = (Cil.makeLocalVar fd name typ) in let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in From 5f3ae26b7c8d58a33208373a9ba1791b56b20eb6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 17:23:29 +0200 Subject: [PATCH 065/628] intendation --- src/framework/analyses.ml | 2 +- src/framework/constraints.ml | 15 +++++++-------- src/util/terminationPreprocessing.ml | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 550adb7b16..52836f979b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -158,7 +158,7 @@ struct struct include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) end - ) + ) let name () = "contexts" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index fde22c4c20..88afb5ca91 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1883,14 +1883,14 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end *) - (*GMapG (S.G) (S.C)*) - (*struct +(*GMapG (S.G) (S.C)*) +(*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) +end*) - (*module type FundecType = +(*module type FundecType = sig type t = fundec @@ -1911,20 +1911,19 @@ end include Printable.Std (* To make it Groupable *) let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) end - module M = MapDomain.MapBot (CVal) (CVal) -*) (*(*TODO: do I need to change V???*) + module M = MapDomain.MapBot (CVal) (CVal)*) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x end*) - (*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) +(*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) let s = function | `Bot -> S.G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" - end*) +end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 5f96483af4..da4fd2e10b 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,8 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - (* NOT tested for TODOOOOO*) - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in From 5717a43867f908989481b5807d3d54b2fd1088c0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 17:31:12 +0200 Subject: [PATCH 066/628] indent --- src/framework/analyses.ml | 2 +- src/framework/constraints.ml | 4 ++-- src/util/terminationPreprocessing.ml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 52836f979b..2f3f4b34a8 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -158,7 +158,7 @@ struct struct include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) end - ) + ) let name () = "contexts" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 88afb5ca91..774c0abc95 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1887,7 +1887,7 @@ end (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m -end*) + end*) (*module type FundecType = @@ -1923,7 +1923,7 @@ end*) | `Bot -> S.G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" -end*) + end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index da4fd2e10b..749b9f2f8e 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,7 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) + let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in From 706a1f516305de78144a1dce17f3bf4142093af1 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 5 Jun 2023 15:33:19 +0200 Subject: [PATCH 067/628] changed loop exit indicator form global variable to a special function --- lib/goblint/runtime/src/goblint.c | 4 ++++ src/analyses/libraryFunctions.ml | 1 + src/analyses/termination_new.ml | 4 ++++ src/util/terminationPreprocessing.ml | 13 ++++--------- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index bc176f93a6..39c18c5b8e 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -27,4 +27,8 @@ void __goblint_split_begin(int exp) { void __goblint_split_end(int exp) { +} + +void __goblint_bounded() { + } \ No newline at end of file diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 3eacf9013a..7bb985ae4b 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -302,6 +302,7 @@ let goblint_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__goblint_assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); ("__goblint_split_begin", unknown [drop "exp" []]); ("__goblint_split_end", unknown [drop "exp" []]); + ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Assert { exp; check = true; refine = false }); ] (** zstd functions. diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a380532afe..bff776b95d 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -80,6 +80,10 @@ end let () = (** Register the preprocessing *) +<<<<<<< HEAD Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); +======= + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); +>>>>>>> dfa9d6ef8 (changed loop exit indicator form global variable to a special function) (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 749b9f2f8e..15a5c948fd 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -8,6 +8,8 @@ open GoblintCil include Printf +let f_bounded = Lval (var (emptyFunction "__goblint_bounded").svar) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -21,15 +23,8 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg le (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor - method! vfunc (f:fundec) = - if !le.vname <> "term_exit-" then begin - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeGlobalVar exit_name typ; - end; - DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -38,7 +33,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [(Lval(var v))], loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) From 09510429a97ac12575c47067d15c18e450a1ae73 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 8 Jun 2023 13:13:39 +0200 Subject: [PATCH 068/628] added first tests for enter; does compile without the enter stuff, but when running we got an Not_found exception due to the definition of V --- src/framework/analyses.ml | 8 +++--- src/framework/constraints.ml | 55 +++++++++++++++++------------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 2f3f4b34a8..41448768a9 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,7 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - +(* Make the given module Goupable*) module C_ (C: Printable.S)= struct include C @@ -139,12 +139,12 @@ struct let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) + let printXml f (a,b) = Base1.printXml f a; Base2.printXml f b (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in let b = Base2.compare b1 b2 in *) - let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) + let pretty () x = text (show x) let hash (a,b) = 2 (*Todo: what do we have to put here?*) @@ -176,7 +176,7 @@ struct | `Lifted1 x -> x | _ -> failwith "GVarGG.spec" let contexts = function - | `Bot -> CSet.bot () + | `Bot -> CMap.bot () | `Lifted2 x -> x | _ -> failwith "GVarGG.contexts" let create_spec spec = `Lifted1 spec diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 774c0abc95..287726419f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1930,58 +1930,55 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C and module G = GVarGG (S.G) (S.C) + and module V = GVarF(S.V) = - -struct - module C = S.C - module P = S.P - module D = S.D - - module V = - struct - include GVarF(S.V) - let s x = `Left x - end - - - (*global invariant +(*global invariant - fundec -> Map (S.C) (Set (fundec * S.C)) So: g -> {c' -> f, c} in case f, c --> g, c' *) +struct + include S + module V = GVarF(S.V) + module G = GVarGG (S.G) (S.C) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - type marshal = S.marshal - let init = S.init let finalize = S.finalize (*TODO*) - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - (**let side_context sideg f c = if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) (*TODO Change the body??*) - let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + global = (fun v -> G.s (ctx.global (V.spec v))); + sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } let query ctx = S.query (conv ctx) let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = + + (* c = context + t = set of tuples (fundec * context) + *) + let side_context sideg f c t = if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (conv ctx) (*TODO*) + sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) + + let enter ctx lval fundec exprList = (*TODO*) + S.enter (conv ctx) lval fundec exprList; + let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) + let fd = fundec in (*Callee fundec*) + let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let fd' = in (*Caller fundec*) + let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context sideg fd (c ()) t + let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) From 2841622620ccd483e19794b7dc6be15309e2ce52 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 15:19:07 +0200 Subject: [PATCH 069/628] Introduce to_interval --- src/cdomains/intDomain.ml | 13 ++++++++++--- src/cdomains/intDomain.mli | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index dea3daecd8..ed6ef5a403 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -171,6 +171,7 @@ sig val equal_to: int_t -> t -> [`Eq | `Neq | `Top] val to_bool: t -> bool option + val to_interval: t -> (int_t * int_t) option val to_excl_list: t -> (int_t list * (int64 * int64)) option val of_excl_list: Cil.ikind -> int_t list -> t val is_excl_list: t -> bool @@ -219,7 +220,6 @@ sig val ending : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t val of_int: Cil.ikind -> int_t -> t val of_bool: Cil.ikind -> bool -> t - val to_interval: t -> (int_t * int_t) option val of_interval: ?suppress_ovwarn:bool -> Cil.ikind -> int_t * int_t -> t val of_congruence: Cil.ikind -> int_t * int_t -> t val is_top_of: Cil.ikind -> t -> bool @@ -712,7 +712,7 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) - let to_interval x = x + let to_interval = Fun.id let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1646,6 +1646,7 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x + let to_interval = failwith "Not implemented!" (* FIXME *) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -1720,6 +1721,7 @@ struct let of_excl_list ik x = top_of ik let is_excl_list x = false let to_incl_list x = None + let to_interval x = None let of_interval ?(suppress_ovwarn=false) ik x = top_of ik let of_congruence ik x = top_of ik let starting ?(suppress_ovwarn=false) ikind x = top_of ikind @@ -1803,6 +1805,10 @@ struct | `Bot, `Bot -> `Bot | _ -> `Top + let to_interval = function + | `Lifted x -> Base.to_interval x + | _ -> None + let neg = lift1 Base.neg let add = lift2 Base.add let sub = lift2 Base.sub @@ -2408,6 +2414,7 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero + let to_interval = failwith "Not implemented!" (* FIXME *) let neg x = x let add x y = x || y @@ -3506,7 +3513,7 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) - let to_interval (_, i, _, _, _) = I2.to_interval i + let to_interval (_, i, _, _, _) = Option.bind i I2.to_interval let to_excl_list x = let merge ps = diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index a853c8acca..5a6a4d7c04 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -187,6 +187,9 @@ sig (** Give a boolean interpretation of an abstract value if possible, otherwise * don't return anything.*) + val to_interval: t -> (int_t * int_t) option + (** Gives an interval interpretation if possible. *) + val to_excl_list: t -> (int_t list * (int64 * int64)) option (** Gives a list representation of the excluded values from included range of bits if possible. *) From 93ea56e6c6ad00e642bc3f5188f23fc67d87b133 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 15:50:22 +0200 Subject: [PATCH 070/628] IntervalSet implementation for to_interval --- src/cdomains/intDomain.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index ed6ef5a403..c0bb39518e 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -1270,7 +1270,9 @@ struct let of_bool _ = function true -> one | false -> zero - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) From 6a4c50afd706d64e78e8d8b94ca918d02d03aebd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 16:16:02 +0200 Subject: [PATCH 071/628] Fix to_interval functions --- src/cdomains/intDomain.ml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index c0bb39518e..28fb4ae9e3 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -350,7 +350,7 @@ struct with Failure _ -> top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = failwith "Not implemented!" (* FIXME *) let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik @@ -1648,7 +1648,7 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = Some (x, x) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -2152,7 +2152,9 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2416,7 +2418,7 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = if x then None else Some (Int64.zero, Int64.zero) let neg x = x let add x y = x || y @@ -2546,7 +2548,9 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3282,7 +3286,7 @@ struct let project ik p t = t - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct From 1d0b8286b61655347728d3edf95a697db432a86e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 17:35:45 +0200 Subject: [PATCH 072/628] Add to_interval in valueDomainQueries.ml --- src/domains/valueDomainQueries.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domains/valueDomainQueries.ml b/src/domains/valueDomainQueries.ml index c89e491e58..2dfa72a430 100644 --- a/src/domains/valueDomainQueries.ml +++ b/src/domains/valueDomainQueries.ml @@ -34,6 +34,7 @@ struct let to_int x = unlift_opt I.to_int x let to_bool x = unlift_opt I.to_bool x + let to_interval x = unlift_opt I.to_interval x let is_top_of ik = unlift_is (I.is_top_of ik) From f6fd162321f7468dd371adcc5a221dfb84131e10 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Jun 2023 18:26:05 +0200 Subject: [PATCH 073/628] debugging --- output.txt | 61 ++++++++++++++++++++-------- runningGob.sh | 4 +- src/analyses/termination_new.ml | 8 +--- src/framework/constraints.ml | 6 +-- src/util/terminationPreprocessing.ml | 2 +- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..6ccb110e96 100644 --- a/output.txt +++ b/output.txt @@ -1,3 +1,26 @@ +2023-06-09 18:19:45 +'./goblint' '-v' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '--set' 'ana.activated[+]' 'termination' '--enable' 'warn.debug' '--set' 'ana.activated[+]' 'apron' '--enable' 'ana.int.interval' '--set' 'ana.apron.domain' 'polyhedra' '--enable' 'justcil' +Custom include dirs: + 1. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/include (exists=true) + 2. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/include (exists=false) + 3. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/include (exists=true) + 4. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/include (exists=false) + 5. /home/johanna/goblint/goblint-analyzer/lib/linux/runtime/include (exists=false) + 6. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/runtime/include (exists=false) + 7. /home/johanna/goblint/goblint-analyzer/lib/libc/runtime/include (exists=false) + 8. /home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include (exists=true) + 9. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/src (exists=false) + 10. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src (exists=true) + 11. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/src (exists=true) + 12. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/src (exists=false) +Preprocessing files. +Preprocessor cpp: is_bad=false +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/pthread.c' '-o' '.goblint/preprocessed/pthread.i' +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/stdlib.c' '-o' '.goblint/preprocessed/stdlib.i' +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '-o' '.goblint/preprocessed/01-simple-cases.i' +Parsing files. +Constructors: +Adding constructors to: main /* Generated by CIL v. 2.0.1-48-g4df989f */ /* print_CIL_Input is true */ @@ -1123,7 +1146,7 @@ void example1(void) while_break: /* CIL Label */ ; } #line 27 - term_exit- = term27_5-file_01-simple-cases; + __goblint_bounded(term27_5-file_01-simple-cases); } #line 32 __goblint_check(a[0] == 0); @@ -1165,7 +1188,7 @@ void example2(void) while_break: /* CIL Label */ ; } #line 42 - term_exit- = term42_5-file_01-simple-cases; + __goblint_bounded(term42_5-file_01-simple-cases); } #line 47 __goblint_check(a[0] == 0); @@ -1207,7 +1230,7 @@ void example3(void) while_break: /* CIL Label */ ; } #line 57 - term_exit- = term57_5-file_01-simple-cases; + __goblint_bounded(term57_5-file_01-simple-cases); } #line 62 __goblint_check(a[0] == 0); @@ -1266,7 +1289,7 @@ void example4(void) while_break: /* CIL Label */ ; } #line 74 - term_exit- = term74_5-file_01-simple-cases; + __goblint_bounded(term74_5-file_01-simple-cases); } #line 82 __goblint_check(a[0] == 0); @@ -1321,7 +1344,7 @@ void example5(void) while_break: /* CIL Label */ ; } #line 95 - term_exit- = term95_5-file_01-simple-cases; + __goblint_bounded(term95_5-file_01-simple-cases); } #line 107 __goblint_check(a[0] == 0); @@ -1370,7 +1393,7 @@ void example6(void) while_break: /* CIL Label */ ; } #line 119 - term_exit- = term119_5-file_01-simple-cases; + __goblint_bounded(term119_5-file_01-simple-cases); } #line 125 __goblint_check(a[0] == 0); @@ -1433,7 +1456,7 @@ void example7(void) while_break: /* CIL Label */ ; } #line 143 - term_exit- = term143_2-file_01-simple-cases; + __goblint_bounded(term143_2-file_01-simple-cases); } #line 147 __goblint_check(a[0] == 0); @@ -1506,7 +1529,7 @@ void example8(void) while_break___0: /* CIL Label */ ; } #line 160 - term_exit- = term160_9-file_01-simple-cases; + __goblint_bounded(term160_9-file_01-simple-cases); } #line 164 i ++; @@ -1514,7 +1537,7 @@ void example8(void) while_break: /* CIL Label */ ; } #line 157 - term_exit- = term157_2-file_01-simple-cases; + __goblint_bounded(term157_2-file_01-simple-cases); } #line 166 return; @@ -1557,7 +1580,7 @@ void example9(void) while_break: /* CIL Label */ ; } #line 174 - term_exit- = term174_2-file_01-simple-cases; + __goblint_bounded(term174_2-file_01-simple-cases); } #line 179 return; @@ -1602,7 +1625,7 @@ void example10(void) while_break: /* CIL Label */ ; } #line 187 - term_exit- = term187_2-file_01-simple-cases; + __goblint_bounded(term187_2-file_01-simple-cases); } #line 195 return; @@ -2081,7 +2104,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___0: /* CIL Label */ ; } #line 10 - term_exit- = term10_5-file_stdlib; + __goblint_bounded(term10_5-file_stdlib); } #line 9 i ++; @@ -2089,7 +2112,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break: /* CIL Label */ ; } #line 9 - term_exit- = term9_3-file_stdlib; + __goblint_bounded(term9_3-file_stdlib); } #line 16 i___0 = (size_t )0; @@ -2157,7 +2180,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___3: /* CIL Label */ ; } #line 21 - term_exit- = term21_9-file_stdlib; + __goblint_bounded(term21_9-file_stdlib); } } #line 17 @@ -2166,7 +2189,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___2: /* CIL Label */ ; } #line 17 - term_exit- = term17_5-file_stdlib; + __goblint_bounded(term17_5-file_stdlib); } #line 16 i___0 ++; @@ -2174,7 +2197,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___1: /* CIL Label */ ; } #line 16 - term_exit- = term16_3-file_stdlib; + __goblint_bounded(term16_3-file_stdlib); } #line 33 return; @@ -2227,9 +2250,13 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size while_break: /* CIL Label */ ; } #line 40 - term_exit- = term40_3-file_stdlib; + __goblint_bounded(term40_3-file_stdlib); } #line 47 return ((void *)0); } } + +vars = 0 evals = 0 narrow_reuses = 0 + +Timings: diff --git a/runningGob.sh b/runningGob.sh index 52d0830b81..e9d7ab1405 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -16,8 +16,8 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint -v $cfile_loops $options_term --enable justcil > output.txt +./goblint -v $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index bff776b95d..bd2057effe 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -80,10 +80,6 @@ end let () = (** Register the preprocessing *) -<<<<<<< HEAD - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); -======= - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); ->>>>>>> dfa9d6ef8 (changed loop exit indicator form global variable to a special function) - (** Register this analysis within the master control program *) +Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); +(** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 287726419f..0d68a1a028 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1970,14 +1970,14 @@ struct sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) let enter ctx lval fundec exprList = (*TODO*) - S.enter (conv ctx) lval fundec exprList; - let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) + S.enter (conv ctx) lval fundec exprList + (*let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) let fd = fundec in (*Callee fundec*) let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) let fd' = in (*Caller fundec*) let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context sideg fd (c ()) t + side_context sideg fd (c ()) t*) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 15a5c948fd..41c5b3f9d7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -23,7 +23,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc (fd : fundec) = object(self) +class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with From 5ae6485e116db3eb00b6653a747262e821b8fc06 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 18:48:14 +0200 Subject: [PATCH 074/628] Fix check_bounded --- src/analyses/termination_new.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index f1dde59c64..8629cac17f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -20,21 +20,21 @@ let is_loop_exit_indicator (x : varinfo) = (* checks if at the current location (=loc) of the analysis an upjumping goto was already reached true: no upjumping goto was reached till now*) -let currrently_no_upjumping_gotos (loc : location) = +let currrently_no_upjumping_gotos (loc : location) = List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents -let no_upjumping_gotos () = +let no_upjumping_gotos () = (List.length upjumpingGotos.contents) <= 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = - let open IntDomain.IntDomTuple in (* TODO: Remove *) - let open Cil in + let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - `Top -> print_endline (varinfo.vname ^ " is TOP"); false + | `Top -> print_endline (varinfo.vname ^ " is TOP"); false | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") - | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); not (is_top v) (* TODO: Is this sound? *) + | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); + not (is_top_of (ikind v) v) module Spec : Analyses.MCPSpec = struct From b6e08f2d3efb4feebf4bf82f2d346666e2b9d9ee Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 18:50:22 +0200 Subject: [PATCH 075/628] Remove debug output --- src/analyses/termination_new.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 8629cac17f..1eac676d91 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -31,10 +31,9 @@ let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - | `Top -> print_endline (varinfo.vname ^ " is TOP"); false - | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") - | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); - not (is_top_of (ikind v) v) + | `Top -> false + | `Lifted v -> not (is_top_of (ikind v) v) + | `Bot -> raise (PreProcessing "Loop variable is Bot") module Spec : Analyses.MCPSpec = struct From beb56834d29cdb0dd2497dfb9e3dc113b17ca8e5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Jun 2023 20:00:41 +0200 Subject: [PATCH 076/628] it runs! :)) but it is not possible to see the global invariant on the html output yet --- runningGob.sh | 2 +- src/framework/analyses.ml | 5 +- src/framework/constraints.ml | 189 ++++++++++++++++++++++++++++++++--- src/framework/control.ml | 1 + 4 files changed, 180 insertions(+), 17 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index e9d7ab1405..848d69c341 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -17,7 +17,7 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" # run analysis, write cil output to file and enable visualization via html #./goblint -v $cfile_loops $options_term --enable justcil > output.txt -./goblint -v $cfile_loops $options_term --html +./goblint $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 41448768a9..993aaf6421 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -166,7 +166,6 @@ struct struct include MapDomain.MapBot (C_ (C)) (CSet) let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) - let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) @@ -184,8 +183,8 @@ struct let printXml f = function | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x let s = function (*TODO: does this work? copied from DeadBranch*) | `Bot -> G.bot () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0d68a1a028..1614354cfa 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1457,6 +1457,145 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + +module DeadBranchLifter2 (S: Spec): Spec = +struct + include S + + let name () = "DeadBranch2 (" ^ S.name () ^ ")" + + (* Two global invariants: + 1. S.V -> S.G -- used for S + 2. node -> (exp -> flat bool) -- used for warnings *) + + module V = + struct + include Printable.Either (S.V) (Node) + let name () = "DeadBranch2" + let s x = `Left x + let node x = `Right x + let is_write_only = function + | `Left x -> S.V.is_write_only x + | `Right _ -> true + end + + module EM = + struct + include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) + let name () = "branches2" + end + + module G = + struct + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + let name () = "deadbranch2" + + let s = function + | `Bot -> S.G.bot () + | `Lifted1 x -> x + | _ -> failwith "DeadBranchLifter2.s" + let node = function + | `Bot -> EM.bot () + | `Lifted2 x -> x + | _ -> failwith "DeadBranchLifter2.node" + let create_s s = `Lifted1 s + let create_node node = `Lifted2 node + + let printXml f = function + | `Lifted1 x -> S.G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + let em = G.node (ctx.global (V.node g)) in + EM.iter (fun exp tv -> + match tv with + | `Lifted tv -> + let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) + let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in + M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv + | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) + M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp + | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) + | `Top -> (* may be both true and false *) + () + ) em; + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | IterSysVars (vq, vf) -> + (* vars for S *) + let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in + S.query (conv ctx) (IterSysVars (vq, vf')); + + (* node vars for dead branches *) + begin match vq with + | Node {node; _} -> + vf (Obj.repr (V.node node)) + | _ -> + () + end + | _ -> + S.query (conv ctx) q + + + let branch ctx = S.branch (conv ctx) + + let branch ctx exp tv = + if !AnalysisState.postsolving then ( + try + let r = branch ctx exp tv in + (* branch is live *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) + r + with Deadcode -> + (* branch is dead *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) + raise Deadcode + ) + else ( + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) + branch ctx exp tv + ) + + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) + let enter ctx = S.enter (conv ctx) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) +end + + module LongjmpLifter (S: Spec): Spec = struct include S @@ -1929,8 +2068,6 @@ end module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C - and module G = GVarGG (S.G) (S.C) - and module V = GVarF(S.V) = (*global invariant - fundec -> Map (S.C) (Set (fundec * S.C)) @@ -1939,7 +2076,11 @@ module RecursionTermLifter (S: Spec) struct include S - module V = GVarF(S.V) + module V = + struct + include GVarF(S.V) + let s = spec + end module G = GVarGG (S.G) (S.C) @@ -1957,7 +2098,26 @@ struct global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } - let query ctx = S.query (conv ctx) + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | _ -> S.query (conv ctx) q + let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) @@ -1969,15 +2129,18 @@ struct if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - let enter ctx lval fundec exprList = (*TODO*) - S.enter (conv ctx) lval fundec exprList - (*let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) - let fd = fundec in (*Callee fundec*) - let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) - let fd' = in (*Caller fundec*) - let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context sideg fd (c ()) t*) + let enter ctx lval fu exprList = (*TODO*) + if !AnalysisState.postsolving then + let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let fd_r : fundec = fu in (*Caller fundec*) (*TODO: Falsch??*) + let c_e : unit -> S.C.t = ctx.context in (*Callee context*) (*TODO: Falsch??*) + let fd_e : fundec = fu in (*Callee fundec*) + let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in (* TODO: is fundec the caller or callee fundec???*) + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context ctx.sideg fd_e (c_e ()) t; + S.enter (conv ctx) lval fu exprList + else + S.enter (conv ctx) lval fu exprList let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..0a36d6c989 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -37,6 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter2) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From b01d69e94d12defa37810b8516e9d9b744cdbbfe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:11:40 +0200 Subject: [PATCH 077/628] Remove unused stuff --- src/analyses/termination_new.ml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1eac676d91..ef623b468b 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -include Printf exception PreProcessing of string @@ -63,10 +62,6 @@ struct D.add x is_bounded ctx.local | _ -> ctx.local - let branch ctx (exp : exp) (tv : bool) = - ctx.local (* TODO: Do we actually need a branch transfer function? *) - - (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in From 6ee3312220b2838ea34033be3fc81ca995232be6 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:17:44 +0200 Subject: [PATCH 078/628] Make things nice, update comments --- src/analyses/termination_new.ml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index ef623b468b..4eced288df 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -7,7 +7,9 @@ open TerminationPreprocessing exception PreProcessing of string let loopCounters : varinfo list ref = ref [] -let upjumpingGotos : location list ref = ref [] (*contains the locations of the upjumping gotos*) + +(* Contains the locations of the upjumping gotos *) +let upjumpingGotos : location list ref = ref [] let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) @@ -17,8 +19,9 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loopExit -(* checks if at the current location (=loc) of the analysis an upjumping goto was already reached - true: no upjumping goto was reached till now*) +(** Checks whether at the current location (=loc) of the analysis an + * upjumping goto was already reached. Returns true if no upjumping goto was + * reached until now *) let currrently_no_upjumping_gotos (loc : location) = List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents @@ -49,33 +52,33 @@ struct include Analyses.IdentitySpec let assign ctx (lval : lval) (rval : exp) = - (* Detect loop counter variable assignment to 0 *) + (* Detect assignment to loop counter variable *) match lval, rval with - (* Assume that the following loop does not terminate *) (Var x, NoOffset), _ when is_loop_counter_var x -> + (* Assume that the following loop does not terminate *) if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local - (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) let is_bounded = check_bounded ctx x in if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local - (* provides information to Goblint*) + (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> - true (* TODO should we use the checl_bound function?*) + true (* TODO should we use the check_bounded function? *) | Queries.MustTermProg -> - true (*TODO check if all values in the domain are true -> true*) + true (*TODO check if all values in the domain are true -> true *) | _ -> Result.top q end let () = - (** Register the preprocessing *) + (* Register the preprocessing *) Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); - (** Register this analysis within the master control program *) + (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 3cc743ab2e55758c0f5e58c51188f24b5d487d37 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:21:49 +0200 Subject: [PATCH 079/628] Unify style to snake_case --- src/analyses/termination_new.ml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4eced288df..7a7f046c39 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,27 +6,27 @@ open TerminationPreprocessing exception PreProcessing of string -let loopCounters : varinfo list ref = ref [] +let loop_counters : varinfo list ref = ref [] (* Contains the locations of the upjumping gotos *) -let upjumpingGotos : location list ref = ref [] +let upjumping_gotos : location list ref = ref [] -let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) +let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loopCounters + List.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = - x = !loopExit + x = !loop_exit (** Checks whether at the current location (=loc) of the analysis an * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents + List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumpingGotos.contents) <= 0 + (List.length upjumping_gotos.contents) <= 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -79,6 +79,6 @@ end let () = (* Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos loop_exit); (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From ba6eaa170392bde34e82ac84d533a4e837f48d74 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:24:00 +0200 Subject: [PATCH 080/628] Make ocamldoc comment --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7a7f046c39..9c87a4038e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -8,7 +8,7 @@ exception PreProcessing of string let loop_counters : varinfo list ref = ref [] -(* Contains the locations of the upjumping gotos *) +(** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) From 8f457230d7cee30965a124933963f8908b01a28f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:39:59 +0200 Subject: [PATCH 081/628] Remove debug output --- src/analyses/termination_new.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 9c87a4038e..19198c4ca9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -56,12 +56,10 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) let is_bounded = check_bounded ctx x in - if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local From f66d46fac00e6ecbe4d7dbf4cf4367b35e877e74 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:03:26 +0200 Subject: [PATCH 082/628] Implement preliminary query function --- src/analyses/termination_new.ml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 19198c4ca9..503b3f2d51 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -59,18 +59,26 @@ struct D.add x false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move *) let is_bounded = check_bounded ctx x in D.add x is_bounded ctx.local | _ -> ctx.local + let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = + (* TODO: Implement check for our special loop exit indicator function *) + ctx.local + (** Provides information to Goblint *) + (* TODO: Consider gotos and recursion *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v when check_bounded ctx v -> - true (* TODO should we use the check_bounded function? *) + | Queries.MustTermLoop v -> + (match D.find_opt v ctx.local with + Some b -> b + | None -> Result.top q) | Queries.MustTermProg -> - true (*TODO check if all values in the domain are true -> true *) + D.for_all (fun loop term_info -> term_info) ctx.local | _ -> Result.top q end From d0b42d1b5b57fc7c2e0f884ea3ef2c4ea86db8f7 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:20:10 +0200 Subject: [PATCH 083/628] Remove function to_interval --- src/cdomains/intDomain.ml | 25 ------------------------- src/cdomains/intDomain.mli | 13 +++++-------- src/domains/valueDomainQueries.ml | 1 - 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 9932e2fa67..df0a4c0507 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -171,7 +171,6 @@ sig val equal_to: int_t -> t -> [`Eq | `Neq | `Top] val to_bool: t -> bool option - val to_interval: t -> (int_t * int_t) option val to_excl_list: t -> (int_t list * (int64 * int64)) option val of_excl_list: Cil.ikind -> int_t list -> t val is_excl_list: t -> bool @@ -350,8 +349,6 @@ struct with Failure _ -> top_of ik - let to_interval x = failwith "Not implemented!" (* FIXME *) - let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik let ending ?(suppress_ovwarn=false) ik x = @@ -431,7 +428,6 @@ struct let of_excl_list ikind is = {v = I.of_excl_list ikind is; ikind} let is_excl_list x = I.is_excl_list x.v let to_incl_list x = I.to_incl_list x.v - let to_interval x = I.to_interval x.v let of_interval ?(suppress_ovwarn=false) ikind (lb,ub) = {v = I.of_interval ~suppress_ovwarn ikind (lb,ub); ikind} let of_congruence ikind (c,m) = {v = I.of_congruence ikind (c,m); ikind} let starting ?(suppress_ovwarn=false) ikind i = {v = I.starting ~suppress_ovwarn ikind i; ikind} @@ -712,7 +708,6 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) - let to_interval = Fun.id let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1270,10 +1265,6 @@ struct let of_bool _ = function true -> one | false -> zero - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None - let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) let of_int ik (x: int_t) = of_interval ik (x, x) @@ -1648,7 +1639,6 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x - let to_interval x = Some (x, x) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -1723,7 +1713,6 @@ struct let of_excl_list ik x = top_of ik let is_excl_list x = false let to_incl_list x = None - let to_interval x = None let of_interval ?(suppress_ovwarn=false) ik x = top_of ik let of_congruence ik x = top_of ik let starting ?(suppress_ovwarn=false) ikind x = top_of ikind @@ -1807,10 +1796,6 @@ struct | `Bot, `Bot -> `Bot | _ -> `Top - let to_interval = function - | `Lifted x -> Base.to_interval x - | _ -> None - let neg = lift1 Base.neg let add = lift2 Base.add let sub = lift2 Base.sub @@ -2152,9 +2137,6 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2418,7 +2400,6 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero - let to_interval x = if x then None else Some (Int64.zero, Int64.zero) let neg x = x let add x y = x || y @@ -2548,9 +2529,6 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3286,7 +3264,6 @@ struct let project ik p t = t - let to_interval x = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct @@ -3519,8 +3496,6 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) - let to_interval (_, i, _, _, _) = Option.bind i I2.to_interval - let to_excl_list x = let merge ps = let (vs, rs) = List.split ps in diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index 5a6a4d7c04..c7b59e4c23 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -187,9 +187,6 @@ sig (** Give a boolean interpretation of an abstract value if possible, otherwise * don't return anything.*) - val to_interval: t -> (int_t * int_t) option - (** Gives an interval interpretation if possible. *) - val to_excl_list: t -> (int_t list * (int64 * int64)) option (** Gives a list representation of the excluded values from included range of bits if possible. *) @@ -235,7 +232,7 @@ sig val invariant: Cil.exp -> t -> Invariant.t end (** Interface of IntDomain implementations that do not take ikinds for arithmetic operations yet. - TODO: Should be ported to S in the future. *) + TODO: Should be ported to S in the future. *) module type S = sig @@ -415,10 +412,10 @@ module IntervalSetFunctor(Ints_t : IntOps.IntOps): SOverflow with type int_t = I module Interval32 :Y with (* type t = (IntOps.Int64Ops.t * IntOps.Int64Ops.t) option and *) type int_t = IntOps.Int64Ops.t module BigInt: - sig - include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) - val cast_to: Cil.ikind -> Z.t -> Z.t - end +sig + include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) + val cast_to: Cil.ikind -> Z.t -> Z.t +end module Interval : SOverflow with type int_t = IntOps.BigIntOps.t diff --git a/src/domains/valueDomainQueries.ml b/src/domains/valueDomainQueries.ml index 2f28f729ea..d366e6dda3 100644 --- a/src/domains/valueDomainQueries.ml +++ b/src/domains/valueDomainQueries.ml @@ -34,7 +34,6 @@ struct let to_int x = unlift_opt I.to_int x let to_bool x = unlift_opt I.to_bool x - let to_interval x = unlift_opt I.to_interval x let is_top_of ik = unlift_is (I.is_top_of ik) From ffd6d4c1234bfa352655493370128044536ec8b5 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:27:28 +0200 Subject: [PATCH 084/628] Add dummy finalize function --- src/analyses/termination_new.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 503b3f2d51..ce0b36121e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -48,6 +48,8 @@ struct let startstate _ = D.bot () let exitstate = startstate (* TODO *) + let finalize () = () (* TODO *) + (** Provides some default implementations *) include Analyses.IdentitySpec From 090e704e72f2e9ba4626f9ca53505f7e03671c9e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 16:22:52 +0200 Subject: [PATCH 085/628] WIP on final loop termination report --- src/analyses/termination_new.ml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index ce0b36121e..44b0c7fb5e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -37,22 +37,31 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") +module FunContextV : Analyses.SpecSysVar = +struct + include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) + include Analyses.StdV +end + + module Spec : Analyses.MCPSpec = struct + (** Provides some default implementations *) + include Analyses.IdentitySpec + let name () = "termination" module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) module C = D + module V = FunContextV + (* TODO *) let startstate _ = D.bot () let exitstate = startstate (* TODO *) let finalize () = () (* TODO *) - (** Provides some default implementations *) - include Analyses.IdentitySpec - let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with From 82bb72dd579517d4357488185080beaea13e5fa0 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 15 Jun 2023 12:32:00 +0200 Subject: [PATCH 086/628] Test case term:20 fixed --- tests/regression/80-termination/20-rand-nonterminating.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 6639e5bc76..88f6f50bd4 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i <= 0; i++) // NOTERM + for (int i = 1; i >= 0; i++) // NOTERM { printf("Loop inside if part: %d\n", i); } @@ -20,10 +20,9 @@ int main() { // Loop inside the else part int j = 1; - while (j < 5) // NOTERM + while (j > 0) // NOTERM { printf("Loop inside else part: %d\n", j); - j++; } } From 37848d8eec23ea6e6d2423a279f80e2a55fce43c Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 15 Jun 2023 13:41:05 +0200 Subject: [PATCH 087/628] Test cases for term with polyhedra --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- tests/regression/80-termination/11-loopless-termination.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/80-termination/17-goto-terminating.c | 2 +- tests/regression/80-termination/18-goto-nonterminating.c | 2 +- tests/regression/80-termination/19-rand-terminating.c | 2 +- tests/regression/80-termination/20-rand-nonterminating.c | 2 +- .../regression/80-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/23-exit-on-rand-terminating.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 508b31500c..ed28fa9b43 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9d5cd4b928..3a19f17bee 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c index b118e65e35..7aeed0145d 100644 --- a/tests/regression/80-termination/11-loopless-termination.c +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// TERM +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 1ea228ae55..e5383aed66 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index 10aa729837..dcf72552bc 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index dbb7a3df59..672128e009 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c index 1d226f0df2..879ae3748a 100644 --- a/tests/regression/80-termination/19-rand-terminating.c +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 88f6f50bd4..27c3f2c388 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index 4510ac1bb7..0edafe0f65 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 97b18ed5fc..5c270f3b2a 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 5e2be62637..f793275b1f 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From ff5755833c8539dd48bb7fd49afdc8b0fedf5784 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 16 Jun 2023 11:13:51 +0200 Subject: [PATCH 088/628] filling of global constraint happens in combine_env --- output.txt | 2262 ---------------------------------- runningGob.sh | 2 +- src/framework/analyses.ml | 18 +- src/framework/constraints.ml | 171 +-- src/framework/control.ml | 3 +- 5 files changed, 33 insertions(+), 2423 deletions(-) diff --git a/output.txt b/output.txt index 6ccb110e96..e69de29bb2 100644 --- a/output.txt +++ b/output.txt @@ -1,2262 +0,0 @@ -2023-06-09 18:19:45 -'./goblint' '-v' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '--set' 'ana.activated[+]' 'termination' '--enable' 'warn.debug' '--set' 'ana.activated[+]' 'apron' '--enable' 'ana.int.interval' '--set' 'ana.apron.domain' 'polyhedra' '--enable' 'justcil' -Custom include dirs: - 1. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/include (exists=true) - 2. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/include (exists=false) - 3. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/include (exists=true) - 4. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/include (exists=false) - 5. /home/johanna/goblint/goblint-analyzer/lib/linux/runtime/include (exists=false) - 6. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/runtime/include (exists=false) - 7. /home/johanna/goblint/goblint-analyzer/lib/libc/runtime/include (exists=false) - 8. /home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include (exists=true) - 9. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/src (exists=false) - 10. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src (exists=true) - 11. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/src (exists=true) - 12. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/src (exists=false) -Preprocessing files. -Preprocessor cpp: is_bad=false -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/pthread.c' '-o' '.goblint/preprocessed/pthread.i' -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/stdlib.c' '-o' '.goblint/preprocessed/stdlib.i' -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '-o' '.goblint/preprocessed/01-simple-cases.i' -Parsing files. -Constructors: -Adding constructors to: main -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -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 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 28 - a[i] = i; -#line 29 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 27 - __goblint_bounded(term27_5-file_01-simple-cases); - } -#line 32 - __goblint_check(a[0] == 0); -#line 33 - __goblint_check(a[3] == 3); -#line 34 - return; -} -} -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term42_5-file_01-simple-cases ; - - { -#line 40 - i = 0; - { -#line 42 - term42_5-file_01-simple-cases = 0; - { -#line 42 - while (1) { - while_continue: /* CIL Label */ ; -#line 43 - a[i] = i; -#line 44 - i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 - if (! (i <= 5)) { -#line 42 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 42 - __goblint_bounded(term42_5-file_01-simple-cases); - } -#line 47 - __goblint_check(a[0] == 0); -#line 48 - __goblint_check(a[3] == 3); -#line 49 - return; -} -} -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term57_5-file_01-simple-cases ; - - { -#line 55 - i = 0; - { -#line 57 - term57_5-file_01-simple-cases = 0; - { -#line 57 - while (1) { - while_continue: /* CIL Label */ ; -#line 57 - if (! (i < 5)) { -#line 57 - goto while_break; - } -#line 57 - term57_5-file_01-simple-cases ++; -#line 58 - a[i] = i; -#line 59 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 57 - __goblint_bounded(term57_5-file_01-simple-cases); - } -#line 62 - __goblint_check(a[0] == 0); -#line 63 - __goblint_check(a[3] == 0); -#line 64 - __goblint_check(a[7] == 0); -#line 65 - return; -} -} -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term74_5-file_01-simple-cases ; - - { -#line 71 - i = 0; -#line 72 - first_iteration = 1; - { -#line 74 - term74_5-file_01-simple-cases = 0; - { -#line 74 - while (1) { - while_continue: /* CIL Label */ ; -#line 74 - if (! (i < 10)) { -#line 74 - goto while_break; - } -#line 74 - term74_5-file_01-simple-cases ++; -#line 75 - if (first_iteration == 1) { -#line 75 - __goblint_check(i == 0); - } else -#line 76 - if (i > 5) { -#line 76 - __goblint_check(i == 6); - } -#line 77 - first_iteration = 0; -#line 78 - a[i] = 0; -#line 79 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 74 - __goblint_bounded(term74_5-file_01-simple-cases); - } -#line 82 - __goblint_check(a[0] == 0); -#line 83 - __goblint_check(first_iteration == 0); -#line 84 - return; -} -} -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term95_5-file_01-simple-cases ; - - { -#line 92 - i = 0; -#line 93 - top = 0; - { -#line 95 - term95_5-file_01-simple-cases = 0; - { -#line 95 - while (1) { - while_continue: /* CIL Label */ ; -#line 95 - if (! (i < 4)) { -#line 95 - goto while_break; - } -#line 95 - term95_5-file_01-simple-cases ++; -#line 96 - a[i] = 0; -#line 97 - top += i; -#line 98 - if (i == 2) { -#line 99 - __goblint_check(top == 3); - } else { -#line 102 - __goblint_check(top == 3); - } -#line 104 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 95 - __goblint_bounded(term95_5-file_01-simple-cases); - } -#line 107 - __goblint_check(a[0] == 0); -#line 108 - __goblint_check(a[3] == 0); -#line 109 - __goblint_check(top == 6); -#line 110 - return; -} -} -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term119_5-file_01-simple-cases ; - - { -#line 116 - i = 0; -#line 117 - top = 0; - { -#line 119 - term119_5-file_01-simple-cases = 0; - { -#line 119 - while (1) { - while_continue: /* CIL Label */ ; -#line 119 - if (! (i < 3)) { -#line 119 - goto while_break; - } -#line 119 - term119_5-file_01-simple-cases ++; -#line 120 - a[i] = 0; -#line 121 - __goblint_check(a[0] == 0); -#line 122 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 119 - __goblint_bounded(term119_5-file_01-simple-cases); - } -#line 125 - __goblint_check(a[0] == 0); -#line 126 - __goblint_check(a[3] == 0); -#line 127 - __goblint_check(top == 6); -#line 128 - return; -} -} -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 132 - if (i > 5) { -#line 133 - return (0); - } else { -#line 136 - return (1); - } -} -} -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term143_2-file_01-simple-cases ; - - { -#line 142 - i = 0; - { -#line 143 - term143_2-file_01-simple-cases = 0; - { -#line 143 - while (1) { - while_continue: /* CIL Label */ ; -#line 143 - tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 - if (! tmp) { -#line 143 - goto while_break; - } -#line 144 - a[i] = i; -#line 145 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 143 - __goblint_bounded(term143_2-file_01-simple-cases); - } -#line 147 - __goblint_check(a[0] == 0); -#line 148 - __goblint_check(a[6] == 0); -#line 149 - return; -} -} -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; - - { -#line 155 - b[0] = 0; -#line 155 - b[1] = 0; -#line 155 - b[2] = 0; -#line 155 - b[3] = 0; -#line 155 - b[4] = 0; -#line 156 - i = 0; - { -#line 157 - term157_2-file_01-simple-cases = 0; - { -#line 157 - while (1) { - while_continue: /* CIL Label */ ; -#line 157 - if (! (i < 5)) { -#line 157 - goto while_break; - } -#line 157 - term157_2-file_01-simple-cases ++; -#line 158 - a[i] = i; -#line 159 - j = 0; - { -#line 160 - term160_9-file_01-simple-cases = 0; - { -#line 160 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 160 - if (! (j < 5)) { -#line 160 - goto while_break___0; - } -#line 160 - term160_9-file_01-simple-cases ++; -#line 161 - b[j] += a[i]; -#line 162 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 160 - __goblint_bounded(term160_9-file_01-simple-cases); - } -#line 164 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 157 - __goblint_bounded(term157_2-file_01-simple-cases); - } -#line 166 - return; -} -} -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term174_2-file_01-simple-cases ; - - { -#line 173 - i = 0; - { -#line 174 - term174_2-file_01-simple-cases = 0; - { -#line 174 - while (1) { - while_continue: /* CIL Label */ ; -#line 174 - if (! 1) { -#line 174 - goto while_break; - } -#line 174 - term174_2-file_01-simple-cases ++; -#line 175 - a[i] = i; -#line 176 - i ++; -#line 177 - if (i == 5) { -#line 177 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 174 - __goblint_bounded(term174_2-file_01-simple-cases); - } -#line 179 - return; -} -} -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term187_2-file_01-simple-cases ; - - { -#line 186 - i = 0; - { -#line 187 - term187_2-file_01-simple-cases = 0; - { -#line 187 - while (1) { - while_continue: /* CIL Label */ ; -#line 187 - if (! (i < 5)) { -#line 187 - goto while_break; - } -#line 187 - term187_2-file_01-simple-cases ++; -#line 188 - if (i == 3) { -#line 189 - i ++; -#line 190 - goto while_continue; - } -#line 192 - a[i] = i; -#line 193 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 187 - __goblint_bounded(term187_2-file_01-simple-cases); - } -#line 195 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 249 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 272 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 326 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 10 - __goblint_bounded(term10_5-file_stdlib); - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 9 - __goblint_bounded(term9_3-file_stdlib); - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } -#line 21 - __goblint_bounded(term21_9-file_stdlib); - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } -#line 17 - __goblint_bounded(term17_5-file_stdlib); - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } -#line 16 - __goblint_bounded(term16_3-file_stdlib); - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 40 - __goblint_bounded(term40_3-file_stdlib); - } -#line 47 - return ((void *)0); -} -} - -vars = 0 evals = 0 narrow_reuses = 0 - -Timings: diff --git a/runningGob.sh b/runningGob.sh index 848d69c341..15007b3e0b 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,6 +1,6 @@ #!/bin/bash make -#make install +make install # set options and file for apron execution options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 993aaf6421..0a7ccd04b2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -139,7 +139,13 @@ struct let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = Base1.printXml f a; Base2.printXml f b (*Todo: what do we have to put here?*) + let printXml f (a,b) = + BatPrintf.fprintf f "\n + Tuple:\n + \n + fundec\n%a\n\n + context\n%a\n\n + \n" Base1.printXml a Base2.printXml b (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in let b = Base2.compare b1 b2 in @@ -150,22 +156,26 @@ struct end -module GVarGG (G: Lattice.S) (C: Printable.S) = +module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = struct include SetDomain.Make ( struct - include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + include (Base) (* Set of Tuples*) end ) let name () = "contexts" + let printXml f a = + BatPrintf.fprintf f "\n\n"; + iter (Base.printXml f) a; + BatPrintf.fprintf f "\n\n" end module CMap = struct include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1614354cfa..31843794ec 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1458,144 +1458,6 @@ struct end -module DeadBranchLifter2 (S: Spec): Spec = -struct - include S - - let name () = "DeadBranch2 (" ^ S.name () ^ ")" - - (* Two global invariants: - 1. S.V -> S.G -- used for S - 2. node -> (exp -> flat bool) -- used for warnings *) - - module V = - struct - include Printable.Either (S.V) (Node) - let name () = "DeadBranch2" - let s x = `Left x - let node x = `Right x - let is_write_only = function - | `Left x -> S.V.is_write_only x - | `Right _ -> true - end - - module EM = - struct - include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches2" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "deadbranch2" - - let s = function - | `Bot -> S.G.bot () - | `Lifted1 x -> x - | _ -> failwith "DeadBranchLifter2.s" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter2.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - module LongjmpLifter (S: Spec): Spec = struct include S @@ -2082,12 +1944,10 @@ struct let s = spec end - module G = GVarGG (S.G) (S.C) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - let finalize = S.finalize (*TODO*) - (**let side_context sideg f c = if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) @@ -2098,6 +1958,8 @@ struct global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } + + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal g -> @@ -2129,23 +1991,24 @@ struct if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - let enter ctx lval fu exprList = (*TODO*) - if !AnalysisState.postsolving then - let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) - let fd_r : fundec = fu in (*Caller fundec*) (*TODO: Falsch??*) - let c_e : unit -> S.C.t = ctx.context in (*Callee context*) (*TODO: Falsch??*) - let fd_e : fundec = fu in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in (* TODO: is fundec the caller or callee fundec???*) - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context ctx.sideg fd_e (c_e ()) t; - S.enter (conv ctx) lval fu exprList - else - S.enter (conv ctx) lval fu exprList + let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) + let combine_env ctx r fe f args fc es f_ask = (*Todo*) + if !AnalysisState.postsolving then + let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let nodeF = ctx.node in + let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) + let c_e: S.C.t = Option.get (fc) in (*Callee context*) + let fd_e : fundec = f in (*Callee fundec*) + let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context ctx.sideg fd_e (c_e) t; + S.combine_env (conv ctx) r fe f args fc es f_ask + else + S.combine_env (conv ctx) r fe f args fc es f_ask let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) let threadenter ctx = S.threadenter (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index 0a36d6c989..6261329e18 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -37,8 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter2) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From 478cb410e4c84154025ef81c660050ccb08b858d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 16 Jun 2023 15:11:39 +0200 Subject: [PATCH 089/628] updated hash and compare of tuple --- src/framework/analyses.ml | 39 ++++-- src/framework/constraints.ml | 245 +---------------------------------- 2 files changed, 34 insertions(+), 250 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 0a7ccd04b2..90be60b779 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -124,15 +124,18 @@ module C_ (C: Printable.S)= struct include C include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + " + callee_context:\n%a\n\n + " printXml c (* wrap in for HTML printing *) end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * C.t) + type t = (CilType.Fundec.t * Base2.t) let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) @@ -143,16 +146,30 @@ struct BatPrintf.fprintf f "\n Tuple:\n \n - fundec\n%a\n\n - context\n%a\n\n - \n" Base1.printXml a Base2.printXml b (*Todo: what do we have to put here?*) - let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) - (*let a = Base1.compare a1 a2 in - let b = Base2.compare b1 b2 in - *) + caller_fundec\n%a\n\n + caller_context\n%a\n\n + \n" Base1.printXml a Base2.printXml b + + (*Result of compare: + start with inital value of 0 + - a1 > a2: +1 + - a1 < a2: -1 + - b1 > b2: +3 + - b1 < b2: -3 + *) + let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) + let res = ref 0 in + let comp_a = Base1.compare a1 a2 in + let comp_b = Base2.compare b1 b2 in + if (comp_a > 0) then res := !(res) + 1 + else if (comp_a < 0) then res := !(res) - 1; + if (comp_b > 0) then res := !(res) + 3 + else if (comp_b < 0) then res := !(res) - 3; + !res + let pretty () x = text (show x) - let hash (a,b) = 2 (*Todo: what do we have to put here?*) + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 31843794ec..143d417cc6 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1694,237 +1694,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(* -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C_ = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C_) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) (*Todo: do we need lift2?*) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end -*) -(*GMapG (S.G) (S.C)*) -(*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - - -(*module type FundecType = - sig - type t = fundec - - val getFundec: t -> fundec - (* Define any other values or types exposed by the module *) - end - - module Fundec (F:fundec) : FundecType = - struct - let getFundec = F - let fname = F.fname - end*) - (* - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal)*) (*(*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end*) -(*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) - let s = function - | `Bot -> S.G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" - end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1944,14 +1713,10 @@ struct let s = spec end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - (*TODO Change the body??*) let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with @@ -1968,6 +1733,8 @@ struct | `Left g -> S.query (conv ctx) (WarnGlobal (Obj.repr g)) | `Right g -> + (*TODO: Implement cycle detection algorithm here*) + Queries.Result.top q end | InvariantGlobal g -> @@ -1992,18 +1759,18 @@ struct sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) let combine_env ctx r fe f args fc es f_ask = (*Todo*) if !AnalysisState.postsolving then - let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let c_r: S.C.t = ctx.context () in (*Caller context*) (*TODO is this the caller or callee context???*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in + + let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask From 7ac939a00cfcb4b9d96c16bd1bc0e3c8740efc72 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Fri, 16 Jun 2023 22:14:12 +0200 Subject: [PATCH 090/628] added implementation for DFS for cycles in Callgraph; Not testet --- src/framework/analyses.ml | 11 +++++++-- src/framework/constraints.ml | 45 ++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 0a7ccd04b2..a5e250c4ed 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -129,11 +129,13 @@ struct end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * C.t) + type t = (CilType.Fundec.t * Base2.t) + let fundec (a,_) = a + let context (_,b) = b let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" @@ -202,6 +204,11 @@ struct | _ -> failwith "RecursionTerm.s" let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + + let base2 instance = + match instance with + | `Lifted2 n -> Some n + | _ -> None end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 31843794ec..b256d8ecbd 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1941,10 +1941,9 @@ struct module V = struct include GVarF(S.V) - let s = spec end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1965,19 +1964,35 @@ struct | WarnGlobal g -> let g: V.t = Obj.obj g in begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end + | `Left g' -> + S.query (conv ctx) (WarnGlobal (Obj.repr g')) + | `Right g' -> + let module LH = Hashtbl.Make (T (CilType.Fundec) (C)) in + let module LS = Set.Make (T (CilType.Fundec) (C)) in + (* TODO: find all cycles/SCCs *) + let global_visited_calls = LH.create 100 in + + (* DFS *) + let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = + if LS.mem call path_visited_calls then + let msgs = + [ + (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); + (Pretty.dprintf "lock after: with", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; + S.query (conv ctx) q + else if not (LH.mem global_visited_calls call) then begin + LH.replace global_visited_calls call (); + let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) + let new_path_visited_calls = LS.add call path_visited_calls in + G.CSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers + end + in + S.query (conv ctx) q + end | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From df59fd78c1bd6577969e517deb9db4dd8b956b6a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 09:57:13 +0200 Subject: [PATCH 091/628] just comments --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 143d417cc6..35b553135a 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1734,7 +1734,7 @@ struct S.query (conv ctx) (WarnGlobal (Obj.repr g)) | `Right g -> (*TODO: Implement cycle detection algorithm here*) - + Queries.Result.top q end | InvariantGlobal g -> @@ -1762,16 +1762,16 @@ struct let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx r fe f args fc es f_ask = (*Todo*) + let combine_env ctx r fe f args fc es f_ask = if !AnalysisState.postsolving then - let c_r: S.C.t = ctx.context () in (*Caller context*) (*TODO is this the caller or callee context???*) + let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else From 7f4866caca9b982d5e3036bf685c36c0723bab8a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 10:34:59 +0200 Subject: [PATCH 092/628] comments, transformed loop_counters to a map to store stmts --- src/analyses/termination_new.ml | 6 +- src/framework/constraints.ml | 269 --------------------------- src/util/terminationPreprocessing.ml | 54 +----- 3 files changed, 10 insertions(+), 319 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 44b0c7fb5e..4926c23daa 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,9 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_counters : varinfo list ref = ref [] + +(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) +let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] @@ -14,7 +16,7 @@ let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loop_counters + VarToStmt.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = x = !loop_exit diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..07750122a5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,275 +1693,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (* - - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = (*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - module G = S.G - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = - if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end -*) module CompareGlobSys (SpecSys: SpecSys) = struct diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..7e1e477262 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,13 +1,8 @@ -(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - - check if overflow happend with new variable - - how do we deal with nested loops? - - make sure only the analyzed files are appended with the code - - return variables that are newly created - *) - open GoblintCil include Printf +module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -43,7 +38,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - lc := List.append !lc ([v] : varinfo list); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s @@ -56,42 +52,4 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) s | _ -> s in ChangeDoChildrenPost (s, action); - end - -(* just a test -class loopCounterVisitor (fd : fundec) = object(self) -inherit nopCilVisitor -method! vstmt s = - match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) - ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) - | _ -> DoChildren -end - -let add_var_loopTerm fd f = - let thisVisitor = new loopCounterVisitor in - visitCilFileSameGlobals (thisVisitor fd ) f*) -(* -let action (fd : fundec) s = - let a s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) - s.skind <- Block nb; - s - | _ -> s -in ChangeDoChildrenPost (s, a) -*) - + end \ No newline at end of file From 99e0a068696f9696b030c67dbcbdae4b20ce0872 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:16:02 +0200 Subject: [PATCH 093/628] small changes --- runningGob.sh | 1 + src/framework/analyses.ml | 3 +-- src/framework/constraints.ml | 3 +++ tests/regression/55-loop-unrolling/01-simple-cases.c | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 15007b3e0b..783ad90fec 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,6 +1,7 @@ #!/bin/bash make make install +clear # set options and file for apron execution options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 890b5c12e8..b70f2c09cd 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -146,8 +146,7 @@ struct let relift (a,b) = (a,b) (*Todo: is this correct?*) let printXml f (a,b) = BatPrintf.fprintf f "\n - Tuple:\n - \n + Tuple:\n caller_fundec\n%a\n\n caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index c6060f8725..8e4eac1bca 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1740,6 +1740,7 @@ struct (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = if LS.mem call path_visited_calls then + (*Cycle found*) let msgs = [ (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); @@ -1748,6 +1749,7 @@ struct M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; S.query (conv ctx) q else if not (LH.mem global_visited_calls call) then begin + printf "test\n"; LH.replace global_visited_calls call (); let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) let new_path_visited_calls = LS.add call path_visited_calls in @@ -1785,6 +1787,7 @@ struct let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in + side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 0073717187..6790add384 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -31,6 +31,8 @@ void example1(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN + + example2(); } // Do-while loop simple example @@ -46,6 +48,7 @@ void example2(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN + example1(); } // Initialization not completed, yet the array representation is not precise From c66a3fb57a499b31e04ee65dd6224cc4455ae038 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:20:57 +0200 Subject: [PATCH 094/628] comments --- src/util/terminationPreprocessing.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 7e1e477262..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -30,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -39,7 +39,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s From 6e37746024b526fb1835c689681dc50756c9f32f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 17 Jun 2023 12:24:55 +0200 Subject: [PATCH 095/628] Change loop analysis domain keys to statements Before, the keys of the domain were simply the (loop counter) variables. Now, the keys are the CIL statements which are the analyzed loop. --- output.txt | 62 ++++++++++++++++----------------- src/analyses/termination_new.ml | 27 +++++++------- src/domains/queries.ml | 8 ++--- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..d751966836 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { +union __anonunion___atomic_wide_counter_1044835921 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { +struct __anonstruct___once_flag_1044835922 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; +typedef struct __anonstruct___once_flag_1044835922 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1683,40 +1683,42 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 249 +#line 246 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 +#line 263 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 +#line 271 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 272 +#line 281 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 +#line 285 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 +#line 288 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , + struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , + struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 323 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 326 +#line 338 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 +#line 343 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 +#line 348 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 +#line 352 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 +#line 357 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 +#line 376 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 +#line 383 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1827,9 +1829,8 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; +#line 773 +extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1994,8 +1995,7 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; + void const *__pointer ) __attribute__((__nothrow__)) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4926c23daa..e722b9a2b2 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,13 +6,13 @@ open TerminationPreprocessing exception PreProcessing of string - -(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) -let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty +(** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) +let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] +(** Indicates the place in the code, right after a loop is exited. *) let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = @@ -25,10 +25,10 @@ let is_loop_exit_indicator (x : varinfo) = * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents + List.for_all (function l -> l >= loc) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumping_gotos.contents) <= 0 + List.length upjumping_gotos.contents = 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -45,6 +45,7 @@ struct include Analyses.StdV end +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) module Spec : Analyses.MCPSpec = struct @@ -54,7 +55,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) module C = D module V = FunContextV (* TODO *) @@ -69,12 +70,14 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - D.add x false ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in - D.add x is_bounded ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) is_bounded ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -82,16 +85,16 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos and recursion *) + (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v -> - (match D.find_opt v ctx.local with + | Queries.MustTermLoop loop_statement -> + (match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b | None -> Result.top q) | Queries.MustTermProg -> - D.for_all (fun loop term_info -> term_info) ctx.local + D.for_all (fun _ term_info -> term_info) ctx.local | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 022e8e1dee..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -117,7 +117,7 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t - | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t type 'a result = 'a @@ -347,7 +347,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 - | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop s1), Any (MustTermLoop s2) -> CilType.Stmt.compare s1 s2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -386,7 +386,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v - | Any (MustTermLoop v) -> CilType.Varinfo.hash v + | Any (MustTermLoop s) -> CilType.Stmt.hash s | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -454,7 +454,7 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf - | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" end From 5efd011ae3dbd97fb88727c89fead835d33502d5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 11:11:31 +0200 Subject: [PATCH 096/628] cycle detection should work --- src/framework/analyses.ml | 8 +-- src/framework/constraints.ml | 98 +++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index b70f2c09cd..c6994fff23 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -135,11 +135,11 @@ end module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * Base2.t) + type t = (Base1.t * Base2.t) let fundec (a,_) = a let context (_,b) = b - let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" let to_yojson x = `String (show x) @@ -159,6 +159,7 @@ struct - b1 < b2: -3 *) let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) + if equal (a1, b1) (a2, b2) then 0 else( let res = ref 0 in let comp_a = Base1.compare a1 a2 in let comp_b = Base2.compare b1 b2 in @@ -166,7 +167,7 @@ struct else if (comp_a < 0) then res := !(res) - 1; if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; - !res + !res) let pretty () x = text (show x) @@ -194,6 +195,7 @@ struct struct include MapDomain.MapBot (C_ (C)) (CSet) let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) + end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 8e4eac1bca..7d46744c90 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1712,7 +1712,7 @@ struct include GVarF(S.V) end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1723,43 +1723,73 @@ struct sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } + let cycleDetection ctx v v' = + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + (* TODO: find all cycles/SCCs *) + let global_visited_calls = LH.create 100 in + + (* DFS *) + let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = + let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) + + if LS.mem call path_visited_calls then ( + (*Cycle found*) + let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Recursion cycle" msgs) + else if not (LH.mem global_visited_calls call) then begin + try + LH.replace global_visited_calls call (); + let new_path_visited_calls = LS.add call path_visited_calls in + + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let gmap = Option.get (gmap_opt) in (*might be empty*) + let callers: G.CSet.t = G.CMap.find (context_e) gmap in (*TODO: how do we get our Map out of g*) (*Todo: the context should be the domain of the map*) + G.CSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers; + with Invalid_argument _ -> () (* path ended: no cycle*) + end + in + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g' -> - S.query (conv ctx) (WarnGlobal (Obj.repr g')) - | `Right g' -> - let module LH = Hashtbl.Make (T (CilType.Fundec) (C)) in - let module LS = Set.Make (T (CilType.Fundec) (C)) in - (* TODO: find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in - - (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = - if LS.mem call path_visited_calls then - (*Cycle found*) + | WarnGlobal v -> + let v: V.t = Obj.obj v in + begin match v with + | `Left v' -> + S.query (conv ctx) (WarnGlobal (Obj.repr v')) + | `Right v' -> + (*Check if the loops terminated*) + match ctx.ask (MustTermProg) with + | false -> (*does not terminate*) let msgs = - [ - (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); - (Pretty.dprintf "lock after: with", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; - S.query (conv ctx) q - else if not (LH.mem global_visited_calls call) then begin - printf "test\n"; - LH.replace global_visited_calls call (); - let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) - let new_path_visited_calls = LS.add call path_visited_calls in - G.CSet.iter (fun to_call -> - iter_call new_path_visited_calls to_call - ) callers - end - in - S.query (conv ctx) q - end + [ + (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Non terminating loops" msgs + | true -> cycleDetection ctx v v' + end + | InvariantGlobal v -> + let v: V.t = Obj.obj v in + begin match v with + | `Left v -> + S.query (conv ctx) (InvariantGlobal (Obj.repr v)) + | `Right v -> + Queries.Result.top q + end | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From 8563cc7e438d1811c9ca151287ebc53d940cfcbb Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 12:39:01 +0200 Subject: [PATCH 097/628] Consider upjumping gotos in whole program query and a bit of change towards using a global invariant --- src/analyses/termination_new.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..d610a89fe9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -21,12 +21,6 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loop_exit -(** Checks whether at the current location (=loc) of the analysis an - * upjumping goto was already reached. Returns true if no upjumping goto was - * reached until now *) -let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function l -> l >= loc) upjumping_gotos.contents - let no_upjumping_gotos () = List.length upjumping_gotos.contents = 0 @@ -39,14 +33,18 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module FunContextV : Analyses.SpecSysVar = +module UnitV : SpecSysVar = struct - include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) - include Analyses.StdV + include Printable.Unit + include StdV end +(** We want to record termination information of loops and use the loop + * statements for that. We use this lifting because we need to have a + * lattice. *) module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +(** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = struct @@ -55,15 +53,13 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) module C = D - module V = FunContextV - (* TODO *) + module V = UnitV + module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = D.bot () - let exitstate = startstate (* TODO *) - - let finalize () = () (* TODO *) + let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) @@ -85,7 +81,6 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with @@ -95,6 +90,7 @@ struct | None -> Result.top q) | Queries.MustTermProg -> D.for_all (fun _ term_info -> term_info) ctx.local + && no_upjumping_gotos () | _ -> Result.top q end From d786f98faad490c4957c8fd8d09e9870abdba14b Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 18:11:11 +0200 Subject: [PATCH 098/628] WIP on using find_loop_heads and global invariant --- src/analyses/termination_new.ml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d610a89fe9..5e56c74a05 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,17 @@ open TerminationPreprocessing exception PreProcessing of string +(* + * TODO: Make this work +module FileCfg = +struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) +end + +let loop_heads = WitnessUtil.find_loop_heads FileCfg + *) + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -67,6 +78,10 @@ struct (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in + (* + * TODO: Make the below line work + let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in + *) D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) From bf44af74d3d864d7dfeb477545aa2f7f4b7b1ffd Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 21:07:06 +0200 Subject: [PATCH 099/628] resolved merge conflict, cycle detection is working, BUT loop results are not correct yet --- src/analyses/termination_new.ml | 10 +++++--- src/framework/analyses.ml | 35 +++++++++++++++------------- src/framework/constraints.ml | 27 +++++++++++---------- src/util/terminationPreprocessing.ml | 9 ++++++- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..fabd341a23 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -90,11 +90,15 @@ struct let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + if no_upjumping_gotos () + then ((match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b - | None -> Result.top q) + | None -> Result.top q)) + else(Result.top q) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + if no_upjumping_gotos () + then (D.for_all (fun _ term_info -> term_info) ctx.local) + else (Result.top q) | _ -> Result.top q end diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c6994fff23..763ffd0e56 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,17 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -(* Make the given module Goupable*) -module C_ (C: Printable.S)= -struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) - " - callee_context:\n%a\n\n - " printXml c (* wrap in for HTML printing *) - -end (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) @@ -146,7 +135,7 @@ struct let relift (a,b) = (a,b) (*Todo: is this correct?*) let printXml f (a,b) = BatPrintf.fprintf f "\n - Tuple:\n + Tuple:\n\n caller_fundec\n%a\n\n caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b @@ -176,6 +165,7 @@ struct end module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = + struct module CSet = struct @@ -186,16 +176,29 @@ struct ) let name () = "contexts" let printXml f a = - BatPrintf.fprintf f "\n\n"; + BatPrintf.fprintf f "\n"; iter (Base.printXml f) a; BatPrintf.fprintf f "\n\n" end + (* Make the given module Goupable*) + module C_Printable (C: Printable.S)= + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + "\n + callee_context\n%a\n\n + " printXml c (* wrap in for HTML printing *) + end + module CMap = struct - include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) - + include MapDomain.MapBot (C_Printable (C)) (CSet) + let printXml f c = BatPrintf.fprintf f " + ContextTupleMap\n + %a\n\n + " printXml c (*TODO*) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 7d46744c90..5be58cd27b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1753,6 +1753,7 @@ struct iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) + end in let gmap_opt = G.base2 (ctx.global (v)) in @@ -1760,9 +1761,19 @@ struct (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) G.CMap.iter(fun key value -> let call = (v', key) in - iter_call LS.empty call + iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) + let checkTerminating ctx v v' = + (*Check if the loops terminated*) + if ctx.ask Queries.MustTermProg + then (cycleDetection ctx v v') + else(let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Possibly non terminating loops" msgs) + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1771,17 +1782,8 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> - (*Check if the loops terminated*) - match ctx.ask (MustTermProg) with - | false -> (*does not terminate*) - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning "Non terminating loops" msgs - | true -> cycleDetection ctx v v' - end + | `Right v' -> checkTerminating ctx v v' + end | InvariantGlobal v -> let v: V.t = Obj.obj v in begin match v with @@ -1790,6 +1792,7 @@ struct | `Right v -> Queries.Result.top q end + | MustTermProgWithRec -> false (*TODO*) | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index a64e48446b..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,6 +18,13 @@ let show_location_id l = class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor + method! vfunc (f:fundec) = + if !le.vname <> "term_exit-" then begin + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeGlobalVar exit_name typ; + end; + DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -26,7 +33,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [(Lval(var v))], loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) From 03dbf0bdf92761f2e1680d90b8156a727856a02a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 21:09:33 +0200 Subject: [PATCH 100/628] added queries --- src/domains/queries.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index c5d7d729b6..6603175f36 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,6 +119,7 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t + | MustTermProgWithRec: MustBool.t t type 'a result = 'a @@ -185,6 +186,7 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) + | MustTermProgWithRec -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -250,6 +252,7 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () + | MustTermProgWithRec -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -312,6 +315,7 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 + | Any MustTermProgWithRec -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -456,6 +460,7 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any MustTermProgWithRec -> Pretty.dprintf "MustTermProgWithRec" end let to_value_domain_ask (ask: ask) = From 5457fc36b887c5bd8196e3b2a544150b4b9916d4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 19 Jun 2023 13:04:28 +0200 Subject: [PATCH 101/628] Use global invariant instead of local state Still needs a bit of work. Currently, loops are only ever analyzed if their loop exit indicator is encountered. --- src/analyses/termination_new.ml | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 5e56c74a05..f062030820 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,16 +6,14 @@ open TerminationPreprocessing exception PreProcessing of string -(* - * TODO: Make this work -module FileCfg = -struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) -end - -let loop_heads = WitnessUtil.find_loop_heads FileCfg - *) +let loop_heads = + let module FileCfg = + struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) + end in + let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in + WitnessInvariant.loop_heads (* TODO: Use this *) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -44,7 +42,7 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV : SpecSysVar = +module UnitV = struct include Printable.Unit include StdV @@ -64,7 +62,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) + module D = Lattice.Unit module C = D module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) @@ -75,20 +73,21 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with + (* (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in - (* - * TODO: Make the below line work - let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in - *) + let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in + let () = print_endline ("Added FALSE for " ^ x.vname) in D.add (`Lifted loop_statement) false ctx.local - | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + *) + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - D.add (`Lifted loop_statement) is_bounded ctx.local + let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -97,16 +96,15 @@ struct (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b - | None -> Result.top q) + | None -> false) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () - | _ -> Result.top q + | _ -> Queries.Result.top q end From 13e8b7a2379ae12ce8b755287d1403f9fa71fff7 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 10:34:59 +0200 Subject: [PATCH 102/628] comments, transformed loop_counters to a map to store stmts --- src/analyses/termination_new.ml | 6 +- src/framework/constraints.ml | 269 --------------------------- src/util/terminationPreprocessing.ml | 54 +----- 3 files changed, 10 insertions(+), 319 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 44b0c7fb5e..4926c23daa 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,9 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_counters : varinfo list ref = ref [] + +(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) +let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] @@ -14,7 +16,7 @@ let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loop_counters + VarToStmt.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = x = !loop_exit diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..07750122a5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,275 +1693,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (* - - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = (*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - module G = S.G - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = - if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end -*) module CompareGlobSys (SpecSys: SpecSys) = struct diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..7e1e477262 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,13 +1,8 @@ -(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - - check if overflow happend with new variable - - how do we deal with nested loops? - - make sure only the analyzed files are appended with the code - - return variables that are newly created - *) - open GoblintCil include Printf +module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -43,7 +38,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - lc := List.append !lc ([v] : varinfo list); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s @@ -56,42 +52,4 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) s | _ -> s in ChangeDoChildrenPost (s, action); - end - -(* just a test -class loopCounterVisitor (fd : fundec) = object(self) -inherit nopCilVisitor -method! vstmt s = - match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) - ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) - | _ -> DoChildren -end - -let add_var_loopTerm fd f = - let thisVisitor = new loopCounterVisitor in - visitCilFileSameGlobals (thisVisitor fd ) f*) -(* -let action (fd : fundec) s = - let a s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) - s.skind <- Block nb; - s - | _ -> s -in ChangeDoChildrenPost (s, a) -*) - + end \ No newline at end of file From 1d8fb5019387bf283a74addac82b42d8e608fb7b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:20:57 +0200 Subject: [PATCH 103/628] comments --- src/util/terminationPreprocessing.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 7e1e477262..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -30,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -39,7 +39,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s From e36eefb052b593e95018275ceaa0fd5a85fa7cfe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 17 Jun 2023 12:24:55 +0200 Subject: [PATCH 104/628] Change loop analysis domain keys to statements Before, the keys of the domain were simply the (loop counter) variables. Now, the keys are the CIL statements which are the analyzed loop. --- output.txt | 62 ++++++++++++++++----------------- src/analyses/termination_new.ml | 27 +++++++------- src/domains/queries.ml | 8 ++--- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..d751966836 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { +union __anonunion___atomic_wide_counter_1044835921 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { +struct __anonstruct___once_flag_1044835922 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; +typedef struct __anonstruct___once_flag_1044835922 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1683,40 +1683,42 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 249 +#line 246 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 +#line 263 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 +#line 271 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 272 +#line 281 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 +#line 285 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 +#line 288 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , + struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , + struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 323 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 326 +#line 338 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 +#line 343 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 +#line 348 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 +#line 352 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 +#line 357 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 +#line 376 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 +#line 383 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1827,9 +1829,8 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; +#line 773 +extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1994,8 +1995,7 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; + void const *__pointer ) __attribute__((__nothrow__)) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4926c23daa..e722b9a2b2 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,13 +6,13 @@ open TerminationPreprocessing exception PreProcessing of string - -(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) -let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty +(** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) +let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] +(** Indicates the place in the code, right after a loop is exited. *) let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = @@ -25,10 +25,10 @@ let is_loop_exit_indicator (x : varinfo) = * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents + List.for_all (function l -> l >= loc) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumping_gotos.contents) <= 0 + List.length upjumping_gotos.contents = 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -45,6 +45,7 @@ struct include Analyses.StdV end +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) module Spec : Analyses.MCPSpec = struct @@ -54,7 +55,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) module C = D module V = FunContextV (* TODO *) @@ -69,12 +70,14 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - D.add x false ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in - D.add x is_bounded ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) is_bounded ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -82,16 +85,16 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos and recursion *) + (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v -> - (match D.find_opt v ctx.local with + | Queries.MustTermLoop loop_statement -> + (match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b | None -> Result.top q) | Queries.MustTermProg -> - D.for_all (fun loop term_info -> term_info) ctx.local + D.for_all (fun _ term_info -> term_info) ctx.local | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 022e8e1dee..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -117,7 +117,7 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t - | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t type 'a result = 'a @@ -347,7 +347,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 - | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop s1), Any (MustTermLoop s2) -> CilType.Stmt.compare s1 s2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -386,7 +386,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v - | Any (MustTermLoop v) -> CilType.Varinfo.hash v + | Any (MustTermLoop s) -> CilType.Stmt.hash s | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -454,7 +454,7 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf - | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" end From 234ae2a6516cddb68f124a97b5ec7ccb43efd3db Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 16 Jun 2023 14:55:01 +0300 Subject: [PATCH 105/628] Fix typo and dead link in taint analysis tutorial --- src/analyses/tutorials/taint.ml | 2 +- tests/regression/99-tutorials/03-taint_simple.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/tutorials/taint.ml b/src/analyses/tutorials/taint.ml index 217125c8bd..3067449e31 100644 --- a/src/analyses/tutorials/taint.ml +++ b/src/analyses/tutorials/taint.ml @@ -1,8 +1,8 @@ (** Simple interprocedural taint analysis template ([taint]). *) (** An analysis specification for didactic purposes. *) -(* Helpful link on CIL: https://goblint.in.tum.de/assets/goblint-cil/ *) (* Goblint documentation: https://goblint.readthedocs.io/en/latest/ *) +(* Helpful link on CIL: https://goblint.github.io/cil/ *) (* You may test your analysis on our toy examples by running `ruby scripts/update_suite.rb group tutorials` *) (* after removing the `SKIP` from the beginning of the tests in tests/regression/99-tutorials/{03-taint_simple.c,04-taint_inter.c} *) diff --git a/tests/regression/99-tutorials/03-taint_simple.c b/tests/regression/99-tutorials/03-taint_simple.c index d9d00351c1..4cc206d949 100644 --- a/tests/regression/99-tutorials/03-taint_simple.c +++ b/tests/regression/99-tutorials/03-taint_simple.c @@ -31,7 +31,7 @@ int main(void) { // Trivial example showing how the analysis you just wrote benefits from other analyses - // If we wanted to write a real analysis, we would also aks other analyses questions, to e.g. handle pointers + // If we wanted to write a real analysis, we would also ask other analyses questions, to e.g. handle pointers int z; if(z == 0) { z = 5; From d0b9de95a9128a5e246de5492642422b61c69f9f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 12:39:01 +0200 Subject: [PATCH 106/628] Consider upjumping gotos in whole program query and a bit of change towards using a global invariant --- src/analyses/termination_new.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..d610a89fe9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -21,12 +21,6 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loop_exit -(** Checks whether at the current location (=loc) of the analysis an - * upjumping goto was already reached. Returns true if no upjumping goto was - * reached until now *) -let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function l -> l >= loc) upjumping_gotos.contents - let no_upjumping_gotos () = List.length upjumping_gotos.contents = 0 @@ -39,14 +33,18 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module FunContextV : Analyses.SpecSysVar = +module UnitV : SpecSysVar = struct - include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) - include Analyses.StdV + include Printable.Unit + include StdV end +(** We want to record termination information of loops and use the loop + * statements for that. We use this lifting because we need to have a + * lattice. *) module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +(** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = struct @@ -55,15 +53,13 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) module C = D - module V = FunContextV - (* TODO *) + module V = UnitV + module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = D.bot () - let exitstate = startstate (* TODO *) - - let finalize () = () (* TODO *) + let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) @@ -85,7 +81,6 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with @@ -95,6 +90,7 @@ struct | None -> Result.top q) | Queries.MustTermProg -> D.for_all (fun _ term_info -> term_info) ctx.local + && no_upjumping_gotos () | _ -> Result.top q end From 88432722ace33653378ae8989ff4903c71f563d4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 18:11:11 +0200 Subject: [PATCH 107/628] WIP on using find_loop_heads and global invariant --- src/analyses/termination_new.ml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d610a89fe9..5e56c74a05 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,17 @@ open TerminationPreprocessing exception PreProcessing of string +(* + * TODO: Make this work +module FileCfg = +struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) +end + +let loop_heads = WitnessUtil.find_loop_heads FileCfg + *) + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -67,6 +78,10 @@ struct (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in + (* + * TODO: Make the below line work + let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in + *) D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) From 49dcae5dfa79f11d03bb36748b6ebabf854254d9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 19 Jun 2023 13:04:28 +0200 Subject: [PATCH 108/628] Use global invariant instead of local state Still needs a bit of work. Currently, loops are only ever analyzed if their loop exit indicator is encountered. --- src/analyses/termination_new.ml | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 5e56c74a05..f062030820 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,16 +6,14 @@ open TerminationPreprocessing exception PreProcessing of string -(* - * TODO: Make this work -module FileCfg = -struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) -end - -let loop_heads = WitnessUtil.find_loop_heads FileCfg - *) +let loop_heads = + let module FileCfg = + struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) + end in + let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in + WitnessInvariant.loop_heads (* TODO: Use this *) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -44,7 +42,7 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV : SpecSysVar = +module UnitV = struct include Printable.Unit include StdV @@ -64,7 +62,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) + module D = Lattice.Unit module C = D module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) @@ -75,20 +73,21 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with + (* (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in - (* - * TODO: Make the below line work - let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in - *) + let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in + let () = print_endline ("Added FALSE for " ^ x.vname) in D.add (`Lifted loop_statement) false ctx.local - | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + *) + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - D.add (`Lifted loop_statement) is_bounded ctx.local + let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -97,16 +96,15 @@ struct (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b - | None -> Result.top q) + | None -> false) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () - | _ -> Result.top q + | _ -> Queries.Result.top q end From 8fc0c1beff17b61b57e4b26173a4eea49679b01d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 109/628] first tests for recursion termination analysis, added empty functor and GMapG --- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..7fd57b357e 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + module GMapG (G: Lattice.S) (C: Printable.S) = struct From 0efdc788435e4404e1f5883b6fc3f80fb8aebe1f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 110/628] Tests for loop termination --- .../80-termination/15-complex-loop-combination-terminating.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e5383aed66..54f8cd97c8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -130,7 +130,7 @@ int main() } } - // Loop with a label and goto statement + /* // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } + } */ return 0; } From 8e9d29e4e8cd34531ad0f3a01b1d8ce5a054ae00 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 111/628] Loop termination tests extended --- .../80-termination/09-complex-for-loop-terminating.c | 2 +- .../regression/80-termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } From 8a47aa678be4ce6d66c0aa159b0878b5b6b77fef Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 13:34:23 +0200 Subject: [PATCH 112/628] Goto test cases --- .../24-upjumping-goto-loopless-terminating.c | 18 +++++++++++++ .../25-leave-loop-goto-terminating.c | 24 +++++++++++++++++ .../26-enter-loop-goto-terminating.c | 27 +++++++++++++++++++ .../27-upjumping-goto-nonterminating.c | 19 +++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c create mode 100644 tests/regression/80-termination/25-leave-loop-goto-terminating.c create mode 100644 tests/regression/80-termination/26-enter-loop-goto-terminating.c create mode 100644 tests/regression/80-termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c new file mode 100644 index 0000000000..aea0d5dd97 --- /dev/null +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -0,0 +1,18 @@ +#include + +int main() { + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark1; + +mark3: + printf("This is mark3\n"); + + return 0; +} diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c new file mode 100644 index 0000000000..34c14eedd6 --- /dev/null +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -0,0 +1,24 @@ +#include + +int main() { + int counter = 0; + + while (1) { + counter++; + + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + printf("Result: %d\n", result); + + // Condition to terminate the loop + if (result >= 10) { + goto end; + } + } + +end: + printf("Loop exited. Result is greater than or equal to 10.\n"); + + return 0; +} diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c new file mode 100644 index 0000000000..d3158ae7f7 --- /dev/null +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -0,0 +1,27 @@ +#include + +int main() { + int counter = 0; + + goto jump_point; + + while (1) { + counter++; + + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + jump_point: + printf("Result: %d\n", result); + + // Condition to terminate the loop + if (result >= 10) { + goto end; + } + } + +end: + printf("Loop exited. Result is greater than or equal to 10.\n"); + + return 0; +} diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c new file mode 100644 index 0000000000..b6dc238fe3 --- /dev/null +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -0,0 +1,19 @@ +#include + +int main() { + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark1; + +mark3: + printf("This is mark3\n"); + goto mark1; + + return 0; +} From bb5ab19e5f1417aae2739ef85ca36c1c54890a84 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 13:40:37 +0200 Subject: [PATCH 113/628] Added recursion tests --- .../81-recursion/01-simple-terminating.c | 21 +++++++++++ .../81-recursion/02-simple-nonterminating.c | 21 +++++++++++ .../81-recursion/03-nested-terminating.c | 35 +++++++++++++++++++ .../81-recursion/04-nested-nonterminating.c | 25 +++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 tests/regression/81-recursion/01-simple-terminating.c create mode 100644 tests/regression/81-recursion/02-simple-nonterminating.c create mode 100644 tests/regression/81-recursion/03-nested-terminating.c create mode 100644 tests/regression/81-recursion/04-nested-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c new file mode 100644 index 0000000000..9e509ebaa9 --- /dev/null +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -0,0 +1,21 @@ +#include + +void recursiveFunction(int n) { + // Base case: When n reaches 0, stop recursion + if (n == 0) { + printf("Terminating recursion\n"); + return; + } + + printf("Recursive call with n = %d\n", n); + + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); +} + +int main() { + // Call the recursive function with an initial value + recursiveFunction(5); + + return 0; +} diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c new file mode 100644 index 0000000000..ec9d31ffcb --- /dev/null +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -0,0 +1,21 @@ +#include + +void recursiveFunction(int n) { + // Base case: When n reaches 0, stop recursion + if (n == 30) { + printf("Terminating recursion\n"); + return; + } + + printf("Recursive call with n = %d\n", n); + + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); +} + +int main() { + // Call the recursive function with an initial value + recursiveFunction(5); + + return 0; +} diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c new file mode 100644 index 0000000000..6cd28043ee --- /dev/null +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -0,0 +1,35 @@ +#include + +void innerRecursiveFunction(int n) { + if (n == 0) { + printf("Terminating inner recursion\n"); + return; + } + + printf("Inner recursive call with n = %d\n", n); + + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(n - 1); +} + +void outerRecursiveFunction(int n) { + if (n == 0) { + printf("Terminating outer recursion\n"); + return; + } + + printf("Outer recursive call with n = %d\n", n); + + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(n - 1); + + // Call to the innerRecursiveFunction + innerRecursiveFunction(n); +} + +int main() { + // Call the outerRecursiveFunction with an initial value + outerRecursiveFunction(3); + + return 0; +} diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c new file mode 100644 index 0000000000..96911687da --- /dev/null +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -0,0 +1,25 @@ +#include + +void innerRecursiveFunction() { + printf("Nested recursive call\n"); + + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(); +} + +void outerRecursiveFunction() { + printf("Outer recursive call\n"); + + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(); + + // Call to the innerRecursiveFunction + innerRecursiveFunction(); +} + +int main() { + // Call the outerRecursiveFunction + outerRecursiveFunction(); + + return 0; +} From c2e08ef4724659bb05baeefdc3f18d9fe0d968b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:16:33 +0200 Subject: [PATCH 114/628] 80/23 fixed --- .../80-termination/23-exit-on-rand-terminating.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index f793275b1f..c8118a4bde 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,16 +1,18 @@ // PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include int main() { - int shortrun, i = 0; + int short_run, i = 0; - while (i < 90 || shortrun == 1) + while (i < 90 && short_run != 1) { i++; if (rand()) { - shortrun = 1; + short_run = 1; } + printf("%i %i\n", i, short_run); } } \ No newline at end of file From 4ec1e9862fddea279e4a23a328bf9481ef1c4552 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:16:58 +0200 Subject: [PATCH 115/628] removed print --- tests/regression/80-termination/23-exit-on-rand-terminating.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index c8118a4bde..228fc3b15e 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -13,6 +13,5 @@ int main() { short_run = 1; } - printf("%i %i\n", i, short_run); } } \ No newline at end of file From 9bba9a1061b6ec1504b247cf26d866d91f5dfc8f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:24:56 +0200 Subject: [PATCH 116/628] Param unified --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- .../80-termination/24-upjumping-goto-loopless-terminating.c | 1 + .../regression/80-termination/25-leave-loop-goto-terminating.c | 1 + .../regression/80-termination/26-enter-loop-goto-terminating.c | 1 + .../80-termination/27-upjumping-goto-nonterminating.c | 1 + tests/regression/81-recursion/01-simple-terminating.c | 1 + tests/regression/81-recursion/02-simple-nonterminating.c | 1 + tests/regression/81-recursion/03-nested-terminating.c | 1 + tests/regression/81-recursion/04-nested-nonterminating.c | 1 + 11 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 508b31500c..ed28fa9b43 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9d5cd4b928..3a19f17bee 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 1ea228ae55..e5383aed66 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index aea0d5dd97..f4b6b8fbe2 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index 34c14eedd6..c30e65f44b 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index d3158ae7f7..5d34e5c523 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index b6dc238fe3..6e4432dc5e 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c index 9e509ebaa9..1c52faec68 100644 --- a/tests/regression/81-recursion/01-simple-terminating.c +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index ec9d31ffcb..a6d6b3ab17 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c index 6cd28043ee..096a1b0121 100644 --- a/tests/regression/81-recursion/03-nested-terminating.c +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c index 96911687da..ab5e35d80f 100644 --- a/tests/regression/81-recursion/04-nested-nonterminating.c +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 0c41ac6ef089ac5c486687a29bb1eb6a3b42cc4e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 16:12:48 +0200 Subject: [PATCH 117/628] Fix from master --- src/framework/analyses.ml | 53 --------------------------------------- 1 file changed, 53 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 7fd57b357e..1d1972ac45 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,59 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - module GMapG (G: Lattice.S) (C: Printable.S) = struct From c2ababd0d10671e3c59ec46a361733b2d6ed6c89 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:08:34 +0200 Subject: [PATCH 118/628] added new massage category --- src/framework/constraints.ml | 4 ++-- src/util/options.schema.json | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1e2644e394..a46abccb49 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1739,7 +1739,7 @@ struct [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning "Recursion cycle" msgs) + M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); @@ -1773,7 +1773,7 @@ struct [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning "Possibly non terminating loops" msgs); + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); printf "true" diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 02fc929a8a..d49b30aca7 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -2078,6 +2078,12 @@ "type": "boolean", "default": true }, + "nonTerminating": { + "title": "warn.nonTerminating", + "description": "nonTerminating warning", + "type": "boolean", + "default": true + }, "unknown": { "title": "warn.unknown", "description": "Unknown (of string) warnings", From 49c3a75751564fb78ce5dda18fc792928b3ace45 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:44:21 +0200 Subject: [PATCH 119/628] deleted queries, comments and todos refreshed :), fixed indentation (hopefully) --- src/domains/queries.ml | 5 --- src/framework/analyses.ml | 76 ++++-------------------------------- src/framework/constraints.ml | 28 ++++++------- 3 files changed, 19 insertions(+), 90 deletions(-) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 6603175f36..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,7 +119,6 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t - | MustTermProgWithRec: MustBool.t t type 'a result = 'a @@ -186,7 +185,6 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) - | MustTermProgWithRec -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -252,7 +250,6 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () - | MustTermProgWithRec -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -315,7 +312,6 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 - | Any MustTermProgWithRec -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -460,7 +456,6 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" - | Any MustTermProgWithRec -> Pretty.dprintf "MustTermProgWithRec" end let to_value_domain_ask (ask: ask) = diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 763ffd0e56..e11903ba06 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -121,7 +121,7 @@ end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = struct include Printable.Std type t = (Base1.t * Base2.t) @@ -140,13 +140,6 @@ struct caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b - (*Result of compare: - start with inital value of 0 - - a1 > a2: +1 - - a1 < a2: -1 - - b1 > b2: +3 - - b1 < b2: -3 - *) let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) if equal (a1, b1) (a2, b2) then 0 else( let res = ref 0 in @@ -157,6 +150,7 @@ struct if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; !res) + let pretty () x = text (show x) @@ -164,7 +158,7 @@ struct end -module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = +module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = @@ -186,10 +180,10 @@ struct struct include C include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + let printXml f c = BatPrintf.fprintf f "\n callee_context\n%a\n\n - " printXml c (* wrap in for HTML printing *) + " printXml c end module CMap = @@ -198,7 +192,7 @@ struct let printXml f c = BatPrintf.fprintf f " ContextTupleMap\n %a\n\n - " printXml c (*TODO*) + " printXml c end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) @@ -219,12 +213,12 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let s = function (*TODO: does this work? copied from DeadBranch*) + let s = function | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" - let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + let create_s s = `Lifted1 s let base2 instance = match instance with @@ -232,60 +226,6 @@ struct | _ -> None end - -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a46abccb49..730f0f41eb 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1712,11 +1712,10 @@ struct include GVarF(S.V) end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (S.C)) + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - (*TODO Change the body??*) let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.spec v))); @@ -1726,7 +1725,7 @@ struct let cycleDetection ctx v v' = let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in let module LS = Set.Make (T (CilType.Fundec) (S.C)) in - (* TODO: find all cycles/SCCs *) + (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) @@ -1748,7 +1747,7 @@ struct let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in (*TODO: how do we get our Map out of g*) (*Todo: the context should be the domain of the map*) + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; @@ -1756,14 +1755,13 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) @@ -1773,11 +1771,8 @@ struct [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - printf "true" + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - - (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> @@ -1795,7 +1790,6 @@ struct | `Right v -> Queries.Result.top q end - | MustTermProgWithRec -> false (*TODO*) | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From 3c9da8d3f7952b67882c0191b022aafde52ef9b8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 19 Jun 2023 17:55:21 +0200 Subject: [PATCH 120/628] position of special function changed from after the loop to right after the loopHead --- src/util/terminationPreprocessing.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 409aa2c2c4..3453aa7110 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -33,13 +33,13 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | Goto (sref, l) -> From 400c8102b9da2c890058a7b47a81afdf9939870c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:57:35 +0200 Subject: [PATCH 121/628] indentation --- src/framework/analyses.ml | 9 ++------- src/framework/constraints.ml | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index e11903ba06..36b80567aa 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,7 +42,6 @@ struct let var_id = Node.show_id end - module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -119,7 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -149,17 +147,14 @@ struct else if (comp_a < 0) then res := !(res) - 1; if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; - !res) - + !res) let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) - + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = - struct module CSet = struct diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 730f0f41eb..9508aa28a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,9 +1711,8 @@ struct struct include GVarF(S.V) end - module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) - + let name () = "RecursionTerm (" ^ S.name () ^ ")" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = @@ -1727,11 +1726,9 @@ struct let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in - (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) - if LS.mem call path_visited_calls then ( (*Cycle found*) let msgs = @@ -1743,7 +1740,6 @@ struct try LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) @@ -1755,13 +1751,13 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) @@ -1814,10 +1810,8 @@ struct let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in - side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else @@ -1832,7 +1826,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 91d3c79acdd9d23834012cf59f093d0e4e3f4884 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 09:57:26 +0200 Subject: [PATCH 122/628] indentation --- src/framework/analyses.ml | 5 ++++- src/framework/constraints.ml | 34 ++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 36b80567aa..fd56c65c2b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,6 +42,7 @@ struct let var_id = Node.show_id end + module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -118,6 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -151,9 +153,10 @@ struct let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end + module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 9508aa28a2..2db480de86 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,6 +1711,7 @@ struct struct include GVarF(S.V) end + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1722,15 +1723,15 @@ struct } let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in + let global_visited_calls = LH.create 100 in (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - (*Cycle found*) + (*Cycle found*) let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); @@ -1739,11 +1740,11 @@ struct else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; @@ -1751,19 +1752,19 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) if ctx.ask Queries.MustTermProg then (cycleDetection ctx v v') - else(let msgs = + else (let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in @@ -1808,10 +1809,10 @@ struct let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) - let c_e: S.C.t = Option.get (fc) in (*Callee context*) + let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else @@ -1826,6 +1827,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From c3a96e4c94181a95da6641dc39191af7b6bed439 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 10:07:36 +0200 Subject: [PATCH 123/628] indentation --- src/framework/analyses.ml | 4 ---- src/framework/constraints.ml | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index fd56c65c2b..f3c76d554b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,7 +42,6 @@ struct let var_id = Node.show_id end - module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -119,7 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -152,11 +150,9 @@ struct !res) let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end - module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2db480de86..66b2c92614 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,7 +1711,7 @@ struct struct include GVarF(S.V) end - + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1727,10 +1727,12 @@ struct let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in + (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( + (*Cycle found*) let msgs = [ @@ -1827,7 +1829,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 7956342e1de1b117725db23c278840dcf39afecb Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 10:17:02 +0200 Subject: [PATCH 124/628] fixed indentation --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 3453aa7110..45794b56cc 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,7 +36,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 7191fabc0f4cfdb888b77ba3782100e65d7f3481 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 10:30:34 +0200 Subject: [PATCH 125/628] made the compare function more ocamalyy :) --- src/framework/analyses.ml | 17 +++++++---------- src/framework/constraints.ml | 10 ++++++---- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index f3c76d554b..5a38af3e15 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -139,15 +139,12 @@ struct \n" Base1.printXml a Base2.printXml b let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 else( - let res = ref 0 in - let comp_a = Base1.compare a1 a2 in - let comp_b = Base2.compare b1 b2 in - if (comp_a > 0) then res := !(res) + 1 - else if (comp_a < 0) then res := !(res) - 1; - if (comp_b > 0) then res := !(res) + 3 - else if (comp_b < 0) then res := !(res) - 3; - !res) + if equal (a1, b1) (a2, b2) then 0 + else( + let val_a a = if (a > 0) then 1 else -1 in + let val_b b = if (b > 0) then 3 else -3 in + val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) + ) let pretty () x = text (show x) let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) @@ -170,7 +167,7 @@ struct end (* Make the given module Goupable*) - module C_Printable (C: Printable.S)= + module C_Printable (C: Printable.S) = struct include C include Printable.Std (* To make it Groupable *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 66b2c92614..eff98c1a8f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1700,9 +1700,11 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C = -(*global invariant +(*global invariants: + - V -> G - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} + Therefore: + g -> {c' -> {(f, c)}} in case f, c --> g, c' *) struct @@ -1732,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - + (*Cycle found*) let msgs = [ @@ -1760,7 +1762,7 @@ struct let call = (v', key) in iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + with Invalid_argument _ -> () (* path ended: no cycle*) let checkTerminating ctx v v' = (*Check if the loops terminated*) From 2df57d36e07495029d865d6264aa93855705d8ad Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 11:47:20 +0200 Subject: [PATCH 126/628] fixed testcase --- runningGob.sh | 2 +- src/framework/constraints.ml | 14 +++++++------- .../regression/55-loop-unrolling/01-simple-cases.c | 3 --- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 783ad90fec..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -21,6 +21,6 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" ./goblint $cfile_loops $options_term --html # set up server to see visualizatino -python3 -m http.server --directory result 8081 +python3 -m http.server --directory result 8080 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index eff98c1a8f..53fe3e5772 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1766,13 +1766,13 @@ struct let checkTerminating ctx v v' = (*Check if the loops terminated*) - if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + if ctx.ask Queries.MustTermProg + then (cycleDetection ctx v v') + else (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 6790add384..0073717187 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -31,8 +31,6 @@ void example1(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN - - example2(); } // Do-while loop simple example @@ -48,7 +46,6 @@ void example2(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN - example1(); } // Initialization not completed, yet the array representation is not precise From 8ef89ec34bbe55781c37c7d966bc90abb76284e0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 12:42:04 +0200 Subject: [PATCH 127/628] small changes, changed concrete name and indentation --- src/framework/constraints.ml | 12 ++++++------ src/util/options.schema.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 53fe3e5772..48dab4e84c 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1767,12 +1767,12 @@ struct let checkTerminating ctx v v' = (*Check if the loops terminated*) if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + then (cycleDetection ctx v v') + else (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with diff --git a/src/util/options.schema.json b/src/util/options.schema.json index d49b30aca7..3efaef2e83 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -2080,7 +2080,7 @@ }, "nonTerminating": { "title": "warn.nonTerminating", - "description": "nonTerminating warning", + "description": "Non Termination warning", "type": "boolean", "default": true }, From 4ea84b275f2246fc82c9192be9c4e52013ad0ec6 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 15:27:27 +0200 Subject: [PATCH 128/628] test shouldn't fail --- output.txt | 2235 ------------------------------------------------- runningGob.sh | 2 +- 2 files changed, 1 insertion(+), 2236 deletions(-) diff --git a/output.txt b/output.txt index d751966836..e69de29bb2 100644 --- a/output.txt +++ b/output.txt @@ -1,2235 +0,0 @@ -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_1044835921 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -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 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_1044835922 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_1044835922 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 28 - a[i] = i; -#line 29 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 27 - term_exit- = term27_5-file_01-simple-cases; - } -#line 32 - __goblint_check(a[0] == 0); -#line 33 - __goblint_check(a[3] == 3); -#line 34 - return; -} -} -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term42_5-file_01-simple-cases ; - - { -#line 40 - i = 0; - { -#line 42 - term42_5-file_01-simple-cases = 0; - { -#line 42 - while (1) { - while_continue: /* CIL Label */ ; -#line 43 - a[i] = i; -#line 44 - i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 - if (! (i <= 5)) { -#line 42 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 42 - term_exit- = term42_5-file_01-simple-cases; - } -#line 47 - __goblint_check(a[0] == 0); -#line 48 - __goblint_check(a[3] == 3); -#line 49 - return; -} -} -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term57_5-file_01-simple-cases ; - - { -#line 55 - i = 0; - { -#line 57 - term57_5-file_01-simple-cases = 0; - { -#line 57 - while (1) { - while_continue: /* CIL Label */ ; -#line 57 - if (! (i < 5)) { -#line 57 - goto while_break; - } -#line 57 - term57_5-file_01-simple-cases ++; -#line 58 - a[i] = i; -#line 59 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 57 - term_exit- = term57_5-file_01-simple-cases; - } -#line 62 - __goblint_check(a[0] == 0); -#line 63 - __goblint_check(a[3] == 0); -#line 64 - __goblint_check(a[7] == 0); -#line 65 - return; -} -} -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term74_5-file_01-simple-cases ; - - { -#line 71 - i = 0; -#line 72 - first_iteration = 1; - { -#line 74 - term74_5-file_01-simple-cases = 0; - { -#line 74 - while (1) { - while_continue: /* CIL Label */ ; -#line 74 - if (! (i < 10)) { -#line 74 - goto while_break; - } -#line 74 - term74_5-file_01-simple-cases ++; -#line 75 - if (first_iteration == 1) { -#line 75 - __goblint_check(i == 0); - } else -#line 76 - if (i > 5) { -#line 76 - __goblint_check(i == 6); - } -#line 77 - first_iteration = 0; -#line 78 - a[i] = 0; -#line 79 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 74 - term_exit- = term74_5-file_01-simple-cases; - } -#line 82 - __goblint_check(a[0] == 0); -#line 83 - __goblint_check(first_iteration == 0); -#line 84 - return; -} -} -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term95_5-file_01-simple-cases ; - - { -#line 92 - i = 0; -#line 93 - top = 0; - { -#line 95 - term95_5-file_01-simple-cases = 0; - { -#line 95 - while (1) { - while_continue: /* CIL Label */ ; -#line 95 - if (! (i < 4)) { -#line 95 - goto while_break; - } -#line 95 - term95_5-file_01-simple-cases ++; -#line 96 - a[i] = 0; -#line 97 - top += i; -#line 98 - if (i == 2) { -#line 99 - __goblint_check(top == 3); - } else { -#line 102 - __goblint_check(top == 3); - } -#line 104 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 95 - term_exit- = term95_5-file_01-simple-cases; - } -#line 107 - __goblint_check(a[0] == 0); -#line 108 - __goblint_check(a[3] == 0); -#line 109 - __goblint_check(top == 6); -#line 110 - return; -} -} -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term119_5-file_01-simple-cases ; - - { -#line 116 - i = 0; -#line 117 - top = 0; - { -#line 119 - term119_5-file_01-simple-cases = 0; - { -#line 119 - while (1) { - while_continue: /* CIL Label */ ; -#line 119 - if (! (i < 3)) { -#line 119 - goto while_break; - } -#line 119 - term119_5-file_01-simple-cases ++; -#line 120 - a[i] = 0; -#line 121 - __goblint_check(a[0] == 0); -#line 122 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 119 - term_exit- = term119_5-file_01-simple-cases; - } -#line 125 - __goblint_check(a[0] == 0); -#line 126 - __goblint_check(a[3] == 0); -#line 127 - __goblint_check(top == 6); -#line 128 - return; -} -} -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 132 - if (i > 5) { -#line 133 - return (0); - } else { -#line 136 - return (1); - } -} -} -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term143_2-file_01-simple-cases ; - - { -#line 142 - i = 0; - { -#line 143 - term143_2-file_01-simple-cases = 0; - { -#line 143 - while (1) { - while_continue: /* CIL Label */ ; -#line 143 - tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 - if (! tmp) { -#line 143 - goto while_break; - } -#line 144 - a[i] = i; -#line 145 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 143 - term_exit- = term143_2-file_01-simple-cases; - } -#line 147 - __goblint_check(a[0] == 0); -#line 148 - __goblint_check(a[6] == 0); -#line 149 - return; -} -} -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; - - { -#line 155 - b[0] = 0; -#line 155 - b[1] = 0; -#line 155 - b[2] = 0; -#line 155 - b[3] = 0; -#line 155 - b[4] = 0; -#line 156 - i = 0; - { -#line 157 - term157_2-file_01-simple-cases = 0; - { -#line 157 - while (1) { - while_continue: /* CIL Label */ ; -#line 157 - if (! (i < 5)) { -#line 157 - goto while_break; - } -#line 157 - term157_2-file_01-simple-cases ++; -#line 158 - a[i] = i; -#line 159 - j = 0; - { -#line 160 - term160_9-file_01-simple-cases = 0; - { -#line 160 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 160 - if (! (j < 5)) { -#line 160 - goto while_break___0; - } -#line 160 - term160_9-file_01-simple-cases ++; -#line 161 - b[j] += a[i]; -#line 162 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 160 - term_exit- = term160_9-file_01-simple-cases; - } -#line 164 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 157 - term_exit- = term157_2-file_01-simple-cases; - } -#line 166 - return; -} -} -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term174_2-file_01-simple-cases ; - - { -#line 173 - i = 0; - { -#line 174 - term174_2-file_01-simple-cases = 0; - { -#line 174 - while (1) { - while_continue: /* CIL Label */ ; -#line 174 - if (! 1) { -#line 174 - goto while_break; - } -#line 174 - term174_2-file_01-simple-cases ++; -#line 175 - a[i] = i; -#line 176 - i ++; -#line 177 - if (i == 5) { -#line 177 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 174 - term_exit- = term174_2-file_01-simple-cases; - } -#line 179 - return; -} -} -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term187_2-file_01-simple-cases ; - - { -#line 186 - i = 0; - { -#line 187 - term187_2-file_01-simple-cases = 0; - { -#line 187 - while (1) { - while_continue: /* CIL Label */ ; -#line 187 - if (! (i < 5)) { -#line 187 - goto while_break; - } -#line 187 - term187_2-file_01-simple-cases ++; -#line 188 - if (i == 3) { -#line 189 - i ++; -#line 190 - goto while_continue; - } -#line 192 - a[i] = i; -#line 193 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 187 - term_exit- = term187_2-file_01-simple-cases; - } -#line 195 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 246 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 263 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 271 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 281 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 285 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , - struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , - struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 323 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 338 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 343 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 348 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 352 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 357 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 376 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 383 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 773 -extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__)) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 10 - term_exit- = term10_5-file_stdlib; - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 9 - term_exit- = term9_3-file_stdlib; - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } -#line 21 - term_exit- = term21_9-file_stdlib; - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } -#line 17 - term_exit- = term17_5-file_stdlib; - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } -#line 16 - term_exit- = term16_3-file_stdlib; - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 40 - term_exit- = term40_3-file_stdlib; - } -#line 47 - return ((void *)0); -} -} diff --git a/runningGob.sh b/runningGob.sh index fcb5417192..0e43ee45c5 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" From 2b75972e9f60087a5558d8b8794652e7084d77d1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 16:13:57 +0200 Subject: [PATCH 129/628] added weird test case --- .../55-loop-unrolling/01-simple-cases.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 0073717187..98e8e34ff0 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -3,6 +3,27 @@ int global; +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(); +g(x); +} + +/* int main(void) { example1(); @@ -16,7 +37,7 @@ int main(void) example9(); example10(); return 0; -} +}*/ // Simple example void example1(void) @@ -30,7 +51,8 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - __goblint_check(a[3] == 3); // UNKNOWN + lab:__goblint_check(a[3] == 3); // UNKNOWN + goto lab; } // Do-while loop simple example From c6f37b2cada18c5cc8d8ca70cf0c39ef6bfda201 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 16:20:19 +0200 Subject: [PATCH 130/628] added weird test case + merging --- runningGob.sh | 2 +- tests/regression/55-loop-unrolling/01-simple-cases.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 0e43ee45c5..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 98e8e34ff0..9bf8d98683 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -37,7 +37,7 @@ int main(void) example9(); example10(); return 0; -}*/ +} // Simple example void example1(void) @@ -216,3 +216,4 @@ void example10(void) } return 0; } +*/ \ No newline at end of file From 566ae50925db871301039150ec3c50e3b9e8d537 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 20 Jun 2023 22:08:05 +0200 Subject: [PATCH 131/628] Fix indentation --- src/framework/analyses.ml | 10 +++++----- src/framework/constraints.ml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..6f53fa098d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -159,18 +159,18 @@ struct | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "GVarG.spec" - let contexts = function + let contexts = function | `Bot -> CSet.bot () | `Lifted2 x -> x | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts - let printXml f = function + let printXml f = function | `Lifted1 x -> G.printXml f x | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x | x -> BatPrintf.fprintf f "%a" printXml x -*) + *) end exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 07750122a5..d66d95d229 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -563,7 +563,7 @@ struct let side_context sideg f c = if !AnalysisState.postsolving then sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c)) - + let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t) list ref = let r = ref [] in let spawns = ref [] in @@ -1127,7 +1127,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" @@ -1764,10 +1764,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 = From 6cf3d129291481c6f899b9b395353b1fa7a23be1 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 20 Jun 2023 22:28:49 +0200 Subject: [PATCH 132/628] Small changes Direct empty list comparison instead of checking length = 0. Make loop_heads a function with argument (). --- src/analyses/termination_new.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index f062030820..a3aa3aef92 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_heads = +let loop_heads () = let module FileCfg = struct let file = !Cilfacade.current_file @@ -31,7 +31,7 @@ let is_loop_exit_indicator (x : varinfo) = x = !loop_exit let no_upjumping_gotos () = - List.length upjumping_gotos.contents = 0 + upjumping_gotos.contents = [] (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = From cfaf4178e38eb1247cb25d974e52b3be6683ba49 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 22:53:50 +0200 Subject: [PATCH 133/628] added location to recursion Warning --- runningGob.sh | 2 +- src/framework/constraints.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 0e43ee45c5..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48dab4e84c..b998ab9629 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1738,7 +1738,7 @@ struct (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) else if not (LH.mem global_visited_calls call) then begin From a4991e0093f739aa1fc190d7cae40c1d93a1971d Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 05:51:55 +0200 Subject: [PATCH 134/628] Adapted update_suite.rb and tests to termination output --- scripts/update_suite.rb | 71 ++++++++++--------- .../01-simple-loop-terminating.c | 4 +- .../02-simple-loop-nonterminating.c | 4 +- .../03-nested-loop-terminating.c | 6 +- .../04-nested-loop-nonterminating.c | 6 +- .../80-termination/05-for-loop-terminating.c | 4 +- .../06-for-loop-nonterminating.c | 4 +- .../07-nested-for-loop-terminating.c | 6 +- .../08-nested-for-loop-nonterminating.c | 6 +- .../09-complex-for-loop-terminating.c | 24 +++---- .../10-complex-loop-terminating.c | 24 +++---- .../80-termination/11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 4 +- .../80-termination/13-do-while-terminating.c | 4 +- .../14-do-while-nonterminating.c | 4 +- .../15-complex-loop-combination-terminating.c | 34 ++++----- ...16-nested-loop-nontrivial-nonterminating.c | 6 +- .../80-termination/17-goto-terminating.c | 4 +- .../80-termination/18-goto-nonterminating.c | 4 +- .../80-termination/19-rand-terminating.c | 6 +- .../80-termination/20-rand-nonterminating.c | 6 +- .../21-no-exit-on-rand-unproofable.c | 3 +- .../22-exit-on-rand-unproofable.c | 3 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../81-recursion/01-simple-terminating.c | 2 +- .../81-recursion/02-simple-nonterminating.c | 2 +- .../81-recursion/03-nested-terminating.c | 2 +- .../81-recursion/04-nested-nonterminating.c | 2 +- 32 files changed, 133 insertions(+), 124 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index dead6cd8f1..69b3bae485 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -147,31 +147,30 @@ def collect_warnings @vars = $1 @evals = $2 end + if l =~ /\[NonTerminating\]/ then warnings[-2] = "non_local_term" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown", "term", "noterm"] - thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /^\[Terminating\]/ then "term" - when /^\[Nonterminating\]/ then "noterm" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" - end + ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown", "term", "noterm"] + thiswarn = case obj + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn @@ -189,17 +188,23 @@ def compare_warnings # full p.path is too long and p.name does not allow click to open in terminal if todo.include? idx then puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" end else - if todo.include? idx then @ignored += 1 else - puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}:#{idx.to_s.blue}" - puts tests_line[idx].rstrip.gray - ferr = idx if ferr.nil? or idx < ferr + if todo.include? idx then + @ignored += 1 + else + if idx < 0 # When non line specific keywords were used don't print a line + puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}" + else + puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}:#{idx.to_s.blue}" + puts tests_line[idx].rstrip.gray + ferr = idx if ferr.nil? or idx < ferr + end end end } case type - when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn" + when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn", "non_local_term" check.call warnings[idx] == type - when "nowarn" + when "nowarn", "local_term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -300,10 +305,6 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" - elsif obj =~ /NON?TERM/ then - tests[i] = "noterm" - elsif obj =~ /TERM/ then - tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" @@ -315,6 +316,12 @@ def parse_tests (lines) end end case lines[0] + when /NON_LOCAL_TERM/ + # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless + tests[-2] = "non_local_term" + when /LOCAL_TERM/ + # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless + tests[-2] = "local_term" when /NON?TERM/ tests[-1] = "noterm" when /TERM/ diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c index 931b125171..a517d0d608 100644 --- a/tests/regression/80-termination/01-simple-loop-terminating.c +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("%d\n", i); i++; diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index 520a4a82e0..bcb9909f80 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,9 +1,9 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - while (1) // NOTERM + while (1) { continue; } diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c index 172827af42..366cbaeea5 100644 --- a/tests/regression/80-termination/03-nested-loop-terminating.c +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -9,12 +9,12 @@ int main() // Outer while loop for rows while (i <= rows) - { // TERM + { int j = 1; // Inner while loop for columns while (j <= columns) - { // TERM + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index 37af9ed6fb..ee2aa4a8c4 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,15 +1,15 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount = 1; - while (outerCount <= 3) // NOTERM + while (outerCount <= 3) { int innerCount = 1; - while (1) // NOTERM + while (1) { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c index ab286a6dd4..2a16184f6d 100644 --- a/tests/regression/80-termination/05-for-loop-terminating.c +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i; - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("%d\n", i); } diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c index 466001e6e5..b8f30361d1 100644 --- a/tests/regression/80-termination/06-for-loop-nonterminating.c +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -1,8 +1,8 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - for (;;) { // NOTERM + for (;;) { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c index eec4dda908..def0787d39 100644 --- a/tests/regression/80-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -7,9 +7,9 @@ int main() int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) // TERM + for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) // TERM + for (int j = 1; j <= columns; j++) { printf("(%d, %d) ", i, j); } diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c index 3f7bcb4f07..0368120b13 100644 --- a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -1,13 +1,13 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) // NOTERM + for (innerCount = 1;; innerCount++) { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..ae68b11575 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -6,17 +6,17 @@ int main() int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) // TERM + for (i = 1; i <= 5; i++) { // Inner loop 1 - for (j = 1; j <= i; j++) // TERM + for (j = 1; j <= i; j++) { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) // TERM + for (k = i; k >= 1; k--) { printf("%d ", k); } @@ -24,9 +24,9 @@ int main() } // Additional loop - for (i = 5; i >= 1; i--) // TERM + for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) // TERM + for (j = i; j >= 1; j--) { printf("%d ", j); } @@ -34,7 +34,7 @@ int main() } // Loop with conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i % 2 == 0) { @@ -47,7 +47,7 @@ int main() } // Loop with nested conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("Number: %d - ", i); if (i < 5) @@ -65,7 +65,7 @@ int main() } // Loop with a break statement - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("%d ", i); if (i == 5) @@ -76,7 +76,7 @@ int main() printf("\n"); // Loop with a continue statement - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i % 2 == 0) { @@ -87,7 +87,7 @@ int main() printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i > 5 && i % 2 == 0) { @@ -98,7 +98,7 @@ int main() // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..eb79338078 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -8,10 +8,10 @@ int main() int k = 5; // Outer while loop - while (i <= 5) // TERM + while (i <= 5) { // Inner while loop 1 - while (j <= i) // TERM + while (j <= i) { printf("%d ", j); j++; @@ -20,7 +20,7 @@ int main() j = 1; // Inner while loop 2 - while (k >= 1) // TERM + while (k >= 1) { printf("%d ", k); k--; @@ -33,10 +33,10 @@ int main() // Additional while loop i = 5; - while (i >= 1) // TERM + while (i >= 1) { j = i; - while (j >= 1) // TERM + while (j >= 1) { printf("%d ", j); j--; @@ -47,7 +47,7 @@ int main() // Loop with conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i % 2 == 0) { @@ -62,7 +62,7 @@ int main() // Loop with nested conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("Number: %d - ", i); if (i < 5) @@ -82,7 +82,7 @@ int main() // Loop with a break statement i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("%d ", i); if (i == 5) @@ -95,7 +95,7 @@ int main() // Loop with a continue statement i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i % 2 == 0) { @@ -109,7 +109,7 @@ int main() // Loop with complex conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i > 5 && i % 2 == 0) { @@ -123,7 +123,7 @@ int main() int a = 1; int b = 2; int c = 3; - while (a <= 10) // TERM + while (a <= 10) { printf("%d %d %d\n", a, b, c); a++; diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c index 7aeed0145d..86a300f18e 100644 --- a/tests/regression/80-termination/11-loopless-termination.c +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c index cc3cc41edc..15032b7b4f 100644 --- a/tests/regression/80-termination/12-do-while-instant-terminating.c +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 0; - do // TERM + do { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c index 05fe270f04..2e04f3e393 100644 --- a/tests/regression/80-termination/13-do-while-terminating.c +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - do // TERM + do { printf("Inside the do-while loop\n"); i++; diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index 1c70d4fc76..5ed18175e9 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - do // NOTERM + do { printf("Inside the do-while loop\n"); i++; diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e5383aed66..f3a08f4139 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -7,14 +7,14 @@ int main() int i; // for loop - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) // TERM + while (j <= 10) { printf("While loop iteration: %d\n", j); j++; @@ -22,7 +22,7 @@ int main() // do-while loop int k = 1; - do // TERM + do { printf("Do-While loop iteration: %d\n", k); k++; @@ -32,10 +32,10 @@ int main() int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) // TERM + for (a = 1; a <= 5; a++) { int c = 1; - while (c <= a) // TERM + while (c <= a) { printf("Nested For-While loop: %d\n", c); c++; @@ -44,10 +44,10 @@ int main() // Nested while and do-while loop int x = 1; - while (x <= 5) // TERM + while (x <= 5) { int y = 1; - do // TERM + do { printf("Nested While-Do-While loop: %d\n", y); y++; @@ -57,9 +57,9 @@ int main() // Nested do-while and for loop int p = 1; - do // TERM + do { - for (int q = 1; q <= p; q++) // TERM + for (int q = 1; q <= p; q++) { printf("Nested Do-While-For loop: %d\n", q); } @@ -71,11 +71,11 @@ int main() // Nested while loop with a break statement int n = 1; - while (n <= 5) // TERM + while (n <= 5) { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) // TERM + while (1) { printf("Inner While loop iteration: %d\n", m); m++; @@ -88,7 +88,7 @@ int main() } // Loop with a continue statement - for (int r = 1; r <= 10; r++) // TERM + for (int r = 1; r <= 10; r++) { if (r % 3 == 0) { @@ -99,7 +99,7 @@ int main() // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) // TERM + while (s <= 10 && s % 2 == 0) { printf("Loop with Multiple Conditions: %d\n", s); s++; @@ -107,13 +107,13 @@ int main() // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { printf("Loop with Multiple Variables: %d %d\n", t, u); } // Loop with nested conditions - for (int v = 1; v <= 10; v++) // TERM + for (int v = 1; v <= 10; v++) { printf("Loop with Nested Conditions: %d - ", v); if (v < 5) @@ -137,7 +137,7 @@ int main() { printf("Loop with Label and Goto: %d\n", w); w++; - goto start; // TERM + goto start; } return 0; diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 855fbd0dca..5ff890e461 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,15 +1,15 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount = 1; - while (outerCount <= 3) // NOTERM + while (outerCount <= 3) { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) // NOTERM + while (outerCount < 3 || innerCount > 0) { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index dcf72552bc..b66fbe57ea 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int num = 1; -loop: // TERM +loop: printf("Current number: %d\n", num); num++; diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index 672128e009..cfe5ab481d 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int num = 1; -loop: // NOTERM +loop: printf("Current number: %d\n", num); num++; diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c index 879ae3748a..426c5cdcca 100644 --- a/tests/regression/80-termination/19-rand-terminating.c +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i <= 5; i++) // TERM + for (int i = 1; i <= 5; i++) { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j <= 5) // TERM + while (j <= 5) { printf("Loop inside else part: %d\n", j); j++; diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 27c3f2c388..7c21538612 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i >= 0; i++) // NOTERM + for (int i = 1; i >= 0; i++) { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j > 0) // NOTERM + while (j > 0) { printf("Loop inside else part: %d\n", j); } diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index 0edafe0f65..f54af1da7c 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,10 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int forever, i = 0; +// This loop is not provable, therefore it should throw a warning while (i < 4 || forever == 1) { i++; diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 5c270f3b2a..1bc104258d 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,10 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int forever = 1; +// This loop is not provable, therefore it should throw a warning while (forever == 1) { if (rand()) //May exit, may not diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 228fc3b15e..9d000069e1 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index f4b6b8fbe2..a774f70457 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index c30e65f44b..28d8824535 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index 5d34e5c523..41bf44c44e 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index 6e4432dc5e..a230827356 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c index 1c52faec68..4f09950025 100644 --- a/tests/regression/81-recursion/01-simple-terminating.c +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index a6d6b3ab17..3ed0b75a0d 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c index 096a1b0121..23bedef644 100644 --- a/tests/regression/81-recursion/03-nested-terminating.c +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c index ab5e35d80f..d28685e139 100644 --- a/tests/regression/81-recursion/04-nested-nonterminating.c +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 7a6b18cbe37d21f9cff1ca0797b2cbc5088da804 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:07:23 +0200 Subject: [PATCH 135/628] reverted test case --- output.txt | 464 ++++++++++++++++++++++++++--------------------------- 1 file changed, 231 insertions(+), 233 deletions(-) diff --git a/output.txt b/output.txt index d751966836..37eb310726 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_1044835921 { +union __anonunion___atomic_wide_counter_316368393 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_316368393 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_1044835922 { +struct __anonstruct___once_flag_826868709 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_1044835922 __once_flag; +typedef struct __anonstruct___once_flag_826868709 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1115,496 +1115,494 @@ void example1(void) } #line 27 term27_5-file_01-simple-cases ++; +#line 27 + term_exit- = term27_5-file_01-simple-cases; #line 28 a[i] = i; -#line 29 - i ++; } while_break: /* CIL Label */ ; } -#line 27 - term_exit- = term27_5-file_01-simple-cases; } -#line 32 +#line 31 __goblint_check(a[0] == 0); -#line 33 +#line 32 __goblint_check(a[3] == 3); -#line 34 +#line 33 return; } } -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 36 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example2(void) { int a[5] ; int i ; - int term42_5-file_01-simple-cases ; + int term41_5-file_01-simple-cases ; { -#line 40 +#line 39 i = 0; { -#line 42 - term42_5-file_01-simple-cases = 0; +#line 41 + term41_5-file_01-simple-cases = 0; { -#line 42 +#line 41 while (1) { while_continue: /* CIL Label */ ; -#line 43 +#line 42 a[i] = i; -#line 44 +#line 43 i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 +#line 41 + term41_5-file_01-simple-cases ++; +#line 41 + term_exit- = term41_5-file_01-simple-cases; +#line 41 if (! (i <= 5)) { -#line 42 +#line 41 goto while_break; } } while_break: /* CIL Label */ ; } -#line 42 - term_exit- = term42_5-file_01-simple-cases; } -#line 47 +#line 46 __goblint_check(a[0] == 0); -#line 48 +#line 47 __goblint_check(a[3] == 3); -#line 49 +#line 48 return; } } -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 51 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example3(void) { int a[10] ; int i ; - int term57_5-file_01-simple-cases ; + int term56_5-file_01-simple-cases ; { -#line 55 +#line 54 i = 0; { -#line 57 - term57_5-file_01-simple-cases = 0; +#line 56 + term56_5-file_01-simple-cases = 0; { -#line 57 +#line 56 while (1) { while_continue: /* CIL Label */ ; -#line 57 +#line 56 if (! (i < 5)) { -#line 57 +#line 56 goto while_break; } +#line 56 + term56_5-file_01-simple-cases ++; +#line 56 + term_exit- = term56_5-file_01-simple-cases; #line 57 - term57_5-file_01-simple-cases ++; -#line 58 a[i] = i; -#line 59 +#line 58 i ++; } while_break: /* CIL Label */ ; } -#line 57 - term_exit- = term57_5-file_01-simple-cases; } -#line 62 +#line 61 __goblint_check(a[0] == 0); -#line 63 +#line 62 __goblint_check(a[3] == 0); -#line 64 +#line 63 __goblint_check(a[7] == 0); -#line 65 +#line 64 return; } } -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 67 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example4(void) { int a[10] ; int i ; int first_iteration ; - int term74_5-file_01-simple-cases ; + int term73_5-file_01-simple-cases ; { -#line 71 +#line 70 i = 0; -#line 72 +#line 71 first_iteration = 1; { -#line 74 - term74_5-file_01-simple-cases = 0; +#line 73 + term73_5-file_01-simple-cases = 0; { -#line 74 +#line 73 while (1) { while_continue: /* CIL Label */ ; -#line 74 +#line 73 if (! (i < 10)) { -#line 74 +#line 73 goto while_break; } +#line 73 + term73_5-file_01-simple-cases ++; +#line 73 + term_exit- = term73_5-file_01-simple-cases; #line 74 - term74_5-file_01-simple-cases ++; -#line 75 if (first_iteration == 1) { -#line 75 +#line 74 __goblint_check(i == 0); } else -#line 76 +#line 75 if (i > 5) { -#line 76 +#line 75 __goblint_check(i == 6); } -#line 77 +#line 76 first_iteration = 0; -#line 78 +#line 77 a[i] = 0; -#line 79 +#line 78 i ++; } while_break: /* CIL Label */ ; } -#line 74 - term_exit- = term74_5-file_01-simple-cases; } -#line 82 +#line 81 __goblint_check(a[0] == 0); -#line 83 +#line 82 __goblint_check(first_iteration == 0); -#line 84 +#line 83 return; } } -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 88 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example5(void) { int a[4] ; int i ; int top ; - int term95_5-file_01-simple-cases ; + int term94_5-file_01-simple-cases ; { -#line 92 +#line 91 i = 0; -#line 93 +#line 92 top = 0; { -#line 95 - term95_5-file_01-simple-cases = 0; +#line 94 + term94_5-file_01-simple-cases = 0; { -#line 95 +#line 94 while (1) { while_continue: /* CIL Label */ ; -#line 95 +#line 94 if (! (i < 4)) { -#line 95 +#line 94 goto while_break; } +#line 94 + term94_5-file_01-simple-cases ++; +#line 94 + term_exit- = term94_5-file_01-simple-cases; #line 95 - term95_5-file_01-simple-cases ++; -#line 96 a[i] = 0; -#line 97 +#line 96 top += i; -#line 98 +#line 97 if (i == 2) { -#line 99 +#line 98 __goblint_check(top == 3); } else { -#line 102 +#line 101 __goblint_check(top == 3); } -#line 104 +#line 103 i ++; } while_break: /* CIL Label */ ; } -#line 95 - term_exit- = term95_5-file_01-simple-cases; } -#line 107 +#line 106 __goblint_check(a[0] == 0); -#line 108 +#line 107 __goblint_check(a[3] == 0); -#line 109 +#line 108 __goblint_check(top == 6); -#line 110 +#line 109 return; } } -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 112 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example6(void) { int a[5] ; int i ; int top ; - int term119_5-file_01-simple-cases ; + int term118_5-file_01-simple-cases ; { -#line 116 +#line 115 i = 0; -#line 117 +#line 116 top = 0; { -#line 119 - term119_5-file_01-simple-cases = 0; +#line 118 + term118_5-file_01-simple-cases = 0; { -#line 119 +#line 118 while (1) { while_continue: /* CIL Label */ ; -#line 119 +#line 118 if (! (i < 3)) { -#line 119 +#line 118 goto while_break; } +#line 118 + term118_5-file_01-simple-cases ++; +#line 118 + term_exit- = term118_5-file_01-simple-cases; #line 119 - term119_5-file_01-simple-cases ++; -#line 120 a[i] = 0; -#line 121 +#line 120 __goblint_check(a[0] == 0); -#line 122 +#line 121 i ++; } while_break: /* CIL Label */ ; } -#line 119 - term_exit- = term119_5-file_01-simple-cases; } -#line 125 +#line 124 __goblint_check(a[0] == 0); -#line 126 +#line 125 __goblint_check(a[3] == 0); -#line 127 +#line 126 __goblint_check(top == 6); -#line 128 +#line 127 return; } } -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 130 "tests/regression/55-loop-unrolling/01-simple-cases.c" int update(int i ) { { -#line 132 +#line 131 if (i > 5) { -#line 133 +#line 132 return (0); } else { -#line 136 +#line 135 return (1); } } } -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 138 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example7(void) { int a[10] ; int i ; int tmp ; - int term143_2-file_01-simple-cases ; + int term142_2-file_01-simple-cases ; { -#line 142 +#line 141 i = 0; { -#line 143 - term143_2-file_01-simple-cases = 0; +#line 142 + term142_2-file_01-simple-cases = 0; { -#line 143 +#line 142 while (1) { while_continue: /* CIL Label */ ; -#line 143 +#line 142 tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 +#line 142 + term142_2-file_01-simple-cases ++; +#line 142 + term_exit- = term142_2-file_01-simple-cases; +#line 142 if (! tmp) { -#line 143 +#line 142 goto while_break; } -#line 144 +#line 143 a[i] = i; -#line 145 +#line 144 i ++; } while_break: /* CIL Label */ ; } -#line 143 - term_exit- = term143_2-file_01-simple-cases; } -#line 147 +#line 146 __goblint_check(a[0] == 0); -#line 148 +#line 147 __goblint_check(a[6] == 0); -#line 149 +#line 148 return; } } -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 151 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example8(void) { int a[5] ; int b[5] ; int i ; int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; + int term159_9-file_01-simple-cases ; + int term156_2-file_01-simple-cases ; { -#line 155 +#line 154 b[0] = 0; -#line 155 +#line 154 b[1] = 0; -#line 155 +#line 154 b[2] = 0; -#line 155 +#line 154 b[3] = 0; -#line 155 +#line 154 b[4] = 0; -#line 156 +#line 155 i = 0; { -#line 157 - term157_2-file_01-simple-cases = 0; +#line 156 + term156_2-file_01-simple-cases = 0; { -#line 157 +#line 156 while (1) { while_continue: /* CIL Label */ ; -#line 157 +#line 156 if (! (i < 5)) { -#line 157 +#line 156 goto while_break; } +#line 156 + term156_2-file_01-simple-cases ++; +#line 156 + term_exit- = term156_2-file_01-simple-cases; #line 157 - term157_2-file_01-simple-cases ++; -#line 158 a[i] = i; -#line 159 +#line 158 j = 0; { -#line 160 - term160_9-file_01-simple-cases = 0; +#line 159 + term159_9-file_01-simple-cases = 0; { -#line 160 +#line 159 while (1) { while_continue___0: /* CIL Label */ ; -#line 160 +#line 159 if (! (j < 5)) { -#line 160 +#line 159 goto while_break___0; } +#line 159 + term159_9-file_01-simple-cases ++; +#line 159 + term_exit- = term159_9-file_01-simple-cases; #line 160 - term160_9-file_01-simple-cases ++; -#line 161 b[j] += a[i]; -#line 162 +#line 161 j ++; } while_break___0: /* CIL Label */ ; } -#line 160 - term_exit- = term160_9-file_01-simple-cases; } -#line 164 +#line 163 i ++; } while_break: /* CIL Label */ ; } -#line 157 - term_exit- = term157_2-file_01-simple-cases; } -#line 166 +#line 165 return; } } -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 169 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example9(void) { int a[5] ; int i ; - int term174_2-file_01-simple-cases ; + int term173_2-file_01-simple-cases ; { -#line 173 +#line 172 i = 0; { -#line 174 - term174_2-file_01-simple-cases = 0; +#line 173 + term173_2-file_01-simple-cases = 0; { -#line 174 +#line 173 while (1) { while_continue: /* CIL Label */ ; -#line 174 +#line 173 if (! 1) { -#line 174 +#line 173 goto while_break; } +#line 173 + term173_2-file_01-simple-cases ++; +#line 173 + term_exit- = term173_2-file_01-simple-cases; #line 174 - term174_2-file_01-simple-cases ++; -#line 175 a[i] = i; -#line 176 +#line 175 i ++; -#line 177 +#line 176 if (i == 5) { -#line 177 +#line 176 goto while_break; } } while_break: /* CIL Label */ ; } -#line 174 - term_exit- = term174_2-file_01-simple-cases; } -#line 179 +#line 178 return; } } -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 182 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example10(void) { int a[5] ; int i ; - int term187_2-file_01-simple-cases ; + int term186_2-file_01-simple-cases ; { -#line 186 +#line 185 i = 0; { -#line 187 - term187_2-file_01-simple-cases = 0; +#line 186 + term186_2-file_01-simple-cases = 0; { -#line 187 +#line 186 while (1) { while_continue: /* CIL Label */ ; -#line 187 +#line 186 if (! (i < 5)) { -#line 187 +#line 186 goto while_break; } +#line 186 + term186_2-file_01-simple-cases ++; +#line 186 + term_exit- = term186_2-file_01-simple-cases; #line 187 - term187_2-file_01-simple-cases ++; -#line 188 if (i == 3) { -#line 189 +#line 188 i ++; -#line 190 +#line 189 goto while_continue; } -#line 192 +#line 191 a[i] = i; -#line 193 +#line 192 i ++; } while_break: /* CIL Label */ ; } -#line 187 - term_exit- = term187_2-file_01-simple-cases; } -#line 195 +#line 194 return; } } @@ -1683,42 +1681,40 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 246 +#line 249 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 263 +#line 251 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 271 +#line 262 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 281 +#line 272 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 285 +#line 276 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , - struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , - struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 323 +#line 279 +extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 282 +extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 311 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 338 +#line 326 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 343 +#line 331 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 348 +#line 336 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 352 +#line 340 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 357 +#line 345 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 376 +#line 364 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 383 +#line 371 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1829,8 +1825,9 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 773 -extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; +#line 766 +extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, +__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1995,7 +1992,8 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__)) ; + void const *__pointer ) __attribute__((__nothrow__, +__access__(__none__,2))) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; @@ -2057,6 +2055,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 9 term9_3-file_stdlib ++; +#line 9 + term_exit- = term9_3-file_stdlib; #line 10 j = (size_t )0; { @@ -2073,6 +2073,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 10 term10_5-file_stdlib ++; +#line 10 + term_exit- = term10_5-file_stdlib; #line 11 (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); #line 10 @@ -2080,16 +2082,12 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___0: /* CIL Label */ ; } -#line 10 - term_exit- = term10_5-file_stdlib; } #line 9 i ++; } while_break: /* CIL Label */ ; } -#line 9 - term_exit- = term9_3-file_stdlib; } #line 16 i___0 = (size_t )0; @@ -2107,6 +2105,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 16 term16_3-file_stdlib ++; +#line 16 + term_exit- = term16_3-file_stdlib; #line 17 j___0 = (size_t )0; { @@ -2123,6 +2123,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 17 term17_5-file_stdlib ++; +#line 17 + term_exit- = term17_5-file_stdlib; #line 19 if (r) { #line 21 @@ -2141,6 +2143,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 21 term21_9-file_stdlib ++; +#line 21 + term_exit- = term21_9-file_stdlib; #line 22 a = (char *)((ptr + i___0 * size) + k); #line 23 @@ -2156,8 +2160,6 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___3: /* CIL Label */ ; } -#line 21 - term_exit- = term21_9-file_stdlib; } } #line 17 @@ -2165,16 +2167,12 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___2: /* CIL Label */ ; } -#line 17 - term_exit- = term17_5-file_stdlib; } #line 16 i___0 ++; } while_break___1: /* CIL Label */ ; } -#line 16 - term_exit- = term16_3-file_stdlib; } #line 33 return; @@ -2212,6 +2210,8 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size } #line 40 term40_3-file_stdlib ++; +#line 40 + term_exit- = term40_3-file_stdlib; #line 41 a = ptr + i * size; #line 42 @@ -2226,8 +2226,6 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size } while_break: /* CIL Label */ ; } -#line 40 - term_exit- = term40_3-file_stdlib; } #line 47 return ((void *)0); From 4a402ca5373f2fe6eeb8e5dcc357368fd4f7b118 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:10:44 +0200 Subject: [PATCH 136/628] reverted test case --- .../55-loop-unrolling/01-simple-cases.c | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 9bf8d98683..3d5ce1b4e4 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -3,27 +3,6 @@ int global; -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(); -g(x); -} - -/* int main(void) { example1(); @@ -215,5 +194,4 @@ void example10(void) ++i; } return 0; -} -*/ \ No newline at end of file +} \ No newline at end of file From 79ac4ba84bdf5b02d643e73993a187f1282a8d38 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:39:49 +0200 Subject: [PATCH 137/628] fixed error that for only one function the analysis was not executed: pulled check for result of loop analysis outside --- src/framework/constraints.ml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index f0ae87acef..48196425f0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1764,24 +1764,23 @@ struct ) gmap (* try all fundec + context pairs that are in the map *) with Invalid_argument _ -> () (* path ended: no cycle*) - let checkTerminating ctx v v' = - (*Check if the loops terminated*) - if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> + let ret = ctx.ask Queries.MustTermProg in + (* check result of loop analysis *) + if not ret then + (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); let v: V.t = Obj.obj v in begin match v with | `Left v' -> - S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> checkTerminating ctx v v' + S.query (conv ctx) (WarnGlobal (Obj.repr v')) + | `Right v' -> if ret then (cycleDetection ctx v v') (* Only analyze if the recursion terminates if the loops terminated *) end | InvariantGlobal v -> let v: V.t = Obj.obj v in From 6a4105df8671cc6fc9a74e19b14257e2672b2543 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 14:48:04 +0200 Subject: [PATCH 138/628] Added SKIP/TODO functionality for loop termination --- scripts/update_suite.rb | 23 ++++++++++++++++--- .../02-simple-loop-nonterminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../80-termination/18-goto-nonterminating.c | 2 +- .../80-termination/20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../81-recursion/02-simple-nonterminating.c | 2 +- 13 files changed, 32 insertions(+), 15 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 69b3bae485..d85acfc1d8 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -186,9 +186,15 @@ def compare_warnings if cond then @correct += 1 # full p.path is too long and p.name does not allow click to open in terminal - if todo.include? idx then puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" end + if todo.include? idx + if idx < 0 + puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan} for #{type.yellow} is now passing!" + else + puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" + end + end else - if todo.include? idx then + if todo.include? idx @ignored += 1 else if idx < 0 # When non line specific keywords were used don't print a line @@ -202,7 +208,9 @@ def compare_warnings end } case type - when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn", "non_local_term" + when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn" + check.call warnings[idx] == type + when "non_local_term" check.call warnings[idx] == type when "nowarn", "local_term" check.call warnings[idx].nil? @@ -316,6 +324,15 @@ def parse_tests (lines) end end case lines[0] + when /TODO|SKIP/ + case lines[0] + when /NON_LOCAL_TERM/ + tests[-2] = "non_local_term" # Not sure if -2 is allowed or undefined in Ruby but it seems to work correctly + todo << -2 + when /LOCAL_TERM/ + tests[-2] = "local_term" + todo << -2 + end when /NON_LOCAL_TERM/ # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless tests[-2] = "non_local_term" diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index bcb9909f80..8c4c63ffab 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..5a7ac43f70 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c index b8f30361d1..73a8b8c6fd 100644 --- a/tests/regression/80-termination/06-for-loop-nonterminating.c +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c index 0368120b13..8b451e56dd 100644 --- a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index 5ed18175e9..c242e9a87c 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..9d51c17216 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index cfe5ab481d..ab85ccf8de 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 7c21538612..fb1f336349 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..ce0fbb78ff 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 1bc104258d..db79588945 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index a230827356..165a53fccf 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index 3ed0b75a0d..ef530f95d8 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 6f3921876d5408062d0289a33f7343431044a7fe Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 15:09:41 +0200 Subject: [PATCH 139/628] Adapted TODO comments to current state --- tests/regression/80-termination/02-simple-loop-nonterminating.c | 2 +- tests/regression/80-termination/04-nested-loop-nonterminating.c | 2 +- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- tests/regression/80-termination/14-do-while-nonterminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- .../80-termination/16-nested-loop-nontrivial-nonterminating.c | 2 +- tests/regression/80-termination/17-goto-terminating.c | 2 +- tests/regression/80-termination/18-goto-nonterminating.c | 2 +- tests/regression/80-termination/20-rand-nonterminating.c | 2 +- .../regression/80-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/23-exit-on-rand-terminating.c | 2 +- .../80-termination/24-upjumping-goto-loopless-terminating.c | 2 +- .../regression/80-termination/25-leave-loop-goto-terminating.c | 2 +- .../regression/80-termination/26-enter-loop-goto-terminating.c | 2 +- .../80-termination/27-upjumping-goto-nonterminating.c | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index 8c4c63ffab..bcb9909f80 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index 5a7ac43f70..ee2aa4a8c4 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ae68b11575..c4cad58bff 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index eb79338078..9a5a4429de 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index c242e9a87c..5ed18175e9 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index f3a08f4139..e0307cc53c 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 9d51c17216..5ff890e461 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index b66fbe57ea..e988926359 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index ab85ccf8de..cfe5ab481d 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index fb1f336349..7c21538612 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index ce0fbb78ff..f54af1da7c 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index db79588945..1bc104258d 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 9d000069e1..253d38c5df 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index a774f70457..01bffde383 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index 28d8824535..fed0e218ac 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index 41bf44c44e..2a43933758 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index 165a53fccf..a230827356 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From 0f3dbdc607d0f0e4f0ae20176195728b1baf2bc7 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:16:13 +0200 Subject: [PATCH 140/628] Comment out unused loop_heads function --- src/analyses/termination_new.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a3aa3aef92..7f2aa8357c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string +(* let loop_heads () = let module FileCfg = struct @@ -13,7 +14,8 @@ let loop_heads () = module Cfg = (val !MyCFG.current_cfg) end in let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in - WitnessInvariant.loop_heads (* TODO: Use this *) + WitnessInvariant.loop_heads (* TODO: Unused *) +*) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty From 1a0905791df38fb6ce2c72ff02de875004d0c201 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:26:31 +0200 Subject: [PATCH 141/628] Answer queries with false when multi-threaded --- src/analyses/termination_new.ml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7f2aa8357c..cd4b652f65 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -96,6 +96,11 @@ struct (* TODO: Implement check for our special loop exit indicator function *) ctx.local + (** Checks whether a new thread was spawned some time. We want to discard + * any knowledge about termination then (see query function) *) + let must_be_single_threaded_since_start ctx = + ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -103,9 +108,11 @@ struct (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) + && must_be_single_threaded_since_start ctx | Queries.MustTermProg -> G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () + && must_be_single_threaded_since_start ctx | _ -> Queries.Result.top q end From 524f0cb6c55f1b840198a399df65f8cca90a9096 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:28:55 +0200 Subject: [PATCH 142/628] Change comments --- src/analyses/termination_new.ml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index cd4b652f65..7ecb11a12c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -75,17 +75,9 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with - (* - (Var x, NoOffset), _ when is_loop_counter_var x -> - (* Assume that the following loop does not terminate *) - let loop_statement = VarToStmt.find x !loop_counters in - let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in - let () = print_endline ("Added FALSE for " ^ x.vname) in - D.add (`Lifted loop_statement) false ctx.local - *) (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move *) + (* TODO: Move to special *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in From 72062a6fee57f95a814226685014288248fdd87a Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 16:01:57 +0200 Subject: [PATCH 143/628] Added requested test cases --- .../28-do-while-continue-terminating.c | 21 +++++++++++ .../29-do-while-continue-nonterminating.c | 21 +++++++++++ .../30-goto-out-of-inner-loop-terminating.c | 22 ++++++++++++ ...31-goto-out-of-inner-loop-nonterminating.c | 23 ++++++++++++ .../32-multithread-terminating.c | 27 ++++++++++++++ .../33-multithread-nonterminating.c | 36 +++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 tests/regression/80-termination/28-do-while-continue-terminating.c create mode 100644 tests/regression/80-termination/29-do-while-continue-nonterminating.c create mode 100644 tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c create mode 100644 tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c create mode 100644 tests/regression/80-termination/32-multithread-terminating.c create mode 100644 tests/regression/80-termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/80-termination/28-do-while-continue-terminating.c new file mode 100644 index 0000000000..5989c61fed --- /dev/null +++ b/tests/regression/80-termination/28-do-while-continue-terminating.c @@ -0,0 +1,21 @@ +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do + { + i++; + printf("Inside the do-while loop\n"); + if (i % 2 == 0) { + + printf("Skipping %i is even\n", i); + continue; + } + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/80-termination/29-do-while-continue-nonterminating.c new file mode 100644 index 0000000000..806456e887 --- /dev/null +++ b/tests/regression/80-termination/29-do-while-continue-nonterminating.c @@ -0,0 +1,21 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do + { + printf("Inside the do-while loop\n"); + i++; + + if(i%2) { + printf("Continue as %i is odd\n", i); + continue; + } + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c new file mode 100644 index 0000000000..76c272a654 --- /dev/null +++ b/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c @@ -0,0 +1,22 @@ +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + printf("\n"); + outer_loop:; // Label for the outer loop + } + + return 0; +} diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c new file mode 100644 index 0000000000..c1824227d0 --- /dev/null +++ b/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -0,0 +1,23 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; 1; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + printf("Goto as continue for outer loop\n"); + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + printf("\n"); + outer_loop:; // Label for the outer loop + } + + return 0; +} diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/80-termination/32-multithread-terminating.c new file mode 100644 index 0000000000..a08fe01398 --- /dev/null +++ b/tests/regression/80-termination/32-multithread-terminating.c @@ -0,0 +1,27 @@ +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +#include +#include + +// Thread function +void* printPID(void* arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + return NULL; +} + +int main() { + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); + + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); + + return 0; +} diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/80-termination/33-multithread-nonterminating.c new file mode 100644 index 0000000000..77cd2aafe6 --- /dev/null +++ b/tests/regression/80-termination/33-multithread-nonterminating.c @@ -0,0 +1,36 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +#include +#include +#include +#include + +// Thread function +void* printPID(void* arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + while(1) { + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + struct timespec sleepTime; + sleepTime.tv_sec = 1; // Seconds + sleepTime.tv_nsec = 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) + printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); + nanosleep(&sleepTime, NULL); + } + return NULL; +} + +int main() { + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); + + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); + + return 0; +} From 2f9f697f4e53e8324a62844839fed5b2f478dcef Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 22 Jun 2023 13:32:39 +0200 Subject: [PATCH 144/628] Skip crashing tests --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index c4cad58bff..8951924c06 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9a5a4429de..dbce2a6b5b 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e0307cc53c..7daa9b98fe 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index ef530f95d8..c7902e2e7f 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From e250557c958d60fa1d8e48b1b678ad600ace27ef Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 13:35:33 +0200 Subject: [PATCH 145/628] reverted test case 55 01 --- tests/regression/55-loop-unrolling/01-simple-cases.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 3d5ce1b4e4..add8c6a8dd 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -30,8 +30,7 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - lab:__goblint_check(a[3] == 3); // UNKNOWN - goto lab; + __goblint_check(a[3] == 3); // UNKNOWN } // Do-while loop simple example From 4e66fd2bf3118fad23d2944400234da6fc869956 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:05:13 +0200 Subject: [PATCH 146/628] make recursion analysis optional (depending if loop ana is activated) --- src/framework/constraints.ml | 5 ++--- src/framework/control.ml | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48196425f0..e57570eb35 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1767,9 +1767,8 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> - let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) - if not ret then + if not (ctx.ask Queries.MustTermProg) then (let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); @@ -1780,7 +1779,7 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> if ret then (cycleDetection ctx v v') (* Only analyze if the recursion terminates if the loops terminated *) + | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) end | InvariantGlobal v -> let v: V.t = Obj.obj v in diff --git a/src/framework/control.ml b/src/framework/control.ml index 6261329e18..b157a2e81a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,6 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in + let arg_termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* 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 @@ -36,7 +37,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 RecursionTermLifter)(*TODO: should we really always evaluate it???*) + |> lift arg_termination (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 4b4be5b8d0bce38f15b07cfd95d4f48a6fc41d3f Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 22 Jun 2023 16:27:14 +0200 Subject: [PATCH 147/628] work-in-progress on svcomp integration --- src/analyses/apron/apronAnalysis.apron.ml | 2 -- src/autoTune.ml | 1 + src/framework/analysisState.ml | 3 +++ src/framework/constraints.ml | 7 ++++--- src/witness/svcomp.ml | 1 + src/witness/svcompSpec.ml | 4 ++++ src/witness/witness.ml | 17 +++++++++++++++++ .../55-loop-unrolling/01-simple-cases.c | 3 +-- 8 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 789701d37c..1ac88c66ee 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,7 +1,5 @@ (** Analysis using Apron for integer variables. *) open Analyses -open TerminationPreprocessing -open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = diff --git a/src/autoTune.ml b/src/autoTune.ml index a267c3bf9b..4fb8a1db5e 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -216,6 +216,7 @@ let focusOnSpecification () = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; + | NoTermination -> () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index 0f3a9f55bc..ddecf1752a 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,6 +7,9 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false +(** TODO:**) +let svcomp_must_terminate = ref true + (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48196425f0..865b0405ee 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1716,7 +1716,7 @@ struct module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) - let name () = "RecursionTerm (" ^ S.name () ^ ")" + let name () = "termination" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with @@ -1734,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - + AnalysisState.svcomp_must_terminate := false; (*Cycle found*) let msgs = [ @@ -1770,7 +1770,8 @@ struct let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) if not ret then - (let msgs = + (AnalysisState.svcomp_must_terminate := false; + let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index a5a572d1c2..a164448210 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -52,6 +52,7 @@ struct | UnreachCall _ -> "unreach-call" | NoOverflow -> "no-overflow" | NoDataRace -> "no-data-race" (* not yet in SV-COMP/Benchexec *) + | NoTermination -> "no-termination" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 464c170251..eec667c5a6 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -6,6 +6,7 @@ type t = | UnreachCall of string | NoDataRace | NoOverflow + | NoTermination let of_string s = let s = String.strip s in @@ -16,6 +17,8 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow + else if global_not = "termination" then (*TODO: does this even work?*) + NoTermination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -42,5 +45,6 @@ let to_string spec = | UnreachCall f -> "call(" ^ f ^ "())" | NoDataRace -> "data-race" | NoOverflow -> "overflow" + | NoTermination -> "termination" in "CHECK( init(main()), LTL(G ! " ^ global_not ^ ") )" diff --git a/src/witness/witness.ml b/src/witness/witness.ml index aff9a01383..04bcb1867b 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -442,6 +442,23 @@ struct in (module TaskResult:WitnessTaskResult) ) + | NoTermination -> (* TODO: implement this properly*) + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) | NoOverflow -> let module TrivialArg = struct diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 3d5ce1b4e4..add8c6a8dd 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -30,8 +30,7 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - lab:__goblint_check(a[3] == 3); // UNKNOWN - goto lab; + __goblint_check(a[3] == 3); // UNKNOWN } // Do-while loop simple example From 62d260fc915aefe9155a952d4a326b974c9d9fb8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:30:04 +0200 Subject: [PATCH 148/628] handled warnings during make --- output.txt | 2233 --------------------- src/analyses/apron/apronAnalysis.apron.ml | 2 - 2 files changed, 2235 deletions(-) delete mode 100644 output.txt diff --git a/output.txt b/output.txt deleted file mode 100644 index 37eb310726..0000000000 --- a/output.txt +++ /dev/null @@ -1,2233 +0,0 @@ -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_316368393 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_316368393 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -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 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 27 - term_exit- = term27_5-file_01-simple-cases; -#line 28 - a[i] = i; - } - while_break: /* CIL Label */ ; - } - } -#line 31 - __goblint_check(a[0] == 0); -#line 32 - __goblint_check(a[3] == 3); -#line 33 - return; -} -} -#line 36 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term41_5-file_01-simple-cases ; - - { -#line 39 - i = 0; - { -#line 41 - term41_5-file_01-simple-cases = 0; - { -#line 41 - while (1) { - while_continue: /* CIL Label */ ; -#line 42 - a[i] = i; -#line 43 - i ++; -#line 41 - term41_5-file_01-simple-cases ++; -#line 41 - term_exit- = term41_5-file_01-simple-cases; -#line 41 - if (! (i <= 5)) { -#line 41 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } - } -#line 46 - __goblint_check(a[0] == 0); -#line 47 - __goblint_check(a[3] == 3); -#line 48 - return; -} -} -#line 51 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term56_5-file_01-simple-cases ; - - { -#line 54 - i = 0; - { -#line 56 - term56_5-file_01-simple-cases = 0; - { -#line 56 - while (1) { - while_continue: /* CIL Label */ ; -#line 56 - if (! (i < 5)) { -#line 56 - goto while_break; - } -#line 56 - term56_5-file_01-simple-cases ++; -#line 56 - term_exit- = term56_5-file_01-simple-cases; -#line 57 - a[i] = i; -#line 58 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 61 - __goblint_check(a[0] == 0); -#line 62 - __goblint_check(a[3] == 0); -#line 63 - __goblint_check(a[7] == 0); -#line 64 - return; -} -} -#line 67 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term73_5-file_01-simple-cases ; - - { -#line 70 - i = 0; -#line 71 - first_iteration = 1; - { -#line 73 - term73_5-file_01-simple-cases = 0; - { -#line 73 - while (1) { - while_continue: /* CIL Label */ ; -#line 73 - if (! (i < 10)) { -#line 73 - goto while_break; - } -#line 73 - term73_5-file_01-simple-cases ++; -#line 73 - term_exit- = term73_5-file_01-simple-cases; -#line 74 - if (first_iteration == 1) { -#line 74 - __goblint_check(i == 0); - } else -#line 75 - if (i > 5) { -#line 75 - __goblint_check(i == 6); - } -#line 76 - first_iteration = 0; -#line 77 - a[i] = 0; -#line 78 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 81 - __goblint_check(a[0] == 0); -#line 82 - __goblint_check(first_iteration == 0); -#line 83 - return; -} -} -#line 88 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term94_5-file_01-simple-cases ; - - { -#line 91 - i = 0; -#line 92 - top = 0; - { -#line 94 - term94_5-file_01-simple-cases = 0; - { -#line 94 - while (1) { - while_continue: /* CIL Label */ ; -#line 94 - if (! (i < 4)) { -#line 94 - goto while_break; - } -#line 94 - term94_5-file_01-simple-cases ++; -#line 94 - term_exit- = term94_5-file_01-simple-cases; -#line 95 - a[i] = 0; -#line 96 - top += i; -#line 97 - if (i == 2) { -#line 98 - __goblint_check(top == 3); - } else { -#line 101 - __goblint_check(top == 3); - } -#line 103 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 106 - __goblint_check(a[0] == 0); -#line 107 - __goblint_check(a[3] == 0); -#line 108 - __goblint_check(top == 6); -#line 109 - return; -} -} -#line 112 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term118_5-file_01-simple-cases ; - - { -#line 115 - i = 0; -#line 116 - top = 0; - { -#line 118 - term118_5-file_01-simple-cases = 0; - { -#line 118 - while (1) { - while_continue: /* CIL Label */ ; -#line 118 - if (! (i < 3)) { -#line 118 - goto while_break; - } -#line 118 - term118_5-file_01-simple-cases ++; -#line 118 - term_exit- = term118_5-file_01-simple-cases; -#line 119 - a[i] = 0; -#line 120 - __goblint_check(a[0] == 0); -#line 121 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 124 - __goblint_check(a[0] == 0); -#line 125 - __goblint_check(a[3] == 0); -#line 126 - __goblint_check(top == 6); -#line 127 - return; -} -} -#line 130 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 131 - if (i > 5) { -#line 132 - return (0); - } else { -#line 135 - return (1); - } -} -} -#line 138 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term142_2-file_01-simple-cases ; - - { -#line 141 - i = 0; - { -#line 142 - term142_2-file_01-simple-cases = 0; - { -#line 142 - while (1) { - while_continue: /* CIL Label */ ; -#line 142 - tmp = update(i); -#line 142 - term142_2-file_01-simple-cases ++; -#line 142 - term_exit- = term142_2-file_01-simple-cases; -#line 142 - if (! tmp) { -#line 142 - goto while_break; - } -#line 143 - a[i] = i; -#line 144 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 146 - __goblint_check(a[0] == 0); -#line 147 - __goblint_check(a[6] == 0); -#line 148 - return; -} -} -#line 151 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term159_9-file_01-simple-cases ; - int term156_2-file_01-simple-cases ; - - { -#line 154 - b[0] = 0; -#line 154 - b[1] = 0; -#line 154 - b[2] = 0; -#line 154 - b[3] = 0; -#line 154 - b[4] = 0; -#line 155 - i = 0; - { -#line 156 - term156_2-file_01-simple-cases = 0; - { -#line 156 - while (1) { - while_continue: /* CIL Label */ ; -#line 156 - if (! (i < 5)) { -#line 156 - goto while_break; - } -#line 156 - term156_2-file_01-simple-cases ++; -#line 156 - term_exit- = term156_2-file_01-simple-cases; -#line 157 - a[i] = i; -#line 158 - j = 0; - { -#line 159 - term159_9-file_01-simple-cases = 0; - { -#line 159 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 159 - if (! (j < 5)) { -#line 159 - goto while_break___0; - } -#line 159 - term159_9-file_01-simple-cases ++; -#line 159 - term_exit- = term159_9-file_01-simple-cases; -#line 160 - b[j] += a[i]; -#line 161 - j ++; - } - while_break___0: /* CIL Label */ ; - } - } -#line 163 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 165 - return; -} -} -#line 169 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term173_2-file_01-simple-cases ; - - { -#line 172 - i = 0; - { -#line 173 - term173_2-file_01-simple-cases = 0; - { -#line 173 - while (1) { - while_continue: /* CIL Label */ ; -#line 173 - if (! 1) { -#line 173 - goto while_break; - } -#line 173 - term173_2-file_01-simple-cases ++; -#line 173 - term_exit- = term173_2-file_01-simple-cases; -#line 174 - a[i] = i; -#line 175 - i ++; -#line 176 - if (i == 5) { -#line 176 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } - } -#line 178 - return; -} -} -#line 182 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term186_2-file_01-simple-cases ; - - { -#line 185 - i = 0; - { -#line 186 - term186_2-file_01-simple-cases = 0; - { -#line 186 - while (1) { - while_continue: /* CIL Label */ ; -#line 186 - if (! (i < 5)) { -#line 186 - goto while_break; - } -#line 186 - term186_2-file_01-simple-cases ++; -#line 186 - term_exit- = term186_2-file_01-simple-cases; -#line 187 - if (i == 3) { -#line 188 - i ++; -#line 189 - goto while_continue; - } -#line 191 - a[i] = i; -#line 192 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 194 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 249 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 272 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 326 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 9 - term_exit- = term9_3-file_stdlib; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 10 - term_exit- = term10_5-file_stdlib; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 16 - term_exit- = term16_3-file_stdlib; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 17 - term_exit- = term17_5-file_stdlib; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 21 - term_exit- = term21_9-file_stdlib; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 40 - term_exit- = term40_3-file_stdlib; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 47 - return ((void *)0); -} -} diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 789701d37c..1ac88c66ee 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,7 +1,5 @@ (** Analysis using Apron for integer variables. *) open Analyses -open TerminationPreprocessing -open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = From 3707652189843f261fb6d12a8cb2abf59e6d107a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:47:16 +0200 Subject: [PATCH 149/628] indentation --- src/analyses/apron/apronAnalysis.apron.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 1ac88c66ee..1c31e975f2 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,5 +1,7 @@ (** Analysis using Apron for integer variables. *) + open Analyses + include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = From f7dab71875d61ae7c24f3221fb5643b7b372e345 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:56:26 +0200 Subject: [PATCH 150/628] indentation --- src/analyses/apron/apronAnalysis.apron.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 1c31e975f2..62ae96f400 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,9 +1,10 @@ -(** Analysis using Apron for integer variables. *) +(** {{!RelationAnalysis} Relational integer value analysis} using {!Apron} domains ([apron]). *) open Analyses include RelationAnalysis + let spec_module: (module MCPSpec) Lazy.t = lazy ( let module Man = (val ApronDomain.get_manager ()) in From 5b0d72ff32fd06809751696b5713a5a5aab897dc Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 22 Jun 2023 18:16:03 +0200 Subject: [PATCH 151/628] Indentation with ocp-indent --- src/analyses/apron/apronAnalysis.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 62ae96f400..bec0c4ec57 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -36,7 +36,7 @@ let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) - + let _ = AfterConfig.register after_config From 8a320eb3a9f5f8cd26fe4414ec5d26f95b4e16f6 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 22 Jun 2023 21:08:00 +0200 Subject: [PATCH 152/628] added sv-comp compatability --- src/framework/analysisState.ml | 2 +- src/framework/constraints.ml | 4 ++-- src/util/options.schema.json | 4 ++-- src/witness/svcompSpec.ml | 2 +- src/witness/witness.ml | 33 +++++++++++++++++++++++---------- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index ddecf1752a..3f577d79f4 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -8,7 +8,7 @@ let should_warn = ref false let svcomp_may_overflow = ref false (** TODO:**) -let svcomp_must_terminate = ref true +let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 865b0405ee..f6d920d74f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1734,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - AnalysisState.svcomp_must_terminate := false; + AnalysisState.svcomp_may_not_terminate := true; (*Cycle found*) let msgs = [ @@ -1770,7 +1770,7 @@ struct let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) if not ret then - (AnalysisState.svcomp_must_terminate := false; + (AnalysisState.svcomp_may_not_terminate := true; let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 3efaef2e83..8ec398b3ad 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -566,7 +566,7 @@ "title": "ana.sv-comp.enabled", "description": "SV-COMP mode", "type": "boolean", - "default": false + "default": true }, "functions": { "title": "ana.sv-comp.functions", @@ -581,7 +581,7 @@ "title": "ana.specification", "description": "SV-COMP specification (path or string)", "type": "string", - "default": "" + "default": "/home/isidor/goblint/goblint-analyzer/tests/sv-comp/no-termination.prp" }, "wp": { "title": "ana.wp", diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index eec667c5a6..f8791d065e 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -17,7 +17,7 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "termination" then (*TODO: does this even work?*) + else if global_not = "termination" then NoTermination else let call_regex = Str.regexp "call(\\(.*\\)())" in diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 04bcb1867b..f0e2f0f799 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -449,16 +449,29 @@ struct let next _ = [] end in - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) + if not !AnalysisState.svcomp_may_not_terminate then + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant = find_invariant + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) | NoOverflow -> let module TrivialArg = struct From 5d3f25cba243f67a14e8446fc6211faec2500116 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 22 Jun 2023 22:01:03 +0200 Subject: [PATCH 153/628] Fix indentation --- src/framework/constraints.ml | 78 ++++++++++++++++++------------------ src/witness/witness.ml | 44 ++++++++++---------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ab6931bf70..ce3ecadc1e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1698,19 +1698,19 @@ end (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D - and module C = S.C + and module C = S.C = (*global invariants: - - V -> G - - fundec -> Map (S.C) (Set (fundec * S.C)) + - V -> G + - fundec -> Map (S.C) (Set (fundec * S.C)) Therefore: g -> {c' -> {(f, c)}} in case f, c --> g, c' *) struct include S - module V = - struct + module V = + struct include GVarF(S.V) end @@ -1718,17 +1718,17 @@ struct let name () = "termination" - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } - let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let cycleDetection ctx v v' = + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in + let global_visited_calls = LH.create 100 in (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = @@ -1736,7 +1736,7 @@ struct if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*Cycle found*) - let msgs = + let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in @@ -1744,25 +1744,25 @@ struct else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) - end + end in - try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () (* path ended: no cycle*) + try + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () (* path ended: no cycle*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1770,18 +1770,18 @@ struct (* check result of loop analysis *) if not (ctx.ask Queries.MustTermProg) then (AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs - ); + let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); let v: V.t = Obj.obj v in begin match v with | `Left v' -> - S.query (conv ctx) (WarnGlobal (Obj.repr v')) + S.query (conv ctx) (WarnGlobal (Obj.repr v')) | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) - end + end | InvariantGlobal v -> let v: V.t = Obj.obj v in begin match v with @@ -1795,30 +1795,30 @@ struct let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - + (* c = context t = set of tuples (fundec * context) *) let side_context sideg f c t = if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - - let enter ctx = S.enter (conv ctx) + + let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx r fe f args fc es f_ask = + let combine_env ctx r fe f args fc es f_ask = if !AnalysisState.postsolving then let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let tup: (fundec * S.C.t) = (fd_r, c_r) in + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask - else + else S.combine_env (conv ctx) r fe f args fc es f_ask let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index f0e2f0f799..b62b2b54cd 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -23,7 +23,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module IsInteresting = struct (* type node = N.t - type edge = TaskResult.Arg.Edge.t *) + type edge = TaskResult.Arg.Edge.t *) let minwitness = get_bool "witness.minimize" let is_interesting_real from_node edge to_node = (* TODO: don't duplicate this logic with write_node, write_edge *) @@ -59,11 +59,11 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module GML = XmlGraphMlWriter in let module GML = (val match get_string "witness.id" with - | "node" -> - (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) - | "enumerate" -> - (module EnumerateNodeGraphMlWriter (N) (GML)) - | _ -> failwith "witness.id: illegal value" + | "node" -> + (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) + | "enumerate" -> + (module EnumerateNodeGraphMlWriter (N) (GML)) + | _ -> failwith "witness.id: illegal value" ) in let module GML = DeDupGraphMlWriter (N) (GML) in @@ -107,16 +107,16 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) GML.write_key g "edge" "goblintLine" "string" None; (* TODO: remove *) (* GML.write_key g "edge" "enterFunction2" "string" None; - GML.write_key g "edge" "returnFromFunction2" "string" None; *) + GML.write_key g "edge" "returnFromFunction2" "string" None; *) GML.start_graph g; GML.write_metadata g "witness-type" ( - match TaskResult.result with - | Result.True -> "correctness_witness" - | Result.False _ -> "violation_witness" - | Result.Unknown -> "unknown_witness" - ); + match TaskResult.result with + | Result.True -> "correctness_witness" + | Result.False _ -> "violation_witness" + | Result.Unknown -> "unknown_witness" + ); GML.write_metadata g "sourcecodelang" "C"; GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Version.goblint); GML.write_metadata g "specification" (Svcomp.Specification.to_string Task.specification); @@ -141,7 +141,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement _, `Lifted i -> let i = InvariantCil.exp_replace_original_name i in [("invariant", CilType.Exp.show i); - ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] + ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] | _ -> (* ignore entry and return invariants, variables of wrong scopes *) (* TODO: don't? fix scopes? *) @@ -150,10 +150,10 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) [] end; (* begin match cfgnode with - | Statement s -> + | Statement s -> [("sourcecode", GobPretty.sprint Basetype.CilStmt.pretty s)] (* TODO: sourcecode not official? especially on node? *) - | _ -> [] - end; *) + | _ -> [] + end; *) (* violation actually only allowed in violation witness *) (* maybe should appear on from_node of entry edge instead *) begin if TaskResult.is_violation node then @@ -170,7 +170,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement stmt -> Printf.sprintf "s%d" stmt.sid | Function f -> Printf.sprintf "ret%d%s" f.vid f.vname | FunctionEntry f -> Printf.sprintf "fun%d%s" f.vid f.vname - )] *) + )] *) (* [("goblintNode", N.to_string node)] *) ]) in @@ -213,9 +213,9 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) (* enter and return on other side of nodes, more correct loc (startline) but had some scope problem? *) (* | MyARG.CFGEdge (Entry f) -> - [("enterFunction2", f.svar.vname)] - | MyARG.CFGEdge (Ret (_, f)) -> - [("returnFromFunction2", f.svar.vname)] *) + [("enterFunction2", f.svar.vname)] + | MyARG.CFGEdge (Ret (_, f)) -> + [("returnFromFunction2", f.svar.vname)] *) | _ -> [] end; [("goblintEdge", Arg.Edge.to_string edge)] @@ -394,12 +394,12 @@ struct struct let path = observer_path end - ) + ) in MCP.register_analysis (module Spec); (* TODO: don't modify JSON but have ref vars for these instead *) (* GobConfig.set_list "ana.activated" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.activated"); - GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) + GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) (* TODO: don't append to end; currently done to get observer order to be nice *) GobConfig.set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String (Spec.name ())]); GobConfig.set_list "ana.path_sens" (GobConfig.get_list "ana.path_sens" @ [`String (Spec.name ())]); From 86031779609876e6b713ac2d5a4640831b3dcc15 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:27:10 +0200 Subject: [PATCH 154/628] Fix indentation --- src/framework/control.ml | 118 +++++++++++++++++++-------------------- src/util/cilfacade.ml | 14 ++--- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index 6a25283687..9a717e2f67 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,25 +20,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 arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) 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 arg_termination (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) @@ -303,10 +303,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 *) @@ -530,9 +530,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 = Version.goblint; 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 = Version.goblint; 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 *) @@ -584,10 +584,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; @@ -619,35 +619,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 diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 2043a94ed0..2a81444e41 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -89,14 +89,14 @@ let visitors_cil = ref [] (* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] - + let do_preprocess_cil ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) + let f fd (name, visitor_fun) = + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + if List.mem name (get_string_list "ana.activated") then + ignore @@ visitCilFunction (visitor_fun fd) fd + in + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) From d987f1a151e481a7dcd9fd50b1dc0b5a53b51f19 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:34:44 +0200 Subject: [PATCH 155/628] Restore signs analysis tutorial --- src/analyses/tutorials/signs.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index 9ae48f8626..31168df86a 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -23,12 +23,12 @@ struct (* TODO: An attempt to abstract integers, but it's just a little wrong... *) let of_int i = - if Z.compare i Z.zero < 0 then Neg - else if Z.compare i Z.zero > 0 then Pos + if Z.compare i Z.zero < 0 then Zero + else if Z.compare i Z.zero > 0 then Zero else Zero let lt x y = match x, y with - | Neg, Pos | Neg, Zero | Pos, Zero -> true (* TODO: Maybe something missing? *) + | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) | _ -> false end @@ -59,7 +59,7 @@ struct (* This should now evaluate expressions. *) let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.of_int i (* TODO: Fix me! *) + | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) | Lval (Var x, NoOffset) -> D.find x d | _ -> SL.top () From b1930abaf634e8a9a6c4f34186b41a5bdf5a9206 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:39:48 +0200 Subject: [PATCH 156/628] Simplify src/framework/analyses.ml Co-authored-by: Julian Erhard --- src/framework/analyses.ml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 20727aaf23..cae9d6f782 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -154,11 +154,7 @@ module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = struct - include SetDomain.Make ( - struct - include (Base) (* Set of Tuples*) - end - ) + include SetDomain.Make (Base) (* Set of Tuples*) let name () = "contexts" let printXml f a = BatPrintf.fprintf f "\n"; From a3fd8d0977a9217838037972d4bb6337422a0961 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:55:10 +0200 Subject: [PATCH 157/628] Fix indentation --- src/framework/analyses.ml | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index cae9d6f782..1c3d596cc2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,19 +119,19 @@ struct end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = -struct +module T (Base1: Printable.S) (Base2: Printable.S) = +struct include Printable.Std type t = (Base1.t * Base2.t) let fundec (a,_) = a let context (_,b) = b let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false - let show (a,b) = (Base1.show a) ^ (Base2.show b) + let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = + let printXml f (a,b) = BatPrintf.fprintf f "\n Tuple:\n\n caller_fundec\n%a\n\n @@ -139,13 +139,13 @@ struct \n" Base1.printXml a Base2.printXml b let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 + if equal (a1, b1) (a2, b2) then 0 else( let val_a a = if (a > 0) then 1 else -1 in let val_b b = if (b > 0) then 3 else -3 in val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) - ) - + ) + let pretty () x = text (show x) let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end @@ -156,24 +156,24 @@ struct struct include SetDomain.Make (Base) (* Set of Tuples*) let name () = "contexts" - let printXml f a = + let printXml f a = BatPrintf.fprintf f "\n"; iter (Base.printXml f) a; BatPrintf.fprintf f "\n\n" end (* Make the given module Goupable*) - module C_Printable (C: Printable.S) = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f - "\n + module C_Printable (C: Printable.S) = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f + "\n callee_context\n%a\n\n " printXml c - end + end - module CMap = + module CMap = struct include MapDomain.MapBot (C_Printable (C)) (CSet) let printXml f c = BatPrintf.fprintf f " @@ -188,14 +188,14 @@ struct | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "GVarGSet.spec" - let contexts = function + let contexts = function | `Bot -> CSet.bot () | `Lifted2 x -> x | _ -> failwith "GVarGSet.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts - let printXml f = function + let printXml f = function | `Lifted1 x -> G.printXml f x | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x From ba596d77282c549e29678885ba718ce592fc42eb Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 16:31:35 +0200 Subject: [PATCH 158/628] Remove build_testing.yml --- .github/workflows/build_testing.yml | 35 ----------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .github/workflows/build_testing.yml diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml deleted file mode 100644 index 1b464043c7..0000000000 --- a/.github/workflows/build_testing.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: build_testing - -on: - - push - - pull_request - -jobs: - tests: - strategy: - fail-fast: false - matrix: - os: - - macos-latest - - ubuntu-latest - ocaml-compiler: - - 4.12.0 - - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup OCaml ${{ matrix.ocaml-compiler }} - env: - OPAMLOCKED: locked - uses: ocaml/setup-ocaml@v2 - with: - ocaml-compiler: ${{ matrix.ocaml-compiler }} - - - name: Install opam dependencies - run: opam install . --deps-only --locked - - - name: Build - run: ./make.sh nat From fbef2088d75d627084e442c3648386c7d23ce419 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:24:33 +0200 Subject: [PATCH 159/628] No skipping --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 8951924c06..7fcd5c5eba 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index dbce2a6b5b..def1786937 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 7daa9b98fe..9ab04745e8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index c7902e2e7f..37c4bbd801 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 13f369acdb55b89378c9768edb07723091c724b7 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:31:36 +0200 Subject: [PATCH 160/628] New non terminating for loop --- .../34-nested-for-loop-nonterminating.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/regression/80-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..1f68f3c0a5 --- /dev/null +++ b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} From d681158d9bc6d37afd3a16ffa100336782311f97 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:34:13 +0200 Subject: [PATCH 161/628] Folder Renaming --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../01-simple-terminating.c | 0 .../02-simple-nonterminating.c | 0 .../03-nested-terminating.c | 0 .../04-nested-nonterminating.c | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{80-termination => 74-loop_termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/05-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/11-loopless-termination.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/13-do-while-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/17-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/18-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/19-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/20-rand-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/32-multithread-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/01-simple-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/02-simple-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/03-nested-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/04-nested-nonterminating.c (100%) diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/01-simple-loop-terminating.c rename to tests/regression/74-loop_termination/01-simple-loop-terminating.c diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/02-simple-loop-nonterminating.c rename to tests/regression/74-loop_termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/03-nested-loop-terminating.c rename to tests/regression/74-loop_termination/03-nested-loop-terminating.c diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/04-nested-loop-nonterminating.c rename to tests/regression/74-loop_termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/05-for-loop-terminating.c rename to tests/regression/74-loop_termination/05-for-loop-terminating.c diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/06-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/06-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/07-nested-for-loop-terminating.c rename to tests/regression/74-loop_termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/08-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/09-complex-for-loop-terminating.c rename to tests/regression/74-loop_termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/10-complex-loop-terminating.c rename to tests/regression/74-loop_termination/10-complex-loop-terminating.c diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c similarity index 100% rename from tests/regression/80-termination/11-loopless-termination.c rename to tests/regression/74-loop_termination/11-loopless-termination.c diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/80-termination/12-do-while-instant-terminating.c rename to tests/regression/74-loop_termination/12-do-while-instant-terminating.c diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/80-termination/13-do-while-terminating.c rename to tests/regression/74-loop_termination/13-do-while-terminating.c diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/80-termination/14-do-while-nonterminating.c rename to tests/regression/74-loop_termination/14-do-while-nonterminating.c diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/80-termination/15-complex-loop-combination-terminating.c rename to tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/17-goto-terminating.c rename to tests/regression/74-loop_termination/17-goto-terminating.c diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/18-goto-nonterminating.c rename to tests/regression/74-loop_termination/18-goto-nonterminating.c diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/19-rand-terminating.c rename to tests/regression/74-loop_termination/19-rand-terminating.c diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/80-termination/20-rand-nonterminating.c rename to tests/regression/74-loop_termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/22-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/23-exit-on-rand-terminating.c rename to tests/regression/74-loop_termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/25-leave-loop-goto-terminating.c rename to tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/26-enter-loop-goto-terminating.c rename to tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/27-upjumping-goto-nonterminating.c rename to tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/80-termination/28-do-while-continue-terminating.c rename to tests/regression/74-loop_termination/28-do-while-continue-terminating.c diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/80-termination/29-do-while-continue-nonterminating.c rename to tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/80-termination/32-multithread-terminating.c rename to tests/regression/74-loop_termination/32-multithread-terminating.c diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/80-termination/33-multithread-nonterminating.c rename to tests/regression/74-loop_termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/34-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c similarity index 100% rename from tests/regression/81-recursion/01-simple-terminating.c rename to tests/regression/75-recursion_termination/01-simple-terminating.c diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/02-simple-nonterminating.c rename to tests/regression/75-recursion_termination/02-simple-nonterminating.c diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c similarity index 100% rename from tests/regression/81-recursion/03-nested-terminating.c rename to tests/regression/75-recursion_termination/03-nested-terminating.c diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/04-nested-nonterminating.c rename to tests/regression/75-recursion_termination/04-nested-nonterminating.c From 541e49b1484fed17376bce8237c54054a85882b9 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:49:43 +0200 Subject: [PATCH 162/628] Enable polyhedra; Removed unnecessary TODOs --- .../15-complex-loop-combination-terminating.c | 2 +- .../74-loop_termination/34-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 9ab04745e8..ec6b50512e 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index 1f68f3c0a5..d8aa9d487d 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From 1b5db9c80811fcc083b90ac66554f03fb70dd9ab Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 12:59:03 +0200 Subject: [PATCH 163/628] patched loop termination check position to right after the loop head --- src/util/terminationPreprocessing.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 45794b56cc..abc0bd36ef 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,8 +35,10 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with - | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + | ss -> + b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + (*| cont :: ss -> + b.bstmts <- cont :: inc_stmt :: check_stmt :: ss;*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From e6ba5597dd0138b773ac21621d445b6eeca7e372 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 12:59:49 +0200 Subject: [PATCH 164/628] removed temporary comment --- src/util/terminationPreprocessing.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index abc0bd36ef..480bede358 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -37,8 +37,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) (match b.bstmts with | ss -> b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) - (*| cont :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: ss;*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 16b8c375d77934e572c7cd9576dcb115bfcfa4f2 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 13:01:43 +0200 Subject: [PATCH 165/628] removed outdated code --- src/util/terminationPreprocessing.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 480bede358..6e29c48917 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,8 +36,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | ss -> - b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) - | _ -> ()); + b.bstmts <- inc_stmt :: check_stmt :: ss; + ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; From 1cefa964032e3d2e39c9380efcfd7c59f9f65517 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:04:25 +0200 Subject: [PATCH 166/628] Removed unnecessary TODOs --- .../regression/74-loop_termination/06-for-loop-nonterminating.c | 2 +- .../74-loop_termination/08-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index 73a8b8c6fd..b8f30361d1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 8b451e56dd..0368120b13 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From 2430f3fc9a798d37025f50e80fc5000551e5b45f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:17:23 +0200 Subject: [PATCH 167/628] Renamed LOCAL_TERM to TERM --- scripts/update_suite.rb | 26 +++++++++---------- .../01-simple-loop-terminating.c | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../03-nested-loop-terminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../05-for-loop-terminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../07-nested-for-loop-terminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 2 +- .../13-do-while-terminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../74-loop_termination/17-goto-terminating.c | 2 +- .../18-goto-nonterminating.c | 2 +- .../74-loop_termination/19-rand-terminating.c | 2 +- .../20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../28-do-while-continue-terminating.c | 2 +- .../29-do-while-continue-nonterminating.c | 2 +- .../30-goto-out-of-inner-loop-terminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 2 +- .../32-multithread-terminating.c | 2 +- .../33-multithread-nonterminating.c | 2 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../01-simple-terminating.c | 2 +- .../02-simple-nonterminating.c | 2 +- .../03-nested-terminating.c | 2 +- .../04-nested-nonterminating.c | 2 +- 39 files changed, 50 insertions(+), 52 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 98eff124af..8841ecea88 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,11 +145,11 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "non_local_term" end # Get NonTerminating warning + if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj when /\(conf\. \d+\)/ then "race" when /Deadlock/ then "deadlock" @@ -208,9 +208,9 @@ def compare_warnings case type when "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type - when "non_local_term" + when "nonterm" check.call warnings[idx] == type - when "nowarn", "local_term" + when "nowarn", "term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -324,19 +324,17 @@ def parse_tests (lines) case lines[0] when /TODO|SKIP/ case lines[0] - when /NON_LOCAL_TERM/ - tests[-1] = "non_local_term" + when /NONTERM/ + tests[-1] = "nonterm" todo << -1 - when /LOCAL_TERM/ - tests[-1] = "local_term" + when /TERM/ + tests[-1] = "term" todo << -1 end - when /NON_LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "non_local_term" - when /LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "local_term" + when /NONTERM/ + tests[-1] = "nonterm" + when /TERM/ + tests[-1] = "term" end Tests.new(self, tests, tests_line, todo) end diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c index a517d0d608..a80084868a 100644 --- a/tests/regression/74-loop_termination/01-simple-loop-terminating.c +++ b/tests/regression/74-loop_termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c index bcb9909f80..eef9f81ea3 100644 --- a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c index 366cbaeea5..5e72ec3284 100644 --- a/tests/regression/74-loop_termination/03-nested-loop-terminating.c +++ b/tests/regression/74-loop_termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..1fb5ada507 100644 --- a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c index 2a16184f6d..cf71fa5135 100644 --- a/tests/regression/74-loop_termination/05-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index b8f30361d1..8c1500cfb1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c index def0787d39..4b3395bd11 100644 --- a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 0368120b13..818146e456 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fcd5c5eba..c26fde710f 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index def1786937..017c10b8a4 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c index 86a300f18e..01f9a953e0 100644 --- a/tests/regression/74-loop_termination/11-loopless-termination.c +++ b/tests/regression/74-loop_termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c index 15032b7b4f..b34dff3f5f 100644 --- a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c +++ b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c index 2e04f3e393..651acb8fd8 100644 --- a/tests/regression/74-loop_termination/13-do-while-terminating.c +++ b/tests/regression/74-loop_termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c index 5ed18175e9..1e05e2be6e 100644 --- a/tests/regression/74-loop_termination/14-do-while-nonterminating.c +++ b/tests/regression/74-loop_termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ec6b50512e..07fbe38cfd 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..b9ccea76af 100644 --- a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index e988926359..b11b5b3da9 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c index cfe5ab481d..aab37803aa 100644 --- a/tests/regression/74-loop_termination/18-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c index 426c5cdcca..5d3cde9f3d 100644 --- a/tests/regression/74-loop_termination/19-rand-terminating.c +++ b/tests/regression/74-loop_termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c index 7c21538612..124a19d0f8 100644 --- a/tests/regression/74-loop_termination/20-rand-nonterminating.c +++ b/tests/regression/74-loop_termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..3bf479b6f9 100644 --- a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c index 1bc104258d..1f1a9bbd89 100644 --- a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 253d38c5df..4b9aacd0fd 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 01bffde383..3c4fffdc8a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index fed0e218ac..380e98ded0 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 2a43933758..b676ca6985 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c index a230827356..52ad7ea820 100644 --- a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 5989c61fed..aa215a502a 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c index 806456e887..896d8fea95 100644 --- a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 76c272a654..0526e20bb4 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c index c1824227d0..722694eb88 100644 --- a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c index a08fe01398..1f98b88eee 100644 --- a/tests/regression/74-loop_termination/32-multithread-terminating.c +++ b/tests/regression/74-loop_termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c index 77cd2aafe6..007af3b57b 100644 --- a/tests/regression/74-loop_termination/33-multithread-nonterminating.c +++ b/tests/regression/74-loop_termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index d8aa9d487d..29e4ff3835 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c index 4f09950025..583f8ccca1 100644 --- a/tests/regression/75-recursion_termination/01-simple-terminating.c +++ b/tests/regression/75-recursion_termination/01-simple-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 37c4bbd801..41a2b7b678 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c index 23bedef644..4cede747f2 100644 --- a/tests/regression/75-recursion_termination/03-nested-terminating.c +++ b/tests/regression/75-recursion_termination/03-nested-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index d28685e139..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 2c7394861d6070f96e8287b24c1b94887e9dd608 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:42:29 +0200 Subject: [PATCH 168/628] Reformat --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 41a2b7b678..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 7f484cb2abf7f438313e7730951dfa1a73ebd928 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:43:41 +0200 Subject: [PATCH 169/628] Skip crashing tests --- .../74-loop_termination/09-complex-for-loop-terminating.c | 2 +- .../74-loop_termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index c26fde710f..7fb9262aab 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index 017c10b8a4..e39613b563 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 07fbe38cfd..ad64a9a5f9 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 2d3239f371..5299544a70 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From a91e716de0d7bcdce098b31babe6333ee32111dd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 13:45:31 +0200 Subject: [PATCH 170/628] Rename loop termination analysis --- src/analyses/{termination_new.ml => loop_termination.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/analyses/{termination_new.ml => loop_termination.ml} (100%) diff --git a/src/analyses/termination_new.ml b/src/analyses/loop_termination.ml similarity index 100% rename from src/analyses/termination_new.ml rename to src/analyses/loop_termination.ml From 8483cece62310439d56da7a373781ca74e9de848 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:06:34 +0200 Subject: [PATCH 171/628] Removed Todos --- tests/regression/74-loop_termination/17-goto-terminating.c | 2 +- .../74-loop_termination/23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- .../74-loop_termination/28-do-while-continue-terminating.c | 2 +- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index b11b5b3da9..1e4c1e719e 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 4b9aacd0fd..94e47d5d9a 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 3c4fffdc8a..e5c4f10f0d 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index 380e98ded0..ea353eb466 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index b676ca6985..8c2f3da4a2 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index aa215a502a..7f91ecc149 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 0526e20bb4..45cadb583f 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..26f30e726b 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 5299544a70..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 91f18efe32ca4f7ddc4c163d156b715e4e56685b Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:26:45 +0200 Subject: [PATCH 172/628] Adapted tests to current state --- tests/regression/74-loop_termination/17-goto-terminating.c | 4 ++-- .../74-loop_termination/23-exit-on-rand-terminating.c | 4 ++-- .../24-upjumping-goto-loopless-terminating.c | 4 ++-- .../74-loop_termination/25-leave-loop-goto-terminating.c | 4 ++-- .../74-loop_termination/26-enter-loop-goto-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index 1e4c1e719e..c4ba717784 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -11,7 +11,7 @@ int main() if (num <= 10) { - goto loop; + goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. } return 0; diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 94e47d5d9a..226f46b16e 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include @@ -6,7 +6,7 @@ int main() { int short_run, i = 0; - while (i < 90 && short_run != 1) + while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; if (rand()) diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e5c4f10f0d..e256df9986 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() { // Currently not able to detect this as terminating goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ea353eb466..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -13,7 +13,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 8c2f3da4a2..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -16,7 +16,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 45cadb583f..6b36919c2d 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { + if (j == 3) { // Apron is not able to detect this goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From 1c430398152499f9b7450100c563c2295a4f61e3 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:32:01 +0200 Subject: [PATCH 173/628] Adapted tests to current state --- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index cbbb115868..ce11a73060 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 17220a589b..355c1ebf00 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From c890d5b3cb9649a0a46eb505bbe56178f15f8aaf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:24:33 +0200 Subject: [PATCH 174/628] No skipping --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 8951924c06..7fcd5c5eba 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index dbce2a6b5b..def1786937 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 7daa9b98fe..9ab04745e8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index c7902e2e7f..37c4bbd801 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 569fefdc111e23eb159b51076e36de9c0be794e6 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:31:36 +0200 Subject: [PATCH 175/628] New non terminating for loop --- .../34-nested-for-loop-nonterminating.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/regression/80-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..1f68f3c0a5 --- /dev/null +++ b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} From aca1ec58c0a8cab65883b19ad963fdad6826b927 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:34:13 +0200 Subject: [PATCH 176/628] Folder Renaming --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../01-simple-terminating.c | 0 .../02-simple-nonterminating.c | 0 .../03-nested-terminating.c | 0 .../04-nested-nonterminating.c | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{80-termination => 74-loop_termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/05-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/11-loopless-termination.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/13-do-while-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/17-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/18-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/19-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/20-rand-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/32-multithread-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/01-simple-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/02-simple-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/03-nested-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/04-nested-nonterminating.c (100%) diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/01-simple-loop-terminating.c rename to tests/regression/74-loop_termination/01-simple-loop-terminating.c diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/02-simple-loop-nonterminating.c rename to tests/regression/74-loop_termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/03-nested-loop-terminating.c rename to tests/regression/74-loop_termination/03-nested-loop-terminating.c diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/04-nested-loop-nonterminating.c rename to tests/regression/74-loop_termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/05-for-loop-terminating.c rename to tests/regression/74-loop_termination/05-for-loop-terminating.c diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/06-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/06-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/07-nested-for-loop-terminating.c rename to tests/regression/74-loop_termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/08-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/09-complex-for-loop-terminating.c rename to tests/regression/74-loop_termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/10-complex-loop-terminating.c rename to tests/regression/74-loop_termination/10-complex-loop-terminating.c diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c similarity index 100% rename from tests/regression/80-termination/11-loopless-termination.c rename to tests/regression/74-loop_termination/11-loopless-termination.c diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/80-termination/12-do-while-instant-terminating.c rename to tests/regression/74-loop_termination/12-do-while-instant-terminating.c diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/80-termination/13-do-while-terminating.c rename to tests/regression/74-loop_termination/13-do-while-terminating.c diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/80-termination/14-do-while-nonterminating.c rename to tests/regression/74-loop_termination/14-do-while-nonterminating.c diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/80-termination/15-complex-loop-combination-terminating.c rename to tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/17-goto-terminating.c rename to tests/regression/74-loop_termination/17-goto-terminating.c diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/18-goto-nonterminating.c rename to tests/regression/74-loop_termination/18-goto-nonterminating.c diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/19-rand-terminating.c rename to tests/regression/74-loop_termination/19-rand-terminating.c diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/80-termination/20-rand-nonterminating.c rename to tests/regression/74-loop_termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/22-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/23-exit-on-rand-terminating.c rename to tests/regression/74-loop_termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/25-leave-loop-goto-terminating.c rename to tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/26-enter-loop-goto-terminating.c rename to tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/27-upjumping-goto-nonterminating.c rename to tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/80-termination/28-do-while-continue-terminating.c rename to tests/regression/74-loop_termination/28-do-while-continue-terminating.c diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/80-termination/29-do-while-continue-nonterminating.c rename to tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/80-termination/32-multithread-terminating.c rename to tests/regression/74-loop_termination/32-multithread-terminating.c diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/80-termination/33-multithread-nonterminating.c rename to tests/regression/74-loop_termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/34-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c similarity index 100% rename from tests/regression/81-recursion/01-simple-terminating.c rename to tests/regression/75-recursion_termination/01-simple-terminating.c diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/02-simple-nonterminating.c rename to tests/regression/75-recursion_termination/02-simple-nonterminating.c diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c similarity index 100% rename from tests/regression/81-recursion/03-nested-terminating.c rename to tests/regression/75-recursion_termination/03-nested-terminating.c diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/04-nested-nonterminating.c rename to tests/regression/75-recursion_termination/04-nested-nonterminating.c From 70bad4c386e3c7bbaa45ff3aec86e618901fd063 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:49:43 +0200 Subject: [PATCH 177/628] Enable polyhedra; Removed unnecessary TODOs --- .../15-complex-loop-combination-terminating.c | 2 +- .../74-loop_termination/34-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 9ab04745e8..ec6b50512e 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index 1f68f3c0a5..d8aa9d487d 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From e70761c567064f43ebdd1b36bf13e34621a4d50f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:04:25 +0200 Subject: [PATCH 178/628] Removed unnecessary TODOs --- .../regression/74-loop_termination/06-for-loop-nonterminating.c | 2 +- .../74-loop_termination/08-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index 73a8b8c6fd..b8f30361d1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 8b451e56dd..0368120b13 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From ee9392942d4df2d43cfab49e4002394b2d42fd33 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:17:23 +0200 Subject: [PATCH 179/628] Renamed LOCAL_TERM to TERM --- scripts/update_suite.rb | 26 +++++++++---------- .../01-simple-loop-terminating.c | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../03-nested-loop-terminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../05-for-loop-terminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../07-nested-for-loop-terminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 2 +- .../13-do-while-terminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../74-loop_termination/17-goto-terminating.c | 2 +- .../18-goto-nonterminating.c | 2 +- .../74-loop_termination/19-rand-terminating.c | 2 +- .../20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../28-do-while-continue-terminating.c | 2 +- .../29-do-while-continue-nonterminating.c | 2 +- .../30-goto-out-of-inner-loop-terminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 2 +- .../32-multithread-terminating.c | 2 +- .../33-multithread-nonterminating.c | 2 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../01-simple-terminating.c | 2 +- .../02-simple-nonterminating.c | 2 +- .../03-nested-terminating.c | 2 +- .../04-nested-nonterminating.c | 2 +- 39 files changed, 50 insertions(+), 52 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 98eff124af..8841ecea88 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,11 +145,11 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "non_local_term" end # Get NonTerminating warning + if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj when /\(conf\. \d+\)/ then "race" when /Deadlock/ then "deadlock" @@ -208,9 +208,9 @@ def compare_warnings case type when "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type - when "non_local_term" + when "nonterm" check.call warnings[idx] == type - when "nowarn", "local_term" + when "nowarn", "term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -324,19 +324,17 @@ def parse_tests (lines) case lines[0] when /TODO|SKIP/ case lines[0] - when /NON_LOCAL_TERM/ - tests[-1] = "non_local_term" + when /NONTERM/ + tests[-1] = "nonterm" todo << -1 - when /LOCAL_TERM/ - tests[-1] = "local_term" + when /TERM/ + tests[-1] = "term" todo << -1 end - when /NON_LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "non_local_term" - when /LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "local_term" + when /NONTERM/ + tests[-1] = "nonterm" + when /TERM/ + tests[-1] = "term" end Tests.new(self, tests, tests_line, todo) end diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c index a517d0d608..a80084868a 100644 --- a/tests/regression/74-loop_termination/01-simple-loop-terminating.c +++ b/tests/regression/74-loop_termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c index bcb9909f80..eef9f81ea3 100644 --- a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c index 366cbaeea5..5e72ec3284 100644 --- a/tests/regression/74-loop_termination/03-nested-loop-terminating.c +++ b/tests/regression/74-loop_termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..1fb5ada507 100644 --- a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c index 2a16184f6d..cf71fa5135 100644 --- a/tests/regression/74-loop_termination/05-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index b8f30361d1..8c1500cfb1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c index def0787d39..4b3395bd11 100644 --- a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 0368120b13..818146e456 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fcd5c5eba..c26fde710f 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index def1786937..017c10b8a4 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c index 86a300f18e..01f9a953e0 100644 --- a/tests/regression/74-loop_termination/11-loopless-termination.c +++ b/tests/regression/74-loop_termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c index 15032b7b4f..b34dff3f5f 100644 --- a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c +++ b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c index 2e04f3e393..651acb8fd8 100644 --- a/tests/regression/74-loop_termination/13-do-while-terminating.c +++ b/tests/regression/74-loop_termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c index 5ed18175e9..1e05e2be6e 100644 --- a/tests/regression/74-loop_termination/14-do-while-nonterminating.c +++ b/tests/regression/74-loop_termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ec6b50512e..07fbe38cfd 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..b9ccea76af 100644 --- a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index e988926359..b11b5b3da9 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c index cfe5ab481d..aab37803aa 100644 --- a/tests/regression/74-loop_termination/18-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c index 426c5cdcca..5d3cde9f3d 100644 --- a/tests/regression/74-loop_termination/19-rand-terminating.c +++ b/tests/regression/74-loop_termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c index 7c21538612..124a19d0f8 100644 --- a/tests/regression/74-loop_termination/20-rand-nonterminating.c +++ b/tests/regression/74-loop_termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..3bf479b6f9 100644 --- a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c index 1bc104258d..1f1a9bbd89 100644 --- a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 253d38c5df..4b9aacd0fd 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 01bffde383..3c4fffdc8a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index fed0e218ac..380e98ded0 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 2a43933758..b676ca6985 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c index a230827356..52ad7ea820 100644 --- a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 5989c61fed..aa215a502a 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c index 806456e887..896d8fea95 100644 --- a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 76c272a654..0526e20bb4 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c index c1824227d0..722694eb88 100644 --- a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c index a08fe01398..1f98b88eee 100644 --- a/tests/regression/74-loop_termination/32-multithread-terminating.c +++ b/tests/regression/74-loop_termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c index 77cd2aafe6..007af3b57b 100644 --- a/tests/regression/74-loop_termination/33-multithread-nonterminating.c +++ b/tests/regression/74-loop_termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index d8aa9d487d..29e4ff3835 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c index 4f09950025..583f8ccca1 100644 --- a/tests/regression/75-recursion_termination/01-simple-terminating.c +++ b/tests/regression/75-recursion_termination/01-simple-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 37c4bbd801..41a2b7b678 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c index 23bedef644..4cede747f2 100644 --- a/tests/regression/75-recursion_termination/03-nested-terminating.c +++ b/tests/regression/75-recursion_termination/03-nested-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index d28685e139..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From d05da3a797473c9ee813b331900513366d0e2a3a Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:42:29 +0200 Subject: [PATCH 180/628] Reformat --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 41a2b7b678..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 036dd175358dbdb2ef1748aed2ca253b28385d32 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:43:41 +0200 Subject: [PATCH 181/628] Skip crashing tests --- .../74-loop_termination/09-complex-for-loop-terminating.c | 2 +- .../74-loop_termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index c26fde710f..7fb9262aab 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index 017c10b8a4..e39613b563 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 07fbe38cfd..ad64a9a5f9 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 2d3239f371..5299544a70 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 4cb5da0fb3afca195cdad847f848dd15f0e3cded Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:06:34 +0200 Subject: [PATCH 182/628] Removed Todos --- tests/regression/74-loop_termination/17-goto-terminating.c | 2 +- .../74-loop_termination/23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- .../74-loop_termination/28-do-while-continue-terminating.c | 2 +- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index b11b5b3da9..1e4c1e719e 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 4b9aacd0fd..94e47d5d9a 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 3c4fffdc8a..e5c4f10f0d 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index 380e98ded0..ea353eb466 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index b676ca6985..8c2f3da4a2 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index aa215a502a..7f91ecc149 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 0526e20bb4..45cadb583f 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..26f30e726b 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 5299544a70..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From fec0d6266469ca2e114c606d7e7c4602018428f2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:26:45 +0200 Subject: [PATCH 183/628] Adapted tests to current state --- tests/regression/74-loop_termination/17-goto-terminating.c | 4 ++-- .../74-loop_termination/23-exit-on-rand-terminating.c | 4 ++-- .../24-upjumping-goto-loopless-terminating.c | 4 ++-- .../74-loop_termination/25-leave-loop-goto-terminating.c | 4 ++-- .../74-loop_termination/26-enter-loop-goto-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index 1e4c1e719e..c4ba717784 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -11,7 +11,7 @@ int main() if (num <= 10) { - goto loop; + goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. } return 0; diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 94e47d5d9a..226f46b16e 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include @@ -6,7 +6,7 @@ int main() { int short_run, i = 0; - while (i < 90 && short_run != 1) + while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; if (rand()) diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e5c4f10f0d..e256df9986 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() { // Currently not able to detect this as terminating goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ea353eb466..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -13,7 +13,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 8c2f3da4a2..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -16,7 +16,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 45cadb583f..6b36919c2d 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { + if (j == 3) { // Apron is not able to detect this goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From 68b01aff36092ad7727383249d81fe26cf4374a7 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:32:01 +0200 Subject: [PATCH 184/628] Adapted tests to current state --- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index cbbb115868..ce11a73060 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 17220a589b..355c1ebf00 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From b7c6ec5493b90eb400522f8663efad91b25e9ef4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:23:34 +0200 Subject: [PATCH 185/628] Restore apronAnalysis.apron.ml --- src/analyses/apron/apronAnalysis.apron.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index bec0c4ec57..29e295a662 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -4,7 +4,6 @@ open Analyses include RelationAnalysis - let spec_module: (module MCPSpec) Lazy.t = lazy ( let module Man = (val ApronDomain.get_manager ()) in @@ -35,8 +34,7 @@ let get_spec (): (module MCPSpec) = let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); - GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) - + GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) let _ = AfterConfig.register after_config From 432e92d7e1e542b63e38d52b84942f2a3470f7f8 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:39:48 +0200 Subject: [PATCH 186/628] Explicitly use () as the abstract local state --- src/analyses/loop_termination.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 7ecb11a12c..6aed200192 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -69,7 +69,7 @@ struct module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) - let startstate _ = D.bot () + let startstate _ = () let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = @@ -81,12 +81,12 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in - ctx.local - | _ -> ctx.local + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) - ctx.local + () (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From 29532421f232de013f95da615820af7e4d944a44 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:44:30 +0200 Subject: [PATCH 187/628] Change let-in clause to sequential statements --- src/analyses/loop_termination.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 6aed200192..1d6a7db262 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -80,7 +80,7 @@ struct (* TODO: Move to special *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); () | _ -> () From c2c69cf1bc3e8e6f8a9978d9769786a0f44669b1 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:17:01 +0200 Subject: [PATCH 188/628] Update src/framework/constraints.ml Make comment more precise Co-authored-by: Michael Schwarz --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ce3ecadc1e..ccee950a7d 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1695,7 +1695,7 @@ struct end -(** Add cycle detection in the function call graph to a analysis *) +(** Add cycle detection in the context-sensitive dynamic function call graph to an analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C From d18d8fe8a32a613ac7a0b4dc27c9d6747c2b9295 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:18:45 +0200 Subject: [PATCH 189/628] Update src/framework/constraints.ml Co-authored-by: Michael Schwarz --- src/framework/constraints.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ccee950a7d..bd65dd5ba4 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1709,10 +1709,7 @@ module RecursionTermLifter (S: Spec) struct include S - module V = - struct - include GVarF(S.V) - end + module V = GVarF(S.V) module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) From 0d77172c0933d6044c83cee065737200730277ac Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:22:29 +0200 Subject: [PATCH 190/628] Remove unnecessary semicola Co-authored-by: Michael Schwarz --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 6e29c48917..47a17575c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,7 +1,7 @@ open GoblintCil include Printf -module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) From 76230f473ef68c940f117d221393cfbf515a7505 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 18:31:30 +0200 Subject: [PATCH 191/628] Restore 01-simple-cases.c from white space change --- tests/regression/55-loop-unrolling/01-simple-cases.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index add8c6a8dd..0073717187 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -193,4 +193,4 @@ void example10(void) ++i; } return 0; -} \ No newline at end of file +} From 6e620417fd57bbdd6b7e9c05c6e7ad6b69bab4de Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 30 Jun 2023 11:05:32 +0200 Subject: [PATCH 192/628] adapted changes from pull request: 1. using a module for tuple; 2. deleted dublicated method; 3. removed the arg from the arg_termination variable --- src/framework/analyses.ml | 39 ------------------------------------ src/framework/constraints.ml | 12 +++++------ src/framework/control.ml | 4 ++-- 3 files changed, 8 insertions(+), 47 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1c3d596cc2..712399d619 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -118,38 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -(* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = -struct - include Printable.Std - type t = (Base1.t * Base2.t) - - let fundec (a,_) = a - let context (_,b) = b - let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false - let show (a,b) = (Base1.show a) ^ (Base2.show b) - let name () = "Tuple" - let to_yojson x = `String (show x) - let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = - BatPrintf.fprintf f "\n - Tuple:\n\n - caller_fundec\n%a\n\n - caller_context\n%a\n\n - \n" Base1.printXml a Base2.printXml b - - let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 - else( - let val_a a = if (a > 0) then 1 else -1 in - let val_b b = if (b > 0) then 3 else -3 in - val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) - ) - - let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) -end - module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = @@ -200,13 +168,6 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let s = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" - - let create_s s = `Lifted1 s - let base2 instance = match instance with | `Lifted2 n -> Some n diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index bd65dd5ba4..c60f84d5e8 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,24 +1711,24 @@ struct include S module V = GVarF(S.V) - module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) + module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) let name () = "termination" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with - global = (fun v -> G.s (ctx.global (V.spec v))); - sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); + global = (fun v -> G.spec (ctx.global (V.spec v))); + sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_spec g)); } let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let module LH = Hashtbl.Make (Printable.Prod (CilType.Fundec) (S.C)) in + let module LS = Set.Make (Printable.Prod (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = + let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; diff --git a/src/framework/control.ml b/src/framework/control.ml index 9a717e2f67..e408aab76a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,7 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in - let arg_termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) + let termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* 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 @@ -37,7 +37,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 arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + |> lift termination (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 9c8d1283e4e5ad9a1fc13c318d8dcb44e11b3d44 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 30 Jun 2023 11:38:20 +0200 Subject: [PATCH 193/628] changed the order in C_Printable --- src/framework/analyses.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 712399d619..9f25a67a0d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -133,8 +133,8 @@ struct (* Make the given module Goupable*) module C_Printable (C: Printable.S) = struct - include C include Printable.Std (* To make it Groupable *) + include C let printXml f c = BatPrintf.fprintf f "\n callee_context\n%a\n\n From c776d8cd82def2ba48f1402f179f7af90f092b94 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Sat, 1 Jul 2023 11:30:47 +0200 Subject: [PATCH 194/628] changed naming for SV-Comp specification from NoTermination to Termination, to meet naming conventions --- src/autoTune.ml | 2 +- src/witness/svcomp.ml | 2 +- src/witness/svcompSpec.ml | 8 ++++---- src/witness/witness.ml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 4fb8a1db5e..9468d1d366 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -216,7 +216,7 @@ let focusOnSpecification () = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | NoTermination -> () + | Termination -> () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index a164448210..2fcb32fff9 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -52,7 +52,7 @@ struct | UnreachCall _ -> "unreach-call" | NoOverflow -> "no-overflow" | NoDataRace -> "no-data-race" (* not yet in SV-COMP/Benchexec *) - | NoTermination -> "no-termination" + | Termination -> "termination" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index f8791d065e..946093bfc0 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -6,7 +6,7 @@ type t = | UnreachCall of string | NoDataRace | NoOverflow - | NoTermination + | Termination let of_string s = let s = String.strip s in @@ -17,8 +17,8 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "termination" then - NoTermination + else if global_not = "no-termination" then + Termination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -45,6 +45,6 @@ let to_string spec = | UnreachCall f -> "call(" ^ f ^ "())" | NoDataRace -> "data-race" | NoOverflow -> "overflow" - | NoTermination -> "termination" + | Termination -> "no-termination" in "CHECK( init(main()), LTL(G ! " ^ global_not ^ ") )" diff --git a/src/witness/witness.ml b/src/witness/witness.ml index b62b2b54cd..94ffea0a0a 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -442,7 +442,7 @@ struct in (module TaskResult:WitnessTaskResult) ) - | NoTermination -> (* TODO: implement this properly*) + | Termination -> (* TODO: implement this properly*) let module TrivialArg = struct include Arg From b1da8e26a684bbe03c0e60fc41a0ade7b0cd6414 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 2 Jul 2023 10:49:46 +0200 Subject: [PATCH 195/628] renamed termination in control to termination_enabled; added comment for global invariant in RecursionTermLifter --- src/framework/constraints.ml | 12 ++++++++---- src/framework/control.ml | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index c60f84d5e8..55763c5852 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1700,12 +1700,16 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C = -(*global invariants: +(* two global invariants: - V -> G + Needed to store the previously built global invariants - fundec -> Map (S.C) (Set (fundec * S.C)) - Therefore: - g -> {c' -> {(f, c)}} - in case f, c --> g, c' *) + The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + This structure therefore stores the context-sensitive call graph. + For example: + let the function f in context c call function g in context c'. + In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} +*) struct include S diff --git a/src/framework/control.ml b/src/framework/control.ml index e408aab76a..5bd815634c 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,7 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in - let termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) + let termination_enabled = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* 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 @@ -37,7 +37,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 (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + |> 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 1ace9d69f036db3878b5f449736775a41b9fba58 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:24:33 +0200 Subject: [PATCH 196/628] Add description to loop/goto termination analysis --- src/analyses/loop_termination.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 1d6a7db262..f066fbbab6 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -1,4 +1,4 @@ -(** Work in progress *) +(** Termination analysis for loops and [goto] statements ([termination]). *) open Analyses open GoblintCil From 30b03ce2fe2892272470d38898bc6e4297dc9ac4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:32:51 +0200 Subject: [PATCH 197/628] Introduce isEverMultiThreaded analysis Does not work properly yet. Need to fix query function. --- src/analyses/everMultiThreaded.ml | 46 +++++++++++++++++++++++++++++++ src/domains/queries.ml | 5 ++++ 2 files changed, 51 insertions(+) create mode 100644 src/analyses/everMultiThreaded.ml diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml new file mode 100644 index 0000000000..c98f173624 --- /dev/null +++ b/src/analyses/everMultiThreaded.ml @@ -0,0 +1,46 @@ +(** Work in progress *) + +open Analyses + +module UnitV = +struct + include Printable.Unit + include StdV +end + +module Spec : Analyses.MCPSpec = +struct + + (** Provides some default implementations *) + include Analyses.IdentitySpec + + let name () = "evermultithreaded" + + module D = Lattice.Unit + module C = D + module V = UnitV + module G = BoolDomain.MayBool + + let startstate _ = () + let exitstate = startstate + + (** Sets the global invariant to true when a thread is spawned *) + let threadspawn ctx lval f args fctx = + ctx.sideg () true; + () + + let query ctx (type a) (q: a Queries.t) : a Queries.result = + match q with + | Queries.IsEverMultiThreaded -> + (* + ctx.global () + *) + Queries.Result.top q (* TODO *) + | _ -> + Queries.Result.top q + +end + +let () = + (* Register this analysis within the master control program *) + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index c5d7d729b6..2810f07342 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,6 +119,7 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t + | IsEverMultiThreaded: MayBool.t t type 'a result = 'a @@ -185,6 +186,7 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) + | IsEverMultiThreaded -> (module MayBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -250,6 +252,7 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () + | IsEverMultiThreaded -> MayBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -312,6 +315,7 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 + | Any IsEverMultiThreaded -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -456,6 +460,7 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any IsEverMultiThreaded -> Pretty.dprintf "IsEverMultiThreaded" end let to_value_domain_ask (ask: ask) = From e8aec04aeb4f550ca4822efc20878ec33674cb60 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:59:34 +0200 Subject: [PATCH 198/628] Finish and use everMultiThreaded analysis Used by the termination analysis --- src/analyses/everMultiThreaded.ml | 9 +++++---- src/analyses/loop_termination.ml | 2 +- src/autoTune.ml | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml index c98f173624..5567ef1223 100644 --- a/src/analyses/everMultiThreaded.ml +++ b/src/analyses/everMultiThreaded.ml @@ -32,10 +32,11 @@ struct let query ctx (type a) (q: a Queries.t) : a Queries.result = match q with | Queries.IsEverMultiThreaded -> - (* - ctx.global () - *) - Queries.Result.top q (* TODO *) + (match ctx.global () with + (* I don't know why this wrapping in a match construct is necessary. + * Without it, the compiler throws an error. *) + true -> true + | false -> false) | _ -> Queries.Result.top q diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index f066fbbab6..4b658071be 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -91,7 +91,7 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = - ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + not (ctx.ask Queries.IsEverMultiThreaded) (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/autoTune.ml b/src/autoTune.ml index 9468d1d366..9c4fb8f742 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -180,7 +180,7 @@ let enableAnalyses anas = List.iter (GobConfig.set_auto "ana.activated[+]") anas (*If only one thread is used in the program, we can disable most thread analyses*) -(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access*) +(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> isEverMultiThreaded *) (*escape is also still enabled, because otherwise we get a warning*) (*does not consider dynamic calls!*) From f8fa8e314339abd704c07421570503ae45206948 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 13:35:45 +0200 Subject: [PATCH 199/628] Revert whitespace change --- src/cdomains/intDomain.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index df0a4c0507..589239810f 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -3263,7 +3263,6 @@ struct let refine_with_incl_list ik a b = a let project ik p t = t - end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct From 4f60156593453f3dac2e86a41b62ad03d0ad4509 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 3 Jul 2023 16:32:17 +0200 Subject: [PATCH 200/628] added missing __goblint_bounded implementations --- lib/goblint/runtime/include/goblint.h | 2 ++ lib/goblint/runtime/src/goblint.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/goblint/runtime/include/goblint.h b/lib/goblint/runtime/include/goblint.h index b0af41616e..3c1abae838 100644 --- a/lib/goblint/runtime/include/goblint.h +++ b/lib/goblint/runtime/include/goblint.h @@ -6,3 +6,5 @@ void __goblint_assume_join(/* pthread_t thread */); // undeclared argument to av void __goblint_split_begin(int exp); void __goblint_split_end(int exp); + +void __goblint_bounded(int exp); \ No newline at end of file diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index 39c18c5b8e..7929fcf37a 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -29,6 +29,6 @@ void __goblint_split_end(int exp) { } -void __goblint_bounded() { +void __goblint_bounded(int exp) { } \ No newline at end of file From 21f2f3428a6be6c62d3d89e794eecb143d7084e9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 16:38:11 +0200 Subject: [PATCH 201/628] Temp. revert must_be_single_threaded_since_start --- src/analyses/loop_termination.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 4b658071be..7341bcd349 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -91,7 +91,10 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = + (* not (ctx.ask Queries.IsEverMultiThreaded) + *) + ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 048de26d949bde76ebf5ffe597bde7654e675e21 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Wed, 5 Jul 2023 18:04:28 +0200 Subject: [PATCH 202/628] Patched inconsistency with nested loops --- runningGob.sh | 2 +- src/util/terminationPreprocessing.ml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/runningGob.sh b/runningGob.sh index fcb5417192..11173bee1f 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_loops="tests/regression/74-loop_termination/03-nested-loop-terminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 47a17575c4..4043c6d256 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -34,7 +34,10 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- inc_stmt :: check_stmt :: s :: inc_stmt2 :: ss; | ss -> b.bstmts <- inc_stmt :: check_stmt :: ss; ); From b67eacdbead591b054783c99dde36e1bdd391673 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 12:09:01 +0200 Subject: [PATCH 203/628] Rename loop termation analysis Keep camelCase naming convention --- src/analyses/{loop_termination.ml => loopTermination.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/analyses/{loop_termination.ml => loopTermination.ml} (100%) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loopTermination.ml similarity index 100% rename from src/analyses/loop_termination.ml rename to src/analyses/loopTermination.ml From 22efd120cd7f59b882b7a68a78b56e784cea96c3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 6 Jul 2023 12:10:27 +0200 Subject: [PATCH 204/628] changed name --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 55763c5852..d744937d53 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1717,7 +1717,7 @@ struct module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) - let name () = "termination" + let name () = "RecursionTermLifter (" ^ S.name () ^ ")" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with From c5fe485c0de7dbcfce0100f5819d7c2150a90c4e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 12:14:22 +0200 Subject: [PATCH 205/628] Remove unused code --- src/analyses/loopTermination.ml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 7341bcd349..d9f8df2f48 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,17 +6,6 @@ open TerminationPreprocessing exception PreProcessing of string -(* -let loop_heads () = - let module FileCfg = - struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) - end in - let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in - WitnessInvariant.loop_heads (* TODO: Unused *) -*) - (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty From b9a5c361cddce214db5217c3298cf68d56f200ee Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 12:53:58 +0200 Subject: [PATCH 206/628] Tests adapted and new test 74/35 --- .../09-complex-for-loop-terminating.c | 1 + .../10-complex-loop-terminating.c | 1 + .../15-complex-loop-combination-terminating.c | 1 + .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../28-do-while-continue-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 3 ++- ...out-of-inner-loop-with-print-terminating.c | 22 +++++++++++++++++++ .../02-simple-nonterminating.c | 2 +- 10 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fb9262aab..30ca32a70a 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index e39613b563..8970223c6e 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ad64a9a5f9..099203d13f 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e256df9986..1dc261d06a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { // Currently not able to detect this as terminating +int main() { // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ce11a73060..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 355c1ebf00..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 7f91ecc149..7756b51071 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -12,7 +12,7 @@ int main() if (i % 2 == 0) { printf("Skipping %i is even\n", i); - continue; + continue; // This is handled as an goto to line 8 and there an up-jumping goto } } while (i <= 5); diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 6b36919c2d..5662e31dc1 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -14,8 +14,9 @@ int main() { } printf("(%d, %d) ", i, j); } - printf("\n"); + printf("Not Skipped?\n"); outer_loop:; // Label for the outer loop + printf("Skipped!\n"); } return 0; diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c new file mode 100644 index 0000000000..b418257c56 --- /dev/null +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -0,0 +1,22 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { // Apron is not able to detect this + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + outer_loop:; // Label for the outer loop + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 26f30e726b..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 7e12cb506a8897f39f6549251883d3f6d663adae Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 12:56:06 +0200 Subject: [PATCH 207/628] Tests is now passing --- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 5662e31dc1..090f3830d5 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From bc7bef754340c0a35db3c15fc366c88959c150ce Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:14:18 +0200 Subject: [PATCH 208/628] Restrict boundedness checking to postsolving --- src/analyses/loopTermination.ml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index d9f8df2f48..00c7591ad2 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -62,16 +62,17 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + if !AnalysisState.postsolving then + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) From 08ad8d0595e52ef49643b1745a86b573468eafdc Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:27:58 +0200 Subject: [PATCH 209/628] Revert "Restrict boundedness checking to postsolving" This reverts commit bc7bef754340c0a35db3c15fc366c88959c150ce. --- src/analyses/loopTermination.ml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 00c7591ad2..d9f8df2f48 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -62,17 +62,16 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - if !AnalysisState.postsolving then - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) From 2e05e9e5710b9a70be84776527906e901ed3b7dd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:40:51 +0200 Subject: [PATCH 210/628] Restrict boundedness checking to postsolving (fix) --- src/analyses/loopTermination.ml | 39 ++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index d9f8df2f48..921aef28ee 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -36,7 +36,7 @@ let check_bounded ctx varinfo = module UnitV = struct include Printable.Unit - include StdV + let is_write_only _ = true end (** We want to record termination information of loops and use the loop @@ -62,20 +62,33 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + if !AnalysisState.postsolving then + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () + else () + (* let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = - (* TODO: Implement check for our special loop exit indicator function *) - () + (* TODO: Implement check for our special loop exit indicator function *) + if !AnalysisState.postsolving then + match f.vname, arglist with + "__goblint_bounded", [Lval (Var x, NoOffset)] -> + let () = print_endline "schpecial" in + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () + else () + *) (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From 0d79d2ace1a5d38931d8204e58a6e844637e96cf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 14:06:17 +0200 Subject: [PATCH 211/628] Widen recursion test --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..d20adea294 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) { From 1190d63212e2a887633438651e6b4844e6669340 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 14:23:36 +0200 Subject: [PATCH 212/628] Adapted test parameter --- .../30-goto-out-of-inner-loop-terminating.c | 2 +- .../35-goto-out-of-inner-loop-with-print-terminating.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 090f3830d5..15ce6e395e 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { // Apron is not able to detect this + if (j == 3) { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c index b418257c56..29a8033fdb 100644 --- a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { // Apron is not able to detect this + if (j == 3) { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From dbe3684a53f6a70367289673a95c9e2529f93b67 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 13:53:55 +0200 Subject: [PATCH 213/628] inlined Groupable C to Map --- runningGob.sh | 11 ++++++++--- src/framework/analyses.ml | 22 ++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 11173bee1f..61dbad53b6 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,12 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/74-loop_termination/03-nested-loop-terminating.c" +cfile_loop30="tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c" +cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c" +cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" +cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" +cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" +cfile_loop1="tests/regression/74-loop_termination/01-simple-loop-terminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" @@ -17,8 +22,8 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -#./goblint -v $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +./goblint $cfile_loop30 $options_term --enable justcil > output.txt +./goblint -v $cfile_loop30 $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8080 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 9f25a67a0d..faf7c456ca 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -130,20 +130,18 @@ struct BatPrintf.fprintf f "\n\n" end - (* Make the given module Goupable*) - module C_Printable (C: Printable.S) = - struct - include Printable.Std (* To make it Groupable *) - include C - let printXml f c = BatPrintf.fprintf f - "\n - callee_context\n%a\n\n - " printXml c - end - module CMap = struct - include MapDomain.MapBot (C_Printable (C)) (CSet) + include MapDomain.MapBot ( + struct + include Printable.Std (* To make it Groupable *) + include C + let printXml f c = BatPrintf.fprintf f + "\n + callee_context\n%a\n\n + " printXml c + end + ) (CSet) let printXml f c = BatPrintf.fprintf f " ContextTupleMap\n %a\n\n From 68bf1031e9efef23fb5605c79ae8473207b55bda Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 9 Jul 2023 17:05:53 +0200 Subject: [PATCH 214/628] Rename query MustTermProg to MustTermAllLoops I find the name MustTermProg confusing because it does not consider recursion. --- src/analyses/loopTermination.ml | 2 +- src/domains/queries.ml | 10 +++++----- src/framework/constraints.ml | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 921aef28ee..38823d3039 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -106,7 +106,7 @@ struct Some b -> b | None -> false) && must_be_single_threaded_since_start ctx - | Queries.MustTermProg -> + | Queries.MustTermAllLoops -> G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 2810f07342..8ff37b6d2c 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -118,7 +118,7 @@ type _ t = | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t - | MustTermProg: MustBool.t t + | MustTermAllLoops: MustBool.t t | IsEverMultiThreaded: MayBool.t t type 'a result = 'a @@ -185,7 +185,7 @@ struct | MayBeTainted -> (module LS) | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) - | MustTermProg -> (module MustBool) + | MustTermAllLoops -> (module MustBool) | IsEverMultiThreaded -> (module MayBool) (** Get bottom result for query. *) @@ -251,7 +251,7 @@ struct | MayBeTainted -> LS.top () | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () - | MustTermProg -> MustBool.top () + | MustTermAllLoops -> MustBool.top () | IsEverMultiThreaded -> MayBool.top () end @@ -314,7 +314,7 @@ struct | Any ThreadCreateIndexedNode -> 51 | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 - | Any MustTermProg -> 54 + | Any MustTermAllLoops -> 54 | Any IsEverMultiThreaded -> 55 let rec compare a b = @@ -459,7 +459,7 @@ struct | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s - | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any MustTermAllLoops -> Pretty.dprintf "MustTermAllLoops" | Any IsEverMultiThreaded -> Pretty.dprintf "IsEverMultiThreaded" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 55763c5852..27edc4f520 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1701,13 +1701,13 @@ module RecursionTermLifter (S: Spec) and module C = S.C = (* two global invariants: - - V -> G - Needed to store the previously built global invariants - - fundec -> Map (S.C) (Set (fundec * S.C)) - The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. - This structure therefore stores the context-sensitive call graph. - For example: - let the function f in context c call function g in context c'. + - V -> G + Needed to store the previously built global invariants + - fundec -> Map (S.C) (Set (fundec * S.C)) + The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + This structure therefore stores the context-sensitive call graph. + For example: + let the function f in context c call function g in context c'. In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} *) @@ -1769,7 +1769,7 @@ struct match q with | WarnGlobal v -> (* check result of loop analysis *) - if not (ctx.ask Queries.MustTermProg) then + if not (ctx.ask Queries.MustTermAllLoops) then (AnalysisState.svcomp_may_not_terminate := true; let msgs = [ From fbc2966201c3af0648d36c71b1e09f7597a7a791 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 18:16:57 +0200 Subject: [PATCH 215/628] Test moved and renamed --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{74-loop_termination => 75-termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{74-loop_termination => 75-termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../35-goto-out-of-inner-loop-with-print-terminating.c | 0 .../36-recursion-terminating.c} | 0 .../37-recursion-nonterminating.c} | 0 .../38-recursion-nested-terminating.c} | 0 .../39-recursion-nested-nonterminating.c} | 0 39 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{74-loop_termination => 75-termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/05-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/11-loopless-termination.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/13-do-while-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/17-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/18-goto-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/19-rand-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/20-rand-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/32-multithread-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/35-goto-out-of-inner-loop-with-print-terminating.c (100%) rename tests/regression/{75-recursion_termination/01-simple-terminating.c => 75-termination/36-recursion-terminating.c} (100%) rename tests/regression/{75-recursion_termination/02-simple-nonterminating.c => 75-termination/37-recursion-nonterminating.c} (100%) rename tests/regression/{75-recursion_termination/03-nested-terminating.c => 75-termination/38-recursion-nested-terminating.c} (100%) rename tests/regression/{75-recursion_termination/04-nested-nonterminating.c => 75-termination/39-recursion-nested-nonterminating.c} (100%) diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/01-simple-loop-terminating.c rename to tests/regression/75-termination/01-simple-loop-terminating.c diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/02-simple-loop-nonterminating.c rename to tests/regression/75-termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/03-nested-loop-terminating.c rename to tests/regression/75-termination/03-nested-loop-terminating.c diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/04-nested-loop-nonterminating.c rename to tests/regression/75-termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/05-for-loop-terminating.c rename to tests/regression/75-termination/05-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/06-for-loop-nonterminating.c rename to tests/regression/75-termination/06-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/07-nested-for-loop-terminating.c rename to tests/regression/75-termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c rename to tests/regression/75-termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/09-complex-for-loop-terminating.c rename to tests/regression/75-termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/10-complex-loop-terminating.c rename to tests/regression/75-termination/10-complex-loop-terminating.c diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c similarity index 100% rename from tests/regression/74-loop_termination/11-loopless-termination.c rename to tests/regression/75-termination/11-loopless-termination.c diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/12-do-while-instant-terminating.c rename to tests/regression/75-termination/12-do-while-instant-terminating.c diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/13-do-while-terminating.c rename to tests/regression/75-termination/13-do-while-terminating.c diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/14-do-while-nonterminating.c rename to tests/regression/75-termination/14-do-while-nonterminating.c diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c rename to tests/regression/75-termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/17-goto-terminating.c rename to tests/regression/75-termination/17-goto-terminating.c diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/18-goto-nonterminating.c rename to tests/regression/75-termination/18-goto-nonterminating.c diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/19-rand-terminating.c rename to tests/regression/75-termination/19-rand-terminating.c diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/20-rand-nonterminating.c rename to tests/regression/75-termination/20-rand-nonterminating.c diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/75-termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c rename to tests/regression/75-termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/23-exit-on-rand-terminating.c rename to tests/regression/75-termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c rename to tests/regression/75-termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c rename to tests/regression/75-termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c rename to tests/regression/75-termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/28-do-while-continue-terminating.c rename to tests/regression/75-termination/28-do-while-continue-terminating.c diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c rename to tests/regression/75-termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/32-multithread-terminating.c rename to tests/regression/75-termination/32-multithread-terminating.c diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/33-multithread-nonterminating.c rename to tests/regression/75-termination/33-multithread-nonterminating.c diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c rename to tests/regression/75-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c rename to tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c similarity index 100% rename from tests/regression/75-recursion_termination/01-simple-terminating.c rename to tests/regression/75-termination/36-recursion-terminating.c diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c similarity index 100% rename from tests/regression/75-recursion_termination/02-simple-nonterminating.c rename to tests/regression/75-termination/37-recursion-nonterminating.c diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c similarity index 100% rename from tests/regression/75-recursion_termination/03-nested-terminating.c rename to tests/regression/75-termination/38-recursion-nested-terminating.c diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c similarity index 100% rename from tests/regression/75-recursion_termination/04-nested-nonterminating.c rename to tests/regression/75-termination/39-recursion-nested-nonterminating.c From 4a6714c1662a26f4aa639c2203bc3c65512f0c88 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 18:18:48 +0200 Subject: [PATCH 216/628] added comments to explain why test 74/28 does fail and why 30 and 35 might behave differently; also restructured module G in the recursionTermLifter --- src/framework/analyses.ml | 54 -------------- src/framework/constraints.ml | 74 +++++++++++++++++-- .../28-do-while-continue-terminating.c | 72 ++++++++++++++++++ .../30-goto-out-of-inner-loop-terminating.c | 8 ++ ...out-of-inner-loop-with-print-terminating.c | 12 +++ 5 files changed, 160 insertions(+), 60 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index faf7c456ca..cd611a9faf 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -118,60 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = -struct - module CSet = - struct - include SetDomain.Make (Base) (* Set of Tuples*) - let name () = "contexts" - let printXml f a = - BatPrintf.fprintf f "\n"; - iter (Base.printXml f) a; - BatPrintf.fprintf f "\n\n" - end - - module CMap = - struct - include MapDomain.MapBot ( - struct - include Printable.Std (* To make it Groupable *) - include C - let printXml f c = BatPrintf.fprintf f - "\n - callee_context\n%a\n\n - " printXml c - end - ) (CSet) - let printXml f c = BatPrintf.fprintf f " - ContextTupleMap\n - %a\n\n - " printXml c - end - - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarGSet.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarGSet.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - - let base2 instance = - match instance with - | `Lifted2 n -> Some n - | _ -> None -end - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d744937d53..047bdf7e38 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1713,9 +1713,71 @@ module RecursionTermLifter (S: Spec) struct include S + + (* contains all the callee fundecs*) module V = GVarF(S.V) - module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) + (* Tuple containing the fundec and context of the caller *) + module CallGraphTuple = + struct + include Printable.Prod (CilType.Fundec) (S.C) + end + + (* Set containing multiple caller tuples *) + module CallGraphSet = + struct + include SetDomain.Make (CallGraphTuple) + let name () = "callerInfo" + let printXml f a = + BatPrintf.fprintf f "\n"; + iter (CallGraphTuple.printXml f) a; + BatPrintf.fprintf f "\n\n" + end + + (* Mapping from the callee context to the set of all caller tuples*) + module CallGraphMap = + struct + include MapDomain.MapBot ( + struct + include Printable.Std (* To make it Groupable *) + include S.C + let printXml f c = BatPrintf.fprintf f + "\n + callee_context\n%a\n\n + " printXml c + end + ) (CallGraphSet) + let printXml f c = BatPrintf.fprintf f " + ContextTupleMap\n + %a\n\n + " printXml c + end + + module G = + struct + include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) + + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTermLifter.spec" + let callGraph = function + | `Bot -> CallGraphMap.bot () + | `Lifted2 x -> x + | _ -> failwith "RecursionTermLifter.callGraph" + let create_spec spec = `Lifted1 spec + let create_callGraph callGraph = `Lifted2 callGraph + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let base2 instance = + match instance with + | `Lifted2 n -> Some n + | _ -> None + end let name () = "RecursionTermLifter (" ^ S.name () ^ ")" @@ -1749,8 +1811,8 @@ struct let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in - G.CSet.iter (fun to_call -> + let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in + CallGraphSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) @@ -1759,7 +1821,7 @@ struct try let gmap_opt = G.base2 (ctx.global (v)) in let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> + CallGraphMap.iter(fun key value -> let call = (v', key) in iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) @@ -1802,7 +1864,7 @@ struct *) let side_context sideg f c t = if !AnalysisState.postsolving then - sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) + sideg (V.contexts f) (G.create_callGraph (CallGraphMap.singleton (c) (t))) let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) @@ -1816,7 +1878,7 @@ struct let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let t = CallGraphSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 7756b51071..f05fa4f315 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -19,3 +19,75 @@ int main() printf("Exited the loop\n"); return 0; } + +/* +NOTE: +Test 28: does not terminate but should terminate (test case "28-do-while-continue-terminating.c") +Reason: upjumping goto + +If one has a look at the generated CIL output (attached at the bottom of this file), one can see that the "continue" is +translated in a "goto" with a corresponding label "__Cont". This label points to the loop-exit condition. Since the condition +is part of the loop, its location is evaluated to 8-17. +The location of the goto "goto __Cont" is located in line 15. +To provide soundness for the analysis, the preprocessing detects upjumping gotos with the help of its location. +In case such a goto is detected, the program is classified as non-terminating. +Due to this inserted goto (which is a result of the "continue"), an upjumping goto is located, which makes this program non-terminating. + +It should be noted that this issue happens when "do while"-loops and "continues" are combined. +If one combines "while"-loops and "continues", the analysis can still classify the loop as terminating. +The reason for that can be seen in the second CIL output, where the "do while"-loop is replaced by a "while"-loop. +Instead of creating a new label, the "while-continue" label of the loop is reused. Also, this goto statement is not specified as a goto, +but as a Continue statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". + + +------------------- SHORTENED CIL output for Test 28 (DO WHILE): ------------------- +int main(void) +{{{{ + #line 8 + while (1) { + while_continue: ; + #line 12 + if (i % 2 == 0) { + #line 15 + goto __Cont; + } + __Cont: + #line 8 + if (! (i <= 5)) { + #line 8 + goto while_break; + } + } + + while_break: + }} + #line 20 + return (0); +}} + + +------------------- SHORTENED CIL output for Test 28 (WHILE): ------------------- +Test 28: replacing DO WHILE with WHILE: +int main(void) +{{{{ + #line 8 + while (1) { + while_continue: ; + #line 8 + if (! (i <= 5)) { + #line 8 + goto while_break; + } + #line 12 + if (i % 2 == 0) { + #line 15 + goto while_continue; + } + } + while_break: ; + }} + #line 20 + return (0); +}} + +*/ diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 15ce6e395e..a92dcd2bc8 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -21,3 +21,11 @@ int main() { return 0; } + +/* +NOTE: In case we do NOT assume no-overflow: +Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") +Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") + +The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" +*/ diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c index 29a8033fdb..bb8bbacbf0 100644 --- a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -20,3 +20,15 @@ int main() { return 0; } + +/* +NOTE: In case we do NOT assume no-overflow: +Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") +Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") + +The only difference between Test 30 and Test 35 is line 17. Test 30 has an additional statement, and Test 35 continues already with the label. +This difference in Test 35 leads to an overflow in line 11, and hence to the non-termination. +This overflow is created by a WPoint Issue. By enabling the no-overflow option this issue can be fixed and, both test cases are correctly detected as terminating. + +(The overflow also happens without the termination analysis enabled.) +*/ From cb13d1497b77e26595bac26017afb5ec627bd39c Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 18:25:33 +0200 Subject: [PATCH 217/628] Tests moved --- .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{75-termination => 76-termination-complex-cases}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{75-termination => 76-termination-complex-cases}/10-complex-loop-terminating.c (100%) rename tests/regression/{75-termination => 76-termination-complex-cases}/15-complex-loop-combination-terminating.c (100%) diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/75-termination/09-complex-for-loop-terminating.c rename to tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/75-termination/10-complex-loop-terminating.c rename to tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/75-termination/15-complex-loop-combination-terminating.c rename to tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c From c6e36e4cbad76128d5a1de1eb601e74653bbdd7a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 18:39:11 +0200 Subject: [PATCH 218/628] cleaned module G from an unnecessary function; addded missing comment to analysisState --- src/framework/analysisState.ml | 2 +- src/framework/constraints.ml | 40 +++++++++++++--------------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index 3f577d79f4..c2d977af9c 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,7 +7,7 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false -(** TODO:**) +(** Whether the termination analysis detectes the program as non-terminating**) let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6aa0fc01e2..e99f39bd8f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1773,10 +1773,6 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let base2 instance = - match instance with - | `Lifted2 n -> Some n - | _ -> None end let name () = "RecursionTermLifter (" ^ S.name () ^ ")" @@ -1797,35 +1793,29 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - AnalysisState.svcomp_may_not_terminate := true; + AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in - M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) + M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin - try - LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in - let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in - CallGraphSet.iter (fun to_call -> - iter_call new_path_visited_calls to_call - ) callers; - with Invalid_argument _ -> () (* path ended: no cycle*) + LH.replace global_visited_calls call (); + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap = G.callGraph (ctx.global (fundec_e_typeV)) in + let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in + CallGraphSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers; end in - try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - CallGraphMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () (* path ended: no cycle*) + let gmap = G.callGraph (ctx.global (v)) in + CallGraphMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with From 9d6684666060ffc5d5bb9d427a3da846c60040b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 20:09:08 +0200 Subject: [PATCH 219/628] Complex test adapted --- .../09-complex-for-loop-terminating.c | 23 +---------- .../10-complex-loop-terminating.c | 14 +------ .../15-complex-loop-combination-terminating.c | 37 +----------------- .../75-termination/40-complex-conditions.c | 39 +++++++++++++++++++ .../regression/75-termination/41-more-tests.c | 30 ++++++++++++++ 5 files changed, 72 insertions(+), 71 deletions(-) rename tests/regression/{76-termination-complex-cases => 75-termination}/09-complex-for-loop-terminating.c (73%) rename tests/regression/{76-termination-complex-cases => 75-termination}/10-complex-loop-terminating.c (84%) rename tests/regression/{76-termination-complex-cases => 75-termination}/15-complex-loop-combination-terminating.c (68%) create mode 100644 tests/regression/75-termination/40-complex-conditions.c create mode 100644 tests/regression/75-termination/41-more-tests.c diff --git a/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c similarity index 73% rename from tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c rename to tests/regression/75-termination/09-complex-for-loop-terminating.c index 30ca32a70a..90591c7554 100644 --- a/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -76,27 +76,6 @@ int main() } printf("\n"); - // Loop with a continue statement - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - continue; - } - printf("%d ", i); - } - printf("\n"); - - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - } - printf("\n"); - // Loop with multiple variables int a, b, c; for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) diff --git a/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c similarity index 84% rename from tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c rename to tests/regression/75-termination/10-complex-loop-terminating.c index 8970223c6e..e33139cced 100644 --- a/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -108,18 +108,6 @@ int main() } printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - i++; - } - printf("\n"); - // Loop with multiple variables int a = 1; int b = 2; diff --git a/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c similarity index 68% rename from tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c rename to tests/regression/75-termination/15-complex-loop-combination-terminating.c index 099203d13f..64afaf30e1 100644 --- a/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -88,31 +88,6 @@ int main() n++; } - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); - } - - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } - - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } - // Loop with nested conditions for (int v = 1; v <= 10; v++) { @@ -131,15 +106,5 @@ int main() } } - // Loop with a label and goto statement - int w = 1; -start: - if (w <= 5) - { - printf("Loop with Label and Goto: %d\n", w); - w++; - goto start; - } - return 0; } diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c new file mode 100644 index 0000000000..2f342e89a0 --- /dev/null +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -0,0 +1,39 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int i; + + // Loop with a continue statement + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); +} \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c new file mode 100644 index 0000000000..112f95c3ee --- /dev/null +++ b/tests/regression/75-termination/41-more-tests.c @@ -0,0 +1,30 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + } \ No newline at end of file From 09ee872f53413b4a7f0790bd2b58735878a8b5e1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 08:37:51 +0200 Subject: [PATCH 220/628] moved warnings to loop analysis --- src/analyses/loopTermination.ml | 16 ++++++++++++++++ src/framework/constraints.ml | 8 +------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 38823d3039..ecb48a5284 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,6 +61,17 @@ struct let startstate _ = () let exitstate = startstate + let finalize () = + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + () + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -71,6 +82,11 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created*) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () else () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e99f39bd8f..6114f30adb 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1822,13 +1822,7 @@ struct | WarnGlobal v -> (* check result of loop analysis *) if not (ctx.ask Queries.MustTermAllLoops) then - (AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs - ); + AnalysisState.svcomp_may_not_terminate := true; let v: V.t = Obj.obj v in begin match v with | `Left v' -> From d6c11b63f8896d00c7eb14958b306efdc1536098 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 14:34:01 +0200 Subject: [PATCH 221/628] Test refactoring & parameter correction --- .../01-simple-loop-terminating.c | 18 +- .../02-simple-loop-nonterminating.c | 14 +- .../03-nested-loop-terminating.c | 37 ++-- .../04-nested-loop-nonterminating.c | 29 ++- .../75-termination/05-for-loop-terminating.c | 16 +- .../06-for-loop-nonterminating.c | 10 +- .../07-nested-for-loop-terminating.c | 25 +-- .../08-nested-for-loop-nonterminating.c | 23 +-- .../09-complex-for-loop-terminating.c | 122 +++++------ .../10-complex-loop-terminating.c | 190 ++++++++---------- .../75-termination/11-loopless-termination.c | 6 +- .../12-do-while-instant-terminating.c | 18 +- .../75-termination/13-do-while-terminating.c | 20 +- .../14-do-while-nonterminating.c | 20 +- .../15-complex-loop-combination-terminating.c | 166 +++++++-------- ...16-nested-loop-nontrivial-nonterminating.c | 29 ++- .../75-termination/17-goto-terminating.c | 21 +- .../75-termination/18-goto-nonterminating.c | 15 +- .../75-termination/19-rand-terminating.c | 38 ++-- .../75-termination/20-rand-nonterminating.c | 36 ++-- .../21-no-exit-on-rand-unproofable.c | 26 +-- .../22-exit-on-rand-unproofable.c | 18 +- .../23-exit-on-rand-terminating.c | 23 +-- .../24-upjumping-goto-loopless-terminating.c | 16 +- .../25-leave-loop-goto-terminating.c | 28 +-- .../26-enter-loop-goto-terminating.c | 32 +-- .../27-upjumping-goto-nonterminating.c | 18 +- .../28-do-while-continue-terminating.c | 76 +++---- .../29-do-while-continue-nonterminating.c | 28 ++- .../30-goto-out-of-inner-loop-terminating.c | 39 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 32 +-- .../32-multithread-terminating.c | 34 ++-- .../33-multithread-nonterminating.c | 53 ++--- .../34-nested-for-loop-nonterminating.c | 23 +-- ...out-of-inner-loop-with-print-terminating.c | 44 ++-- .../75-termination/36-recursion-terminating.c | 24 +-- .../37-recursion-nonterminating.c | 24 +-- .../38-recursion-nested-terminating.c | 40 ++-- .../39-recursion-nested-nonterminating.c | 24 +-- .../75-termination/40-complex-conditions.c | 52 +++-- .../regression/75-termination/41-more-tests.c | 44 ++-- 41 files changed, 718 insertions(+), 833 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index a80084868a..66b6585f67 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,15 +1,13 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - while (i <= 10) - { - printf("%d\n", i); - i++; - } + while (i <= 10) { + printf("%d\n", i); + i++; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index eef9f81ea3..6fe8816da4 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,12 +1,10 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - while (1) - { - continue; - } +int main() { + while (1) { + continue; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 5e72ec3284..4e3fafabcf 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,27 +1,24 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int rows = 3; - int columns = 4; - int i = 1; +int main() { + int rows = 3; + int columns = 4; + int i = 1; - // Outer while loop for rows - while (i <= rows) - { - int j = 1; + // Outer while loop for rows + while (i <= rows) { + int j = 1; - // Inner while loop for columns - while (j <= columns) - { - printf("(%d, %d) ", i, j); - j++; - } - - printf("\n"); - i++; + // Inner while loop for columns + while (j <= columns) { + printf("(%d, %d) ", i, j); + j++; } - return 0; + printf("\n"); + i++; + } + + return 0; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 1fb5ada507..00c2554ed2 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,23 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount = 1; +int main() { + int outerCount = 1; - while (outerCount <= 3) - { - int innerCount = 1; + while (outerCount <= 3) { + int innerCount = 1; - while (1) - { - printf("(%d, %d) ", outerCount, innerCount); - innerCount++; - } - - printf("\n"); - outerCount++; + while (1) { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; } - return 0; + printf("\n"); + outerCount++; + } + + return 0; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index cf71fa5135..fe07200e5b 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,14 +1,12 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i; +int main() { + int i; - for (i = 1; i <= 10; i++) - { - printf("%d\n", i); - } + for (i = 1; i <= 10; i++) { + printf("%d\n", i); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 8c1500cfb1..374cd3e59f 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,10 +1,10 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - for (;;) { - printf("This loop does not terminate.\n"); - } + for (;;) { + printf("This loop does not terminate.\n"); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index 4b3395bd11..a94f3f360c 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,20 +1,17 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int rows = 3; - int columns = 4; +int main() { + int rows = 3; + int columns = 4; - // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) - { - for (int j = 1; j <= columns; j++) - { - printf("(%d, %d) ", i, j); - } - printf("\n"); + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) { + for (int j = 1; j <= columns; j++) { + printf("(%d, %d) ", i, j); } + printf("\n"); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index 818146e456..e78e819cc0 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,19 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount, innerCount; +int main() { + int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) - { - for (innerCount = 1;; innerCount++) - { - printf("(%d, %d) ", outerCount, innerCount); - } - - printf("\n"); + for (outerCount = 1; outerCount <= 3; outerCount++) { + for (innerCount = 1;; innerCount++) { + printf("(%d, %d) ", outerCount, innerCount); } - return 0; + printf("\n"); + } + + return 0; } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 90591c7554..018fba6822 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,87 +1,67 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - int i, j, k; +int main() { + int i, j, k; - // Outer loop - for (i = 1; i <= 5; i++) - { - // Inner loop 1 - for (j = 1; j <= i; j++) - { - printf("%d ", j); - } - printf("\n"); - - // Inner loop 2 - for (k = i; k >= 1; k--) - { - printf("%d ", k); - } - printf("\n"); + // Outer loop + for (i = 1; i <= 5; i++) { + // Inner loop 1 + for (j = 1; j <= i; j++) { + printf("%d ", j); } + printf("\n"); - // Additional loop - for (i = 5; i >= 1; i--) - { - for (j = i; j >= 1; j--) - { - printf("%d ", j); - } - printf("\n"); + // Inner loop 2 + for (k = i; k >= 1; k--) { + printf("%d ", k); } + printf("\n"); + } - // Loop with conditions - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - printf("%d is even\n", i); - } - else - { - printf("%d is odd\n", i); - } + // Additional loop + for (i = 5; i >= 1; i--) { + for (j = i; j >= 1; j--) { + printf("%d ", j); } + printf("\n"); + } - // Loop with nested conditions - for (i = 1; i <= 10; i++) - { - printf("Number: %d - ", i); - if (i < 5) - { - printf("Less than 5\n"); - } - else if (i > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } + // Loop with conditions + for (i = 1; i <= 10; i++) { + if (i % 2 == 0) { + printf("%d is even\n", i); + } else { + printf("%d is odd\n", i); } + } - // Loop with a break statement - for (i = 1; i <= 10; i++) - { - printf("%d ", i); - if (i == 5) - { - break; - } + // Loop with nested conditions + for (i = 1; i <= 10; i++) { + printf("Number: %d - ", i); + if (i < 5) { + printf("Less than 5\n"); + } else if (i > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } - printf("\n"); + } - // Loop with multiple variables - int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) - { - printf("%d %d %d\n", a, b, c); + // Loop with a break statement + for (i = 1; i <= 10; i++) { + printf("%d ", i); + if (i == 5) { + break; } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + printf("%d %d %d\n", a, b, c); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index e33139cced..88bf6a4565 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,124 +1,102 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - int i = 1; - int j = 1; - int k = 5; +int main() { + int i = 1; + int j = 1; + int k = 5; - // Outer while loop - while (i <= 5) - { - // Inner while loop 1 - while (j <= i) - { - printf("%d ", j); - j++; - } - printf("\n"); - j = 1; - - // Inner while loop 2 - while (k >= 1) - { - printf("%d ", k); - k--; - } - printf("\n"); - k = 5; - - i++; + // Outer while loop + while (i <= 5) { + // Inner while loop 1 + while (j <= i) { + printf("%d ", j); + j++; } + printf("\n"); + j = 1; - // Additional while loop - i = 5; - while (i >= 1) - { - j = i; - while (j >= 1) - { - printf("%d ", j); - j--; - } - printf("\n"); - i--; + // Inner while loop 2 + while (k >= 1) { + printf("%d ", k); + k--; } + printf("\n"); + k = 5; + + i++; + } - // Loop with conditions - i = 1; - while (i <= 10) - { - if (i % 2 == 0) - { - printf("%d is even\n", i); - } - else - { - printf("%d is odd\n", i); - } - i++; + // Additional while loop + i = 5; + while (i >= 1) { + j = i; + while (j >= 1) { + printf("%d ", j); + j--; } + printf("\n"); + i--; + } - // Loop with nested conditions - i = 1; - while (i <= 10) - { - printf("Number: %d - ", i); - if (i < 5) - { - printf("Less than 5\n"); - } - else if (i > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - i++; + // Loop with conditions + i = 1; + while (i <= 10) { + if (i % 2 == 0) { + printf("%d is even\n", i); + } else { + printf("%d is odd\n", i); } + i++; + } - // Loop with a break statement - i = 1; - while (i <= 10) - { - printf("%d ", i); - if (i == 5) - { - break; - } - i++; + // Loop with nested conditions + i = 1; + while (i <= 10) { + printf("Number: %d - ", i); + if (i < 5) { + printf("Less than 5\n"); + } else if (i > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } - printf("\n"); + i++; + } - // Loop with a continue statement - i = 1; - while (i <= 10) - { - if (i % 2 == 0) - { - i++; - continue; - } - printf("%d ", i); - i++; + // Loop with a break statement + i = 1; + while (i <= 10) { + printf("%d ", i); + if (i == 5) { + break; } - printf("\n"); + i++; + } + printf("\n"); - // Loop with multiple variables - int a = 1; - int b = 2; - int c = 3; - while (a <= 10) - { - printf("%d %d %d\n", a, b, c); - a++; - b += 2; - c += 3; + // Loop with a continue statement + i = 1; + while (i <= 10) { + if (i % 2 == 0) { + i++; + continue; } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index 01f9a953e0..a1846905fc 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - printf("Terminating code without a loop\n"); - return 0; + printf("Terminating code without a loop\n"); + return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index b34dff3f5f..087b88f1f5 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,15 +1,13 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 0; +int main() { + int i = 0; - do - { - printf("Inside the do-while loop\n"); - } while (i > 0); + do { + printf("Inside the do-while loop\n"); + } while (i > 0); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 651acb8fd8..34343d6ba6 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,16 +1,14 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; - } while (i <= 5); + do { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 1e05e2be6e..6473fdc20d 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,16 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; - } while (i >= 2); + do { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 64afaf30e1..23282d24b1 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,110 +1,90 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - // Non-nested loops - int i; +int main() { + // Non-nested loops + int i; - // for loop - for (i = 1; i <= 10; i++) - { - printf("For loop iteration: %d\n", i); - } + // for loop + for (i = 1; i <= 10; i++) { + printf("For loop iteration: %d\n", i); + } - // while loop - int j = 1; - while (j <= 10) - { - printf("While loop iteration: %d\n", j); - j++; - } + // while loop + int j = 1; + while (j <= 10) { + printf("While loop iteration: %d\n", j); + j++; + } - // do-while loop - int k = 1; - do - { - printf("Do-While loop iteration: %d\n", k); - k++; - } while (k <= 10); + // do-while loop + int k = 1; + do { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); - // Nested loops - int a, b; + // Nested loops + int a, b; - // Nested for and while loop - for (a = 1; a <= 5; a++) - { - int c = 1; - while (c <= a) - { - printf("Nested For-While loop: %d\n", c); - c++; - } + // Nested for and while loop + for (a = 1; a <= 5; a++) { + int c = 1; + while (c <= a) { + printf("Nested For-While loop: %d\n", c); + c++; } + } - // Nested while and do-while loop - int x = 1; - while (x <= 5) - { - int y = 1; - do - { - printf("Nested While-Do-While loop: %d\n", y); - y++; - } while (y <= x); - x++; - } + // Nested while and do-while loop + int x = 1; + while (x <= 5) { + int y = 1; + do { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } - // Nested do-while and for loop - int p = 1; - do - { - for (int q = 1; q <= p; q++) - { - printf("Nested Do-While-For loop: %d\n", q); - } - p++; - } while (p <= 5); + // Nested do-while and for loop + int p = 1; + do { + for (int q = 1; q <= p; q++) { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); - // Additional loops - int m; + // Additional loops + int m; - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; + // Nested while loop with a break statement + int n = 1; + while (n <= 5) { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) { + break; + } } + n++; + } - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } + // Loop with nested conditions + for (int v = 1; v <= 10; v++) { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) { + printf("Less than 5\n"); + } else if (v > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index b9ccea76af..f89e28d91a 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,23 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount = 1; +int main() { + int outerCount = 1; - while (outerCount <= 3) - { - int innerCount = 1; + while (outerCount <= 3) { + int innerCount = 1; - while (outerCount < 3 || innerCount > 0) - { - printf("(%d, %d) ", outerCount, innerCount); - innerCount++; - } - - printf("\n"); - outerCount++; + while (outerCount < 3 || innerCount > 0) { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; } - return 0; + printf("\n"); + outerCount++; + } + + return 0; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index c4ba717784..3ad01cbd79 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,18 +1,17 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int num = 1; +int main() { + int num = 1; loop: - printf("Current number: %d\n", num); - num++; + printf("Current number: %d\n", num); + num++; - if (num <= 10) - { - goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. - } + if (num <= 10) { + goto loop; // We are not able to detect up-jumping gotos as terminating, we + // just warn about them might being nonterminating. + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index aab37803aa..e26f02ec11 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,15 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int num = 1; +int main() { + int num = 1; loop: - printf("Current number: %d\n", num); - num++; + printf("Current number: %d\n", num); + num++; - goto loop; + goto loop; - return 0; + return 0; } diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index 5d3cde9f3d..fc5d6ee7b7 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -1,31 +1,25 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include -int main() -{ - // Seed the random number generator - srand(time(NULL)); +int main() { + // Seed the random number generator + srand(time(NULL)); - if (rand()) - { - // Loop inside the if part - for (int i = 1; i <= 5; i++) - { - printf("Loop inside if part: %d\n", i); - } + if (rand()) { + // Loop inside the if part + for (int i = 1; i <= 5; i++) { + printf("Loop inside if part: %d\n", i); } - else - { - // Loop inside the else part - int j = 1; - while (j <= 5) - { - printf("Loop inside else part: %d\n", j); - j++; - } + } else { + // Loop inside the else part + int j = 1; + while (j <= 5) { + printf("Loop inside else part: %d\n", j); + j++; } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 124a19d0f8..e74c15c948 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -1,30 +1,24 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include -int main() -{ - // Seed the random number generator - srand(time(NULL)); +int main() { + // Seed the random number generator + srand(time(NULL)); - if (rand()) - { - // Loop inside the if part - for (int i = 1; i >= 0; i++) - { - printf("Loop inside if part: %d\n", i); - } + if (rand()) { + // Loop inside the if part + for (int i = 1; i >= 0; i++) { + printf("Loop inside if part: %d\n", i); } - else - { - // Loop inside the else part - int j = 1; - while (j > 0) - { - printf("Loop inside else part: %d\n", j); - } + } else { + // Loop inside the else part + int j = 1; + while (j > 0) { + printf("Loop inside else part: %d\n", j); } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 3bf479b6f9..10774e3420 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,20 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int forever, i = 0; +int main() { + int forever, i = 0; -// This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) - { - i++; - if (i == 4) - { - if (rand()) - { - forever = 1; - } - } + // This loop is not provable, therefore it should throw a warning + while (i < 4 || forever == 1) { + i++; + if (i == 4) { + if (rand()) { + forever = 1; + } } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 1f1a9bbd89..3f76f05aa9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,16 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int forever = 1; +int main() { + int forever = 1; -// This loop is not provable, therefore it should throw a warning - while (forever == 1) + // This loop is not provable, therefore it should throw a warning + while (forever == 1) { + if (rand()) // May exit, may not { - if (rand()) //May exit, may not - { - forever = 0; - } + forever = 0; } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 226f46b16e..080b3c8871 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -1,17 +1,16 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include -int main() -{ - int short_run, i = 0; +int main() { + int short_run, i = 0; - while (i < 90 && short_run != 1) // Currently not able to detect this as terminating - { - i++; - if (rand()) - { - short_run = 1; - } + while (i < 90 && + short_run != 1) // Currently not able to detect this as terminating + { + i++; + if (rand()) { + short_run = 1; } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1dc261d06a..1a4ef63ff7 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,19 +1,19 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { // Currently not able to detect up-jumping loop free gotos - goto mark2; + goto mark2; mark1: - printf("This is mark1\n"); - goto mark3; + printf("This is mark1\n"); + goto mark3; mark2: - printf("This is mark2\n"); - goto mark1; + printf("This is mark2\n"); + goto mark1; mark3: - printf("This is mark3\n"); + printf("This is mark3\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index cbbb115868..35edf86938 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,25 +1,25 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int counter = 0; + int counter = 0; - while (1) { - counter++; + while (1) { + counter++; - // Dummy code - printf("Iteration %d\n", counter); - int result = counter * 2; - printf("Result: %d\n", result); + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + printf("Result: %d\n", result); - // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this - goto end; - } + // Condition to terminate the loop + if (result >= 10) { // Apron is not able to detect this + goto end; } + } end: - printf("Loop exited. Result is greater than or equal to 10.\n"); + printf("Loop exited. Result is greater than or equal to 10.\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 17220a589b..97b46f66ca 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,28 +1,28 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int counter = 0; + int counter = 0; - goto jump_point; + goto jump_point; - while (1) { - counter++; + while (1) { + counter++; - // Dummy code - printf("Iteration %d\n", counter); - int result = counter * 2; - jump_point: - printf("Result: %d\n", result); + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + jump_point: + printf("Result: %d\n", result); - // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this - goto end; - } + // Condition to terminate the loop + if (result >= 10) { // Apron is not able to detect this + goto end; } + } end: - printf("Loop exited. Result is greater than or equal to 10.\n"); + printf("Loop exited. Result is greater than or equal to 10.\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index 52ad7ea820..a6621dd986 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,20 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - goto mark2; + goto mark2; mark1: - printf("This is mark1\n"); - goto mark3; + printf("This is mark1\n"); + goto mark3; mark2: - printf("This is mark2\n"); - goto mark1; + printf("This is mark2\n"); + goto mark1; mark3: - printf("This is mark3\n"); - goto mark1; + printf("This is mark3\n"); + goto mark1; - return 0; + return 0; } diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index f05fa4f315..b55aaf28c2 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,47 +1,52 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - i++; - printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + do { + i++; + printf("Inside the do-while loop\n"); + if (i % 2 == 0) { - printf("Skipping %i is even\n", i); - continue; // This is handled as an goto to line 8 and there an up-jumping goto - } - } while (i <= 5); + printf("Skipping %i is even\n", i); + continue; // This is handled as an goto to line 8 and there an up-jumping + // goto + } + } while (i <= 5); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } /* -NOTE: -Test 28: does not terminate but should terminate (test case "28-do-while-continue-terminating.c") -Reason: upjumping goto +NOTE: +Test 28: does not terminate but should terminate (test case +"28-do-while-continue-terminating.c") Reason: upjumping goto -If one has a look at the generated CIL output (attached at the bottom of this file), one can see that the "continue" is -translated in a "goto" with a corresponding label "__Cont". This label points to the loop-exit condition. Since the condition -is part of the loop, its location is evaluated to 8-17. -The location of the goto "goto __Cont" is located in line 15. -To provide soundness for the analysis, the preprocessing detects upjumping gotos with the help of its location. -In case such a goto is detected, the program is classified as non-terminating. -Due to this inserted goto (which is a result of the "continue"), an upjumping goto is located, which makes this program non-terminating. +If one has a look at the generated CIL output (attached at the bottom of this +file), one can see that the "continue" is translated in a "goto" with a +corresponding label "__Cont". This label points to the loop-exit condition. +Since the condition is part of the loop, its location is evaluated to 8-17. The +location of the goto "goto __Cont" is located in line 15. To provide soundness +for the analysis, the preprocessing detects upjumping gotos with the help of its +location. In case such a goto is detected, the program is classified as +non-terminating. Due to this inserted goto (which is a result of the +"continue"), an upjumping goto is located, which makes this program +non-terminating. -It should be noted that this issue happens when "do while"-loops and "continues" are combined. -If one combines "while"-loops and "continues", the analysis can still classify the loop as terminating. -The reason for that can be seen in the second CIL output, where the "do while"-loop is replaced by a "while"-loop. -Instead of creating a new label, the "while-continue" label of the loop is reused. Also, this goto statement is not specified as a goto, -but as a Continue statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". +It should be noted that this issue happens when "do while"-loops and "continues" +are combined. If one combines "while"-loops and "continues", the analysis can +still classify the loop as terminating. The reason for that can be seen in the +second CIL output, where the "do while"-loop is replaced by a "while"-loop. +Instead of creating a new label, the "while-continue" label of the loop is +reused. Also, this goto statement is not specified as a goto, but as a Continue +statement. Hence, it is not analyzed for the upjumping gotos, which does not +lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): ------------------- -int main(void) +------------------- SHORTENED CIL output for Test 28 (DO WHILE): +------------------- int main(void) {{{{ #line 8 while (1) { @@ -51,7 +56,7 @@ int main(void) #line 15 goto __Cont; } - __Cont: + __Cont: #line 8 if (! (i <= 5)) { #line 8 @@ -66,9 +71,8 @@ int main(void) }} -------------------- SHORTENED CIL output for Test 28 (WHILE): ------------------- -Test 28: replacing DO WHILE with WHILE: -int main(void) +------------------- SHORTENED CIL output for Test 28 (WHILE): +------------------- Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 896d8fea95..be3e7e12de 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,21 +1,19 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; + do { + printf("Inside the do-while loop\n"); + i++; - if(i%2) { - printf("Continue as %i is odd\n", i); - continue; - } - } while (i >= 2); + if (i % 2) { + printf("Continue as %i is odd\n", i); + continue; + } + } while (i >= 2); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index a92dcd2bc8..e2eff29c8b 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,31 +1,32 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; i <= rows; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - printf("Not Skipped?\n"); - outer_loop:; // Label for the outer loop - printf("Skipped!\n"); + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + printf("Not Skipped?\n"); + outer_loop:; // Label for the outer loop + printf("Skipped!\n"); + } - return 0; + return 0; } -/* +/* NOTE: In case we do NOT assume no-overflow: Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") -Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") +Test 35: does not terminate (test case +"35-goto-out-of-inner-loop-with-print-terminating.c") -The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" +The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" */ diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 722694eb88..756a93414b 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,23 +1,23 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; 1; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - printf("Goto as continue for outer loop\n"); - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - printf("\n"); - outer_loop:; // Label for the outer loop + // Outer loop for rows + for (int i = 1; 1; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + printf("Goto as continue for outer loop\n"); + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + printf("\n"); + outer_loop:; // Label for the outer loop + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index 1f98b88eee..beab8564f5 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,27 +1,27 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include #include // Thread function -void* printPID(void* arg) { - pid_t pid = getpid(); - pthread_t tid = pthread_self(); - printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); - return NULL; +void *printPID(void *arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + return NULL; } int main() { - // Create three threads - pthread_t thread1, thread2, thread3; - pthread_create(&thread1, NULL, printPID, NULL); - pthread_create(&thread2, NULL, printPID, NULL); - pthread_create(&thread3, NULL, printPID, NULL); + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); - // Wait for all threads to finish - pthread_join(thread1, NULL); - pthread_join(thread2, NULL); - pthread_join(thread3, NULL); + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); - return 0; + return 0; } diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 007af3b57b..278c107821 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -1,36 +1,37 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -#include -#include +#include #include +#include +#include // Thread function -void* printPID(void* arg) { - pid_t pid = getpid(); - pthread_t tid = pthread_self(); - while(1) { - printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); - struct timespec sleepTime; - sleepTime.tv_sec = 1; // Seconds - sleepTime.tv_nsec = 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) - printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); - nanosleep(&sleepTime, NULL); - } - return NULL; +void *printPID(void *arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + while (1) { + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + struct timespec sleepTime; + sleepTime.tv_sec = 1; // Seconds + sleepTime.tv_nsec = + 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) + printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); + nanosleep(&sleepTime, NULL); + } + return NULL; } int main() { - // Create three threads - pthread_t thread1, thread2, thread3; - pthread_create(&thread1, NULL, printPID, NULL); - pthread_create(&thread2, NULL, printPID, NULL); - pthread_create(&thread3, NULL, printPID, NULL); + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); - // Wait for all threads to finish - pthread_join(thread1, NULL); - pthread_join(thread2, NULL); - pthread_join(thread3, NULL); + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); - return 0; + return 0; } diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 29e4ff3835..3384ed0f60 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,19 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount, innerCount; +int main() { + int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) - { - for (innerCount = 1; innerCount > 0; innerCount++) - { - printf("(%d, %d) ", outerCount, innerCount); - } - - printf("\n"); + for (outerCount = 1; outerCount <= 3; outerCount++) { + for (innerCount = 1; innerCount > 0; innerCount++) { + printf("(%d, %d) ", outerCount, innerCount); } - return 0; + printf("\n"); + } + + return 0; } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index bb8bbacbf0..646f39111a 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,34 +1,38 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; i <= rows; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - outer_loop:; // Label for the outer loop - printf("\n"); + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + outer_loop:; // Label for the outer loop + printf("\n"); + } - return 0; + return 0; } -/* +/* NOTE: In case we do NOT assume no-overflow: Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") -Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") +Test 35: does not terminate (test case +"35-goto-out-of-inner-loop-with-print-terminating.c") -The only difference between Test 30 and Test 35 is line 17. Test 30 has an additional statement, and Test 35 continues already with the label. -This difference in Test 35 leads to an overflow in line 11, and hence to the non-termination. -This overflow is created by a WPoint Issue. By enabling the no-overflow option this issue can be fixed and, both test cases are correctly detected as terminating. +The only difference between Test 30 and Test 35 is line 17. Test 30 has an +additional statement, and Test 35 continues already with the label. This +difference in Test 35 leads to an overflow in line 11, and hence to the +non-termination. This overflow is created by a WPoint Issue. By enabling the +no-overflow option this issue can be fixed and, both test cases are correctly +detected as terminating. (The overflow also happens without the termination analysis enabled.) */ diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 583f8ccca1..533778332f 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,22 +1,22 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { - // Base case: When n reaches 0, stop recursion - if (n == 0) { - printf("Terminating recursion\n"); - return; - } + // Base case: When n reaches 0, stop recursion + if (n == 0) { + printf("Terminating recursion\n"); + return; + } - printf("Recursive call with n = %d\n", n); + printf("Recursive call with n = %d\n", n); - // Recursive call: Decrement n and call the function again - recursiveFunction(n - 1); + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); } int main() { - // Call the recursive function with an initial value - recursiveFunction(5); + // Call the recursive function with an initial value + recursiveFunction(5); - return 0; + return 0; } diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index d20adea294..089a4d3bcc 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,22 +1,22 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) { - // Base case: When n reaches 0, stop recursion - if (n == 30) { - printf("Terminating recursion\n"); - return; - } + // Base case: When n reaches 0, stop recursion + if (n == 30) { + printf("Terminating recursion\n"); + return; + } - printf("Recursive call with n = %d\n", n); + printf("Recursive call with n = %d\n", n); - // Recursive call: Decrement n and call the function again - recursiveFunction(n - 1); + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); } int main() { - // Call the recursive function with an initial value - recursiveFunction(5); + // Call the recursive function with an initial value + recursiveFunction(5); - return 0; + return 0; } diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index 4cede747f2..eace365a44 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,36 +1,36 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { - if (n == 0) { - printf("Terminating inner recursion\n"); - return; - } + if (n == 0) { + printf("Terminating inner recursion\n"); + return; + } - printf("Inner recursive call with n = %d\n", n); + printf("Inner recursive call with n = %d\n", n); - // Recursive call to the innerRecursiveFunction - innerRecursiveFunction(n - 1); + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(n - 1); } void outerRecursiveFunction(int n) { - if (n == 0) { - printf("Terminating outer recursion\n"); - return; - } + if (n == 0) { + printf("Terminating outer recursion\n"); + return; + } - printf("Outer recursive call with n = %d\n", n); + printf("Outer recursive call with n = %d\n", n); - // Recursive call to the outerRecursiveFunction - outerRecursiveFunction(n - 1); + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(n - 1); - // Call to the innerRecursiveFunction - innerRecursiveFunction(n); + // Call to the innerRecursiveFunction + innerRecursiveFunction(n); } int main() { - // Call the outerRecursiveFunction with an initial value - outerRecursiveFunction(3); + // Call the outerRecursiveFunction with an initial value + outerRecursiveFunction(3); - return 0; + return 0; } diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 2d3239f371..8b57f83857 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,26 +1,26 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { - printf("Nested recursive call\n"); + printf("Nested recursive call\n"); - // Recursive call to the innerRecursiveFunction - innerRecursiveFunction(); + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(); } void outerRecursiveFunction() { - printf("Outer recursive call\n"); + printf("Outer recursive call\n"); - // Recursive call to the outerRecursiveFunction - outerRecursiveFunction(); + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(); - // Call to the innerRecursiveFunction - innerRecursiveFunction(); + // Call to the innerRecursiveFunction + innerRecursiveFunction(); } int main() { - // Call the outerRecursiveFunction - outerRecursiveFunction(); + // Call the outerRecursiveFunction + outerRecursiveFunction(); - return 0; + return 0; } diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index 2f342e89a0..d5fe6b808a 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,39 +1,33 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int i; + int i; - // Loop with a continue statement - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - continue; - } - printf("%d ", i); + // Loop with a continue statement + for (i = 1; i <= 10; i++) { + if (i % 2 == 0) { + continue; } - printf("\n"); + printf("%d ", i); + } + printf("\n"); - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } + // Loop with complex conditions + for (i = 1; i <= 10; i++) { + if (i > 5 && i % 2 == 0) { + printf("%d ", i); } - printf("\n"); + } + printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - i++; + // Loop with complex conditions + i = 1; + while (i <= 10) { + if (i > 5 && i % 2 == 0) { + printf("%d ", i); } - printf("\n"); + i++; + } + printf("\n"); } \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 112f95c3ee..272be43293 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,30 +1,26 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include int main() { - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); + // Loop with a continue statement + for (int r = 1; r <= 10; r++) { + if (r % 3 == 0) { + continue; } + printf("Loop with Continue: %d\n", r); + } - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } - } \ No newline at end of file + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } +} \ No newline at end of file From 1faf7290699344def397dbd6ade78da546e494d5 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 10 Jul 2023 14:51:01 +0200 Subject: [PATCH 222/628] added autoTune for termination analysis in mainGoblint.ml --- src/maingoblint.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 8944d87ea0..f9abd9637b 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -159,7 +159,12 @@ let check_arguments () = ^ String.concat " and " @@ List.map (fun s -> "'" ^ s ^ "'") imprecise_options) ); if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; - if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'" + if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; + if List.mem "termination" @@ get_string_list "ana.activated" then ( + set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); + set_string "sem.int.signed_overflow" "assume_none"; + warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" + ) (** Initialize some globals in other modules. *) let handle_flags () = From 43bf64daf294ad4c0798a63fd7738d6c32235c82 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 10 Jul 2023 16:10:56 +0200 Subject: [PATCH 223/628] temporarly removed sem.int.signed_overflow assume_none autotuning --- src/maingoblint.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index f9abd9637b..371deb989a 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,7 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); - set_string "sem.int.signed_overflow" "assume_none"; + (*set_string "sem.int.signed_overflow" "assume_none";*) warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" ) From 5ef2664537eed087c99da0b8b70b7d9667fc21f5 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:12:13 +0200 Subject: [PATCH 224/628] Test indentation --- .../01-simple-loop-terminating.c | 6 +- .../02-simple-loop-nonterminating.c | 6 +- .../03-nested-loop-terminating.c | 9 ++- .../04-nested-loop-nonterminating.c | 9 ++- .../75-termination/05-for-loop-terminating.c | 6 +- .../06-for-loop-nonterminating.c | 6 +- .../07-nested-for-loop-terminating.c | 9 ++- .../08-nested-for-loop-nonterminating.c | 9 ++- .../09-complex-for-loop-terminating.c | 51 +++++++++++------ .../10-complex-loop-terminating.c | 57 +++++++++++++------ .../75-termination/11-loopless-termination.c | 3 +- .../12-do-while-instant-terminating.c | 6 +- .../75-termination/13-do-while-terminating.c | 6 +- .../14-do-while-nonterminating.c | 6 +- .../15-complex-loop-combination-terminating.c | 53 +++++++++++------ ...16-nested-loop-nontrivial-nonterminating.c | 9 ++- .../75-termination/17-goto-terminating.c | 6 +- .../75-termination/18-goto-nonterminating.c | 3 +- .../75-termination/19-rand-terminating.c | 16 ++++-- .../75-termination/20-rand-nonterminating.c | 16 ++++-- .../21-no-exit-on-rand-unproofable.c | 12 ++-- .../22-exit-on-rand-unproofable.c | 6 +- .../23-exit-on-rand-terminating.c | 6 +- .../24-upjumping-goto-loopless-terminating.c | 3 +- .../25-leave-loop-goto-terminating.c | 9 ++- .../26-enter-loop-goto-terminating.c | 9 ++- .../27-upjumping-goto-nonterminating.c | 3 +- .../28-do-while-continue-terminating.c | 9 ++- .../29-do-while-continue-nonterminating.c | 9 ++- .../30-goto-out-of-inner-loop-terminating.c | 12 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 12 ++-- .../32-multithread-terminating.c | 6 +- .../33-multithread-nonterminating.c | 9 ++- .../34-nested-for-loop-nonterminating.c | 9 ++- ...out-of-inner-loop-with-print-terminating.c | 12 ++-- .../75-termination/36-recursion-terminating.c | 9 ++- .../37-recursion-nonterminating.c | 9 ++- .../38-recursion-nested-terminating.c | 15 +++-- .../39-recursion-nested-nonterminating.c | 9 ++- .../75-termination/40-complex-conditions.c | 21 ++++--- .../regression/75-termination/41-more-tests.c | 15 +++-- 41 files changed, 334 insertions(+), 162 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index 66b6585f67..aaa2a7a895 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d\n", i); i++; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 6fe8816da4..51fb340f3b 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - while (1) { +int main() +{ + while (1) + { continue; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 4e3fafabcf..70327c1016 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,17 +1,20 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; int i = 1; // Outer while loop for rows - while (i <= rows) { + while (i <= rows) + { int j = 1; // Inner while loop for columns - while (j <= columns) { + while (j <= columns) + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 00c2554ed2..fffc932f36 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (1) { + while (1) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index fe07200e5b..bf58408487 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d\n", i); } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 374cd3e59f..be876c9741 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - for (;;) { +int main() +{ + for (;;) + { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index a94f3f360c..1c43eeaada 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,13 +1,16 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) { + for (int i = 1; i <= rows; i++) + { + for (int j = 1; j <= columns; j++) + { printf("(%d, %d) ", i, j); } printf("\n"); diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e78e819cc0..e360d45d0a 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1;; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 018fba6822..9767b4bc1c 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,57 +1,75 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) { + for (i = 1; i <= 5; i++) + { // Inner loop 1 - for (j = 1; j <= i; j++) { + for (j = 1; j <= i; j++) + { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) { + for (k = i; k >= 1; k--) + { printf("%d ", k); } printf("\n"); } // Additional loop - for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) { + for (i = 5; i >= 1; i--) + { + for (j = i; j >= 1; j--) + { printf("%d ", j); } printf("\n"); } // Loop with conditions - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } } // Loop with nested conditions - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } // Loop with a break statement - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } } @@ -59,7 +77,8 @@ int main() { // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) + { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 88bf6a4565..19091b1033 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,15 +1,18 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i = 1; int j = 1; int k = 5; // Outer while loop - while (i <= 5) { + while (i <= 5) + { // Inner while loop 1 - while (j <= i) { + while (j <= i) + { printf("%d ", j); j++; } @@ -17,7 +20,8 @@ int main() { j = 1; // Inner while loop 2 - while (k >= 1) { + while (k >= 1) + { printf("%d ", k); k--; } @@ -29,9 +33,11 @@ int main() { // Additional while loop i = 5; - while (i >= 1) { + while (i >= 1) + { j = i; - while (j >= 1) { + while (j >= 1) + { printf("%d ", j); j--; } @@ -41,10 +47,14 @@ int main() { // Loop with conditions i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } i++; @@ -52,13 +62,19 @@ int main() { // Loop with nested conditions i = 1; - while (i <= 10) { + while (i <= 10) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } i++; @@ -66,9 +82,11 @@ int main() { // Loop with a break statement i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } i++; @@ -77,8 +95,10 @@ int main() { // Loop with a continue statement i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { i++; continue; } @@ -91,7 +111,8 @@ int main() { int a = 1; int b = 2; int c = 3; - while (a <= 10) { + while (a <= 10) + { printf("%d %d %d\n", a, b, c); a++; b += 2; diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index a1846905fc..51c0605757 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,8 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ printf("Terminating code without a loop\n"); return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 087b88f1f5..3767430a51 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 0; - do { + do + { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 34343d6ba6..8faeec1e64 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i <= 5); diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 6473fdc20d..30c8349bb5 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,10 +1,12 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i >= 2); diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 23282d24b1..d987397dd7 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,25 +1,29 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ // Non-nested loops int i; // for loop - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) { + while (j <= 10) + { printf("While loop iteration: %d\n", j); j++; } // do-while loop int k = 1; - do { + do + { printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); @@ -28,9 +32,11 @@ int main() { int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) { + for (a = 1; a <= 5; a++) + { int c = 1; - while (c <= a) { + while (c <= a) + { printf("Nested For-While loop: %d\n", c); c++; } @@ -38,9 +44,11 @@ int main() { // Nested while and do-while loop int x = 1; - while (x <= 5) { + while (x <= 5) + { int y = 1; - do { + do + { printf("Nested While-Do-While loop: %d\n", y); y++; } while (y <= x); @@ -49,8 +57,10 @@ int main() { // Nested do-while and for loop int p = 1; - do { - for (int q = 1; q <= p; q++) { + do + { + for (int q = 1; q <= p; q++) + { printf("Nested Do-While-For loop: %d\n", q); } p++; @@ -61,13 +71,16 @@ int main() { // Nested while loop with a break statement int n = 1; - while (n <= 5) { + while (n <= 5) + { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) { + while (1) + { printf("Inner While loop iteration: %d\n", m); m++; - if (m == 4) { + if (m == 4) + { break; } } @@ -75,13 +88,19 @@ int main() { } // Loop with nested conditions - for (int v = 1; v <= 10; v++) { + for (int v = 1; v <= 10; v++) + { printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) { + if (v < 5) + { printf("Less than 5\n"); - } else if (v > 5) { + } + else if (v > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index f89e28d91a..87b4b82ed9 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) { + while (outerCount < 3 || innerCount > 0) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 3ad01cbd79..7624ae1ffc 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,14 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: printf("Current number: %d\n", num); num++; - if (num <= 10) { + if (num <= 10) + { goto loop; // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index e26f02ec11..25f79e5b57 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index fc5d6ee7b7..06deac6c34 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i <= 5; i++) { + for (int i = 1; i <= 5; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j <= 5) { + while (j <= 5) + { printf("Loop inside else part: %d\n", j); j++; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index e74c15c948..83630ed6c4 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i >= 0; i++) { + for (int i = 1; i >= 0; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j > 0) { + while (j > 0) + { printf("Loop inside else part: %d\n", j); } } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 10774e3420..3e7a65dfd4 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,14 +1,18 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) { + while (i < 4 || forever == 1) + { i++; - if (i == 4) { - if (rand()) { + if (i == 4) + { + if (rand()) + { forever = 1; } } diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 3f76f05aa9..b8d7992bd9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,11 +1,13 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) { + while (forever == 1) + { if (rand()) // May exit, may not { forever = 0; diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 080b3c8871..24d4980406 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -2,14 +2,16 @@ #include #include -int main() { +int main() +{ int short_run, i = 0; while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; - if (rand()) { + if (rand()) + { short_run = 1; } } diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1a4ef63ff7..be5698d1d8 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,8 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { // Currently not able to detect up-jumping loop free gotos +int main() +{ // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 35edf86938..2cda3d3a03 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,10 +1,12 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; - while (1) { + while (1) + { counter++; // Dummy code @@ -13,7 +15,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 97b46f66ca..0de9a95d6c 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,12 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; goto jump_point; - while (1) { + while (1) + { counter++; // Dummy code @@ -16,7 +18,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index a6621dd986..e27d7161d5 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ goto mark2; mark1: diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..ebd0395218 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,13 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { i++; printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + if (i % 2 == 0) + { printf("Skipping %i is even\n", i); continue; // This is handled as an goto to line 8 and there an up-jumping diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index be3e7e12de..41f1dbd5bc 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,14 +1,17 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; - if (i % 2) { + if (i % 2) + { printf("Continue as %i is odd\n", i); continue; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index e2eff29c8b..5cdadf4396 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 756a93414b..cb54b5dd2f 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,15 +1,19 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) { + for (int i = 1; 1; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { printf("Goto as continue for outer loop\n"); goto outer_loop; // Jump to the label "outer_loop" } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index beab8564f5..950eaaaa51 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -4,14 +4,16 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 278c107821..dad62aa0f4 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -6,10 +6,12 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); - while (1) { + while (1) + { printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); struct timespec sleepTime; sleepTime.tv_sec = 1; // Seconds @@ -21,7 +23,8 @@ void *printPID(void *arg) { return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 3384ed0f60..709960640f 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 646f39111a..f564354e51 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 533778332f..7336417c91 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,9 +1,11 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 0) { + if (n == 0) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 089a4d3bcc..38aaf3de85 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,9 +1,11 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 30) { + if (n == 30) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index eace365a44..bef05eb1a0 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,8 +1,10 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction(int n) { - if (n == 0) { +void innerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating inner recursion\n"); return; } @@ -13,8 +15,10 @@ void innerRecursiveFunction(int n) { innerRecursiveFunction(n - 1); } -void outerRecursiveFunction(int n) { - if (n == 0) { +void outerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating outer recursion\n"); return; } @@ -28,7 +32,8 @@ void outerRecursiveFunction(int n) { innerRecursiveFunction(n); } -int main() { +int main() +{ // Call the outerRecursiveFunction with an initial value outerRecursiveFunction(3); diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8b57f83857..8311d9f573 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,14 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() { +void innerRecursiveFunction() +{ printf("Nested recursive call\n"); // Recursive call to the innerRecursiveFunction innerRecursiveFunction(); } -void outerRecursiveFunction() { +void outerRecursiveFunction() +{ printf("Outer recursive call\n"); // Recursive call to the outerRecursiveFunction @@ -18,7 +20,8 @@ void outerRecursiveFunction() { innerRecursiveFunction(); } -int main() { +int main() +{ // Call the outerRecursiveFunction outerRecursiveFunction(); diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index d5fe6b808a..a74c863fb4 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,12 +1,15 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; // Loop with a continue statement - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { continue; } printf("%d ", i); @@ -14,8 +17,10 @@ int main() { printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) { - if (i > 5 && i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } } @@ -23,8 +28,10 @@ int main() { // Loop with complex conditions i = 1; - while (i <= 10) { - if (i > 5 && i % 2 == 0) { + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } i++; diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 272be43293..1fb9f83f5d 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,11 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ // Loop with a continue statement - for (int r = 1; r <= 10; r++) { - if (r % 3 == 0) { + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { continue; } printf("Loop with Continue: %d\n", r); @@ -13,14 +16,16 @@ int main() { // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) { + while (s <= 10 && s % 2 == 0) + { printf("Loop with Multiple Conditions: %d\n", s); s++; } // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { printf("Loop with Multiple Variables: %d %d\n", t, u); } } \ No newline at end of file From 71b1eb21eeaecc3bdebdd24fb11b966a5fbb84ff Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:55:45 +0200 Subject: [PATCH 225/628] Execute termination tests in CI even if skipped. --- .github/workflows/locked.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/locked.yml b/.github/workflows/locked.yml index 751ade6880..48809d34c1 100644 --- a/.github/workflows/locked.yml +++ b/.github/workflows/locked.yml @@ -64,6 +64,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From 472a76c77d7437e446fed001fac2184fb96bd4bb Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 17:29:28 +0200 Subject: [PATCH 226/628] added warning for multithreaded case --- src/analyses/loopTermination.ml | 26 +++++++++++-------- .../28-do-while-continue-terminating.c | 8 +++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index ecb48a5284..4242dd2b36 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,17 +61,6 @@ struct let startstate _ = () let exitstate = startstate - let finalize () = - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); - () - let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -126,6 +115,21 @@ struct G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx + | WarnGlobal v -> + (* warning for detected possible non-termination *) + (*upjumping gotos *) + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + (* multithreaded *) + if not (must_be_single_threaded_since_start ctx) then ( + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ); | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..495c6f30b1 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): -------------------- int main(void) +----- SHORTENED CIL output for Test 28 (DO WHILE): ----- +int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ lead to the problem as with the "do while". }} -------------------- SHORTENED CIL output for Test 28 (WHILE): -------------------- Test 28: replacing DO WHILE with WHILE: int main(void) +----- SHORTENED CIL output for Test 28 (WHILE): ----- +Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 4af911a0c99939ea90dcdc357b0cffb61e2a1444 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 19:55:19 +0200 Subject: [PATCH 227/628] Revert "added warning for multithreaded case" This reverts commit 472a76c77d7437e446fed001fac2184fb96bd4bb. --- src/analyses/loopTermination.ml | 26 ++++++++----------- .../28-do-while-continue-terminating.c | 8 +++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 4242dd2b36..ecb48a5284 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,6 +61,17 @@ struct let startstate _ = () let exitstate = startstate + let finalize () = + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + () + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -115,21 +126,6 @@ struct G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx - | WarnGlobal v -> - (* warning for detected possible non-termination *) - (*upjumping gotos *) - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); - (* multithreaded *) - if not (must_be_single_threaded_since_start ctx) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ); | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 495c6f30b1..b55aaf28c2 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". ------ SHORTENED CIL output for Test 28 (DO WHILE): ----- -int main(void) +------------------- SHORTENED CIL output for Test 28 (DO WHILE): +------------------- int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ int main(void) }} ------ SHORTENED CIL output for Test 28 (WHILE): ----- -Test 28: replacing DO WHILE with WHILE: int main(void) +------------------- SHORTENED CIL output for Test 28 (WHILE): +------------------- Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 32a654bbdbe411b91360149541d3c3532d42ecde Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 21:04:50 +0200 Subject: [PATCH 228/628] addedd the possibly non-terminating warning for multi threaded programs --- src/analyses/loopTermination.ml | 32 +++++++++++++------ .../28-do-while-continue-terminating.c | 8 ++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index ecb48a5284..bfcb364e87 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,6 +6,10 @@ open TerminationPreprocessing exception PreProcessing of string +(** Stores the result of the query if the program is single threaded or not + since finalize does not has ctx as an argument*) +let single_thread : bool ref = ref false + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -62,15 +66,21 @@ struct let exitstate = startstate let finalize () = + (* warning for detected possible non-termination *) + (*upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) - ); - () + ); + (* multithreaded *) + if not (!single_thread) then ( + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then @@ -112,20 +122,24 @@ struct (* not (ctx.ask Queries.IsEverMultiThreaded) *) - ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + let single_threaded = ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) in + single_thread := single_threaded; + single_threaded (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with + must_be_single_threaded_since_start ctx + && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) - && must_be_single_threaded_since_start ctx | Queries.MustTermAllLoops -> - G.for_all (fun _ term_info -> term_info) (ctx.global ()) + must_be_single_threaded_since_start ctx (* must be the first to be evaluated! + This has the side effect that the single_Thread variable is set + In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) && no_upjumping_gotos () - && must_be_single_threaded_since_start ctx + && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..9e8cb7496b 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): -------------------- int main(void) +------- SHORTENED CIL output for Test 28 (DO WHILE): ------- +int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ lead to the problem as with the "do while". }} -------------------- SHORTENED CIL output for Test 28 (WHILE): -------------------- Test 28: replacing DO WHILE with WHILE: int main(void) +------- SHORTENED CIL output for Test 28 (WHILE): ------- +Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 53c3c1ce32c78f9844d6d36b5ec73b1954bbf108 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 12 Jul 2023 16:01:32 +0200 Subject: [PATCH 229/628] Enable use of everMultiThreaded analysis --- src/analyses/everMultiThreaded.ml | 2 +- src/analyses/loopTermination.ml | 40 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml index 5567ef1223..f44aaffc93 100644 --- a/src/analyses/everMultiThreaded.ml +++ b/src/analyses/everMultiThreaded.ml @@ -1,4 +1,4 @@ -(** Work in progress *) +(** Analysis to register whether any additional thread has ever been spawned ([evermultithreaded]). *) open Analyses diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfcb364e87..f62eedcce4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,7 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string -(** Stores the result of the query if the program is single threaded or not +(** Stores the result of the query if the program is single threaded or not since finalize does not has ctx as an argument*) let single_thread : bool ref = ref false @@ -65,21 +65,21 @@ struct let startstate _ = () let exitstate = startstate - let finalize () = + let finalize () = (* warning for detected possible non-termination *) (*upjumping gotos *) if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ) + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) let assign ctx (lval : lval) (rval : exp) = @@ -119,10 +119,7 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = - (* - not (ctx.ask Queries.IsEverMultiThreaded) - *) - let single_threaded = ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) in + let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded @@ -130,14 +127,15 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_be_single_threaded_since_start ctx + must_be_single_threaded_since_start ctx && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with - Some b -> b - | None -> false) + Some b -> b + | None -> false) | Queries.MustTermAllLoops -> - must_be_single_threaded_since_start ctx (* must be the first to be evaluated! - This has the side effect that the single_Thread variable is set - In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) + (* Must be the first to be evaluated! This has the side effect that + * single_thread is set. In case of another order and due to lazy + * evaluation the correct value of single_thread can not be guaranteed! *) + must_be_single_threaded_since_start ctx && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From 76486c9a9c7bc08fd213cda8beb737c5861bfa8e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 12 Jul 2023 16:04:20 +0200 Subject: [PATCH 230/628] Make struct for V anonymous --- src/analyses/loopTermination.ml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index f62eedcce4..367c3a328c 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -37,12 +37,6 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV = -struct - include Printable.Unit - let is_write_only _ = true -end - (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a * lattice. *) @@ -59,7 +53,11 @@ struct module D = Lattice.Unit module C = D - module V = UnitV + module V = + struct + include Printable.Unit + let is_write_only _ = true + end module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () From ba9d35a9973a38f748bbbcba3cabd4284c6ac57f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 13 Jul 2023 12:19:12 +0200 Subject: [PATCH 231/628] indentation --- src/analyses/loopTermination.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfcb364e87..1dece04bbc 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -75,11 +75,11 @@ struct [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) - ); + ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ) + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) let assign ctx (lval : lval) (rval : exp) = @@ -135,9 +135,9 @@ struct Some b -> b | None -> false) | Queries.MustTermAllLoops -> - must_be_single_threaded_since_start ctx (* must be the first to be evaluated! - This has the side effect that the single_Thread variable is set - In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) + must_be_single_threaded_since_start ctx (* must be the first to be evaluated! *) + (*Reason: must_be_single_threaded_since_start has the side effect that the single_Thread variable is set + In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From a98f503ed7c47e2d208b7031268e314f08680ade Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 12:27:02 +0200 Subject: [PATCH 232/628] Test goal and comments changed --- .../75-termination/17-goto-terminating.c | 3 ++- .../24-upjumping-goto-loopless-terminating.c | 3 ++- .../28-do-while-continue-terminating.c | 3 +-- .../32-multithread-terminating.c | 3 ++- ...42-downjumping-goto-loopless-terminating.c | 19 +++++++++++++++++++ 5 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 3ad01cbd79..8270f8c960 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,4 +1,5 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include int main() { diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1a4ef63ff7..88d8c8f418 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,5 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include int main() { // Currently not able to detect up-jumping loop free gotos diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 9e8cb7496b..402e744e2f 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -10,8 +10,7 @@ int main() { if (i % 2 == 0) { printf("Skipping %i is even\n", i); - continue; // This is handled as an goto to line 8 and there an up-jumping - // goto + continue; // This is handled as an goto to line 8 and therefore an up-jumping goto } } while (i <= 5); diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index beab8564f5..737b867cde 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,4 +1,5 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but as the termination analysis is meant to not handle multithreaded programs we expect NonTerm here #include #include #include diff --git a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c new file mode 100644 index 0000000000..54bcfdc508 --- /dev/null +++ b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c @@ -0,0 +1,19 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { // Currently not able to detect up-jumping loop free gotos + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark3; + +mark3: + printf("This is mark3\n"); + + return 0; +} From 98c062a2c28db2418adcd67fa5c540c75d2cfebf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:12:13 +0200 Subject: [PATCH 233/628] Test indentation --- .../01-simple-loop-terminating.c | 6 +- .../02-simple-loop-nonterminating.c | 6 +- .../03-nested-loop-terminating.c | 9 ++- .../04-nested-loop-nonterminating.c | 9 ++- .../75-termination/05-for-loop-terminating.c | 6 +- .../06-for-loop-nonterminating.c | 6 +- .../07-nested-for-loop-terminating.c | 9 ++- .../08-nested-for-loop-nonterminating.c | 9 ++- .../09-complex-for-loop-terminating.c | 51 +++++++++++------ .../10-complex-loop-terminating.c | 57 +++++++++++++------ .../75-termination/11-loopless-termination.c | 3 +- .../12-do-while-instant-terminating.c | 6 +- .../75-termination/13-do-while-terminating.c | 6 +- .../14-do-while-nonterminating.c | 6 +- .../15-complex-loop-combination-terminating.c | 53 +++++++++++------ ...16-nested-loop-nontrivial-nonterminating.c | 9 ++- .../75-termination/17-goto-terminating.c | 6 +- .../75-termination/18-goto-nonterminating.c | 3 +- .../75-termination/19-rand-terminating.c | 16 ++++-- .../75-termination/20-rand-nonterminating.c | 16 ++++-- .../21-no-exit-on-rand-unproofable.c | 12 ++-- .../22-exit-on-rand-unproofable.c | 6 +- .../23-exit-on-rand-terminating.c | 6 +- .../24-upjumping-goto-loopless-terminating.c | 3 +- .../25-leave-loop-goto-terminating.c | 9 ++- .../26-enter-loop-goto-terminating.c | 9 ++- .../27-upjumping-goto-nonterminating.c | 3 +- .../28-do-while-continue-terminating.c | 9 ++- .../29-do-while-continue-nonterminating.c | 9 ++- .../30-goto-out-of-inner-loop-terminating.c | 12 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 12 ++-- .../32-multithread-terminating.c | 6 +- .../33-multithread-nonterminating.c | 9 ++- .../34-nested-for-loop-nonterminating.c | 9 ++- ...out-of-inner-loop-with-print-terminating.c | 12 ++-- .../75-termination/36-recursion-terminating.c | 9 ++- .../37-recursion-nonterminating.c | 9 ++- .../38-recursion-nested-terminating.c | 15 +++-- .../39-recursion-nested-nonterminating.c | 9 ++- .../75-termination/40-complex-conditions.c | 21 ++++--- .../regression/75-termination/41-more-tests.c | 15 +++-- 41 files changed, 334 insertions(+), 162 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index 66b6585f67..aaa2a7a895 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d\n", i); i++; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 6fe8816da4..51fb340f3b 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - while (1) { +int main() +{ + while (1) + { continue; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 4e3fafabcf..70327c1016 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,17 +1,20 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; int i = 1; // Outer while loop for rows - while (i <= rows) { + while (i <= rows) + { int j = 1; // Inner while loop for columns - while (j <= columns) { + while (j <= columns) + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 00c2554ed2..fffc932f36 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (1) { + while (1) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index fe07200e5b..bf58408487 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d\n", i); } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 374cd3e59f..be876c9741 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - for (;;) { +int main() +{ + for (;;) + { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index a94f3f360c..1c43eeaada 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,13 +1,16 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) { + for (int i = 1; i <= rows; i++) + { + for (int j = 1; j <= columns; j++) + { printf("(%d, %d) ", i, j); } printf("\n"); diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e78e819cc0..e360d45d0a 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1;; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 018fba6822..9767b4bc1c 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,57 +1,75 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) { + for (i = 1; i <= 5; i++) + { // Inner loop 1 - for (j = 1; j <= i; j++) { + for (j = 1; j <= i; j++) + { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) { + for (k = i; k >= 1; k--) + { printf("%d ", k); } printf("\n"); } // Additional loop - for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) { + for (i = 5; i >= 1; i--) + { + for (j = i; j >= 1; j--) + { printf("%d ", j); } printf("\n"); } // Loop with conditions - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } } // Loop with nested conditions - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } // Loop with a break statement - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } } @@ -59,7 +77,8 @@ int main() { // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) + { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 88bf6a4565..19091b1033 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,15 +1,18 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i = 1; int j = 1; int k = 5; // Outer while loop - while (i <= 5) { + while (i <= 5) + { // Inner while loop 1 - while (j <= i) { + while (j <= i) + { printf("%d ", j); j++; } @@ -17,7 +20,8 @@ int main() { j = 1; // Inner while loop 2 - while (k >= 1) { + while (k >= 1) + { printf("%d ", k); k--; } @@ -29,9 +33,11 @@ int main() { // Additional while loop i = 5; - while (i >= 1) { + while (i >= 1) + { j = i; - while (j >= 1) { + while (j >= 1) + { printf("%d ", j); j--; } @@ -41,10 +47,14 @@ int main() { // Loop with conditions i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } i++; @@ -52,13 +62,19 @@ int main() { // Loop with nested conditions i = 1; - while (i <= 10) { + while (i <= 10) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } i++; @@ -66,9 +82,11 @@ int main() { // Loop with a break statement i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } i++; @@ -77,8 +95,10 @@ int main() { // Loop with a continue statement i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { i++; continue; } @@ -91,7 +111,8 @@ int main() { int a = 1; int b = 2; int c = 3; - while (a <= 10) { + while (a <= 10) + { printf("%d %d %d\n", a, b, c); a++; b += 2; diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index a1846905fc..51c0605757 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,8 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ printf("Terminating code without a loop\n"); return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 087b88f1f5..3767430a51 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 0; - do { + do + { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 34343d6ba6..8faeec1e64 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i <= 5); diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 6473fdc20d..30c8349bb5 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,10 +1,12 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i >= 2); diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 23282d24b1..d987397dd7 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,25 +1,29 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ // Non-nested loops int i; // for loop - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) { + while (j <= 10) + { printf("While loop iteration: %d\n", j); j++; } // do-while loop int k = 1; - do { + do + { printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); @@ -28,9 +32,11 @@ int main() { int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) { + for (a = 1; a <= 5; a++) + { int c = 1; - while (c <= a) { + while (c <= a) + { printf("Nested For-While loop: %d\n", c); c++; } @@ -38,9 +44,11 @@ int main() { // Nested while and do-while loop int x = 1; - while (x <= 5) { + while (x <= 5) + { int y = 1; - do { + do + { printf("Nested While-Do-While loop: %d\n", y); y++; } while (y <= x); @@ -49,8 +57,10 @@ int main() { // Nested do-while and for loop int p = 1; - do { - for (int q = 1; q <= p; q++) { + do + { + for (int q = 1; q <= p; q++) + { printf("Nested Do-While-For loop: %d\n", q); } p++; @@ -61,13 +71,16 @@ int main() { // Nested while loop with a break statement int n = 1; - while (n <= 5) { + while (n <= 5) + { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) { + while (1) + { printf("Inner While loop iteration: %d\n", m); m++; - if (m == 4) { + if (m == 4) + { break; } } @@ -75,13 +88,19 @@ int main() { } // Loop with nested conditions - for (int v = 1; v <= 10; v++) { + for (int v = 1; v <= 10; v++) + { printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) { + if (v < 5) + { printf("Less than 5\n"); - } else if (v > 5) { + } + else if (v > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index f89e28d91a..87b4b82ed9 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) { + while (outerCount < 3 || innerCount > 0) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 8270f8c960..45e92f32e8 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -2,14 +2,16 @@ // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include -int main() { +int main() +{ int num = 1; loop: printf("Current number: %d\n", num); num++; - if (num <= 10) { + if (num <= 10) + { goto loop; // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index e26f02ec11..25f79e5b57 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index fc5d6ee7b7..06deac6c34 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i <= 5; i++) { + for (int i = 1; i <= 5; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j <= 5) { + while (j <= 5) + { printf("Loop inside else part: %d\n", j); j++; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index e74c15c948..83630ed6c4 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i >= 0; i++) { + for (int i = 1; i >= 0; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j > 0) { + while (j > 0) + { printf("Loop inside else part: %d\n", j); } } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 10774e3420..3e7a65dfd4 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,14 +1,18 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) { + while (i < 4 || forever == 1) + { i++; - if (i == 4) { - if (rand()) { + if (i == 4) + { + if (rand()) + { forever = 1; } } diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 3f76f05aa9..b8d7992bd9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,11 +1,13 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) { + while (forever == 1) + { if (rand()) // May exit, may not { forever = 0; diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 080b3c8871..24d4980406 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -2,14 +2,16 @@ #include #include -int main() { +int main() +{ int short_run, i = 0; while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; - if (rand()) { + if (rand()) + { short_run = 1; } } diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 88d8c8f418..3dbff9d7ea 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -2,7 +2,8 @@ // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include -int main() { // Currently not able to detect up-jumping loop free gotos +int main() +{ // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 35edf86938..2cda3d3a03 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,10 +1,12 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; - while (1) { + while (1) + { counter++; // Dummy code @@ -13,7 +15,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 97b46f66ca..0de9a95d6c 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,12 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; goto jump_point; - while (1) { + while (1) + { counter++; // Dummy code @@ -16,7 +18,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index a6621dd986..e27d7161d5 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ goto mark2; mark1: diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 402e744e2f..61bd578dcf 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,13 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { i++; printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + if (i % 2 == 0) + { printf("Skipping %i is even\n", i); continue; // This is handled as an goto to line 8 and therefore an up-jumping goto diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index be3e7e12de..41f1dbd5bc 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,14 +1,17 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; - if (i % 2) { + if (i % 2) + { printf("Continue as %i is odd\n", i); continue; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index e2eff29c8b..5cdadf4396 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 756a93414b..cb54b5dd2f 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,15 +1,19 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) { + for (int i = 1; 1; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { printf("Goto as continue for outer loop\n"); goto outer_loop; // Jump to the label "outer_loop" } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index 737b867cde..fbac273776 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -5,14 +5,16 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 278c107821..dad62aa0f4 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -6,10 +6,12 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); - while (1) { + while (1) + { printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); struct timespec sleepTime; sleepTime.tv_sec = 1; // Seconds @@ -21,7 +23,8 @@ void *printPID(void *arg) { return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 3384ed0f60..709960640f 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 646f39111a..f564354e51 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 533778332f..7336417c91 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,9 +1,11 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 0) { + if (n == 0) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 089a4d3bcc..38aaf3de85 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,9 +1,11 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 30) { + if (n == 30) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index eace365a44..bef05eb1a0 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,8 +1,10 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction(int n) { - if (n == 0) { +void innerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating inner recursion\n"); return; } @@ -13,8 +15,10 @@ void innerRecursiveFunction(int n) { innerRecursiveFunction(n - 1); } -void outerRecursiveFunction(int n) { - if (n == 0) { +void outerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating outer recursion\n"); return; } @@ -28,7 +32,8 @@ void outerRecursiveFunction(int n) { innerRecursiveFunction(n); } -int main() { +int main() +{ // Call the outerRecursiveFunction with an initial value outerRecursiveFunction(3); diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8b57f83857..8311d9f573 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,14 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() { +void innerRecursiveFunction() +{ printf("Nested recursive call\n"); // Recursive call to the innerRecursiveFunction innerRecursiveFunction(); } -void outerRecursiveFunction() { +void outerRecursiveFunction() +{ printf("Outer recursive call\n"); // Recursive call to the outerRecursiveFunction @@ -18,7 +20,8 @@ void outerRecursiveFunction() { innerRecursiveFunction(); } -int main() { +int main() +{ // Call the outerRecursiveFunction outerRecursiveFunction(); diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index d5fe6b808a..a74c863fb4 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,12 +1,15 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; // Loop with a continue statement - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { continue; } printf("%d ", i); @@ -14,8 +17,10 @@ int main() { printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) { - if (i > 5 && i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } } @@ -23,8 +28,10 @@ int main() { // Loop with complex conditions i = 1; - while (i <= 10) { - if (i > 5 && i % 2 == 0) { + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } i++; diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 272be43293..1fb9f83f5d 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,11 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ // Loop with a continue statement - for (int r = 1; r <= 10; r++) { - if (r % 3 == 0) { + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { continue; } printf("Loop with Continue: %d\n", r); @@ -13,14 +16,16 @@ int main() { // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) { + while (s <= 10 && s % 2 == 0) + { printf("Loop with Multiple Conditions: %d\n", s); s++; } // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { printf("Loop with Multiple Variables: %d %d\n", t, u); } } \ No newline at end of file From 4dd330ce4c530b68f1b2f4722c89c3e44c289a1f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:55:45 +0200 Subject: [PATCH 234/628] Execute termination tests in CI even if skipped. --- .github/workflows/locked.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/locked.yml b/.github/workflows/locked.yml index 751ade6880..48809d34c1 100644 --- a/.github/workflows/locked.yml +++ b/.github/workflows/locked.yml @@ -64,6 +64,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From 5f984170bd0de91e79d972be599896a637037a84 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 20:51:13 +0200 Subject: [PATCH 235/628] Test explanation && new test case termination 43 --- ...-multi-expression-conditions-terminating.c | 44 +++++++++++++++++++ ...itions.c => 41-for-continue-terminating.c} | 25 +++-------- .../regression/75-termination/41-more-tests.c | 31 ------------- .../43-return-from-endless-loop-terminating.c | 14 ++++++ 4 files changed, 64 insertions(+), 50 deletions(-) create mode 100644 tests/regression/75-termination/40-multi-expression-conditions-terminating.c rename tests/regression/75-termination/{40-complex-conditions.c => 41-for-continue-terminating.c} (52%) delete mode 100644 tests/regression/75-termination/41-more-tests.c create mode 100644 tests/regression/75-termination/43-return-from-endless-loop-terminating.c diff --git a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c new file mode 100644 index 0000000000..8e7b4e273d --- /dev/null +++ b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c @@ -0,0 +1,44 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + // Loop with complex conditions + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) + { + if (i > 5 && i % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // CIL defines new jump labels to default location (-1) + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } +} \ No newline at end of file diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/41-for-continue-terminating.c similarity index 52% rename from tests/regression/75-termination/40-complex-conditions.c rename to tests/regression/75-termination/41-for-continue-terminating.c index a74c863fb4..1d109c4ee7 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -3,38 +3,25 @@ int main() { - int i; - // Loop with a continue statement for (i = 1; i <= 10; i++) { if (i % 2 == 0) { - continue; + continue; // Converted to an goto to "for" in line 7 } printf("%d ", i); } printf("\n"); - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - } - printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) + // Loop with a continue statement + for (int r = 1; r <= 10; r++) { - if (i > 5 && i % 2 == 0) + if (r % 3 == 0) { - printf("%d ", i); + continue; // Converted to an goto to "for" in line 19 } - i++; + printf("Loop with Continue: %d\n", r); } - printf("\n"); } \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c deleted file mode 100644 index 1fb9f83f5d..0000000000 --- a/tests/regression/75-termination/41-more-tests.c +++ /dev/null @@ -1,31 +0,0 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include - -int main() -{ - - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); - } - - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } - - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } -} \ No newline at end of file diff --git a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c new file mode 100644 index 0000000000..06bda24bd7 --- /dev/null +++ b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c @@ -0,0 +1,14 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int i = 1; + + while (i != 0) { + printf("%d\n", i); + i++; + if (i>10) { + return 0; + } + } +} From 76f540ffea9d19b7c9dc711047774900892c850d Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 20:58:17 +0200 Subject: [PATCH 236/628] Test explanation && new test case termination 43 --- tests/regression/75-termination/41-for-continue-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-termination/41-for-continue-terminating.c b/tests/regression/75-termination/41-for-continue-terminating.c index 1d109c4ee7..1d3b96fcf8 100644 --- a/tests/regression/75-termination/41-for-continue-terminating.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -4,7 +4,7 @@ int main() { // Loop with a continue statement - for (i = 1; i <= 10; i++) + for (int i = 1; i <= 10; i++) { if (i % 2 == 0) { From 40ea15c5a2d3691bfa047701e09e45bcec161799 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 13 Jul 2023 22:27:45 +0200 Subject: [PATCH 237/628] Added special function --Still work in progress --- src/analyses/libraryDesc.ml | 1 + src/util/terminationPreprocessing.ml | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 8b90553e95..0ac3e87f96 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,6 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } + | Bounded of { var: Cil.exp} | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4043c6d256..1aa78ccae7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,6 +3,19 @@ include Printf module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +let specialFunction name = + print_endline @@ "specialfunction done"; + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } + +let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,11 +48,12 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: check_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: check_stmt :: ss; + b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 30692fc5d626c99c5b120502009e7e88c546d14e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 22:47:22 +0200 Subject: [PATCH 238/628] Test for code line detection --- scripts/update_suite.rb | 45 +++++++++++-------- src/analyses/loopTermination.ml | 6 +-- src/framework/constraints.ml | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../75-termination/17-goto-terminating.c | 3 +- .../75-termination/18-goto-nonterminating.c | 2 +- .../75-termination/20-rand-nonterminating.c | 4 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 5 +-- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 4 +- .../29-do-while-continue-nonterminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 4 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../37-recursion-nonterminating.c | 2 +- .../39-recursion-nested-nonterminating.c | 4 +- 22 files changed, 56 insertions(+), 47 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 8841ecea88..60a7ec06be 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -149,24 +149,27 @@ def collect_warnings next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" end oldwarn = warnings[i] @@ -206,7 +209,7 @@ def compare_warnings end } case type - when "deadlock", "race", "fail", "unknown", "warn" + when "goto", "fundec", "loop", "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type when "nonterm" check.call warnings[idx] == type @@ -309,6 +312,12 @@ def parse_tests (lines) tests[i] = "success" elsif obj =~ /FAIL/ then tests[i] = "fail" + elsif obj =~ /NONTERMLOOP/ then + tests[i] = "loop" + elsif obj =~ /NONTERMGOTO/ then + tests[i] = "goto" + elsif obj =~ /NONTERMFUNDEC/ then + tests[i] = "fundec" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" elsif obj =~ /(assert|__goblint_check).*\(/ then diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 367c3a328c..44caf5c90a 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -70,13 +70,13 @@ struct List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", Some (M.Location.CilLocation x));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)" ) @@ -93,7 +93,7 @@ struct (* In case the loop is not bounded, a warning is created*) if not (is_bounded) then ( let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + [(Pretty.dprintf "The program might not terminate! (Loop analysis)", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6114f30adb..3d10248885 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1797,7 +1797,7 @@ struct (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 51fb340f3b..c6e1c6c8d6 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -3,7 +3,7 @@ int main() { - while (1) + while (1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { continue; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index fffc932f36..21a6d47051 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -9,7 +9,7 @@ int main() { int innerCount = 1; - while (1) + while (1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index be876c9741..0f96209e35 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -3,7 +3,7 @@ int main() { - for (;;) + for (;;) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e360d45d0a..ec76f31534 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) + for (innerCount = 1;; innerCount++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 30c8349bb5..5522b61d88 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -9,7 +9,7 @@ int main() { printf("Inside the do-while loop\n"); i++; - } while (i >= 2); + } while (i >= 2); // NONTERMLOOP termination analysis shall mark while as non-terminating loop printf("Exited the loop\n"); return 0; diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index 87b4b82ed9..bded788a90 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -9,7 +9,7 @@ int main() { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) + while (outerCount < 3 || innerCount > 0) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 45e92f32e8..941db0c601 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -12,7 +12,8 @@ int main() if (num <= 10) { - goto loop; // We are not able to detect up-jumping gotos as terminating, we + goto loop; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto + // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index 25f79e5b57..f88088ad12 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -9,7 +9,7 @@ int main() printf("Current number: %d\n", num); num++; - goto loop; + goto loop; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto return 0; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 83630ed6c4..394bce7709 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i >= 0; i++) + for (int i = 1; i >= 0; i++) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j > 0) + while (j > 0) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("Loop inside else part: %d\n", j); } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 3e7a65dfd4..902ef2a4e2 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -6,7 +6,7 @@ int main() int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) + while (i < 4 || forever == 1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { i++; if (i == 4) diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index b8d7992bd9..f14f7d4e3f 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -6,7 +6,7 @@ int main() int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) + while (forever == 1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { if (rand()) // May exit, may not { diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 24d4980406..013aff2dd5 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -5,9 +5,8 @@ int main() { int short_run, i = 0; - - while (i < 90 && - short_run != 1) // Currently not able to detect this as terminating + // Currently not able to detect this as terminating due to multiple conditions + while (i < 90 && short_run != 1) { i++; if (rand()) diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 3dbff9d7ea..3f4e115445 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -12,7 +12,7 @@ int main() mark2: printf("This is mark2\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto mark3: printf("This is mark3\n"); diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index e27d7161d5..5ce295872c 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -11,11 +11,11 @@ int main() mark2: printf("This is mark2\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto mark3: printf("This is mark3\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto return 0; } diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 41f1dbd5bc..34766ab2e7 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -15,7 +15,7 @@ int main() printf("Continue as %i is odd\n", i); continue; } - } while (i >= 2); + } while (i >= 2); // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop printf("Exited the loop\n"); return 0; diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index cb54b5dd2f..d7ff329396 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) + for (int i = 1; 1; i++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { // Inner loop for columns for (int j = 1; j <= columns; j++) @@ -15,7 +15,7 @@ int main() if (j == 3) { printf("Goto as continue for outer loop\n"); - goto outer_loop; // Jump to the label "outer_loop" + goto outer_loop; } printf("(%d, %d) ", i, j); } diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 709960640f..24605ad478 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) + for (innerCount = 1; innerCount > 0; innerCount++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 38aaf3de85..21316de9bd 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,7 +1,7 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) +void recursiveFunction(int n) // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { // Base case: When n reaches 0, stop recursion if (n == 30) diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8311d9f573..b3aa8bf21b 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,7 +1,7 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() +void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { printf("Nested recursive call\n"); @@ -9,7 +9,7 @@ void innerRecursiveFunction() innerRecursiveFunction(); } -void outerRecursiveFunction() +void outerRecursiveFunction() // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { printf("Outer recursive call\n"); From dc0a284ccc4c6337db5458882345a6aa126cf3bc Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 13 Jul 2023 23:42:13 +0200 Subject: [PATCH 239/628] changed __goblint_bounded constructor from Assert to Bounded --- src/analyses/libraryDesc.ml | 2 +- src/analyses/libraryFunctions.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 0ac3e87f96..3896e74574 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,7 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } - | Bounded of { var: Cil.exp} + | Bounded of { exp: Cil.exp} | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 5d65cf9cb3..045268ca4d 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -303,7 +303,7 @@ let goblint_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__goblint_assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); ("__goblint_split_begin", unknown [drop "exp" []]); ("__goblint_split_end", unknown [drop "exp" []]); - ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Assert { exp; check = true; refine = false }); + ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Bounded { exp }); ] (** zstd functions. From 1f499e99f91a5345105fd873f08fc00758336e5d Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:31:05 +0200 Subject: [PATCH 240/628] Use special function instead of variable indicator We now use __goblint_bounded to mark the place where the value of the loop counter variable shall be checked for being bounded. Before, we used a variable called loop exit indicator for that. --- src/analyses/loopTermination.ml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 367c3a328c..307e76211d 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,6 +4,7 @@ open Analyses open GoblintCil open TerminationPreprocessing +(* TODO: Remove *) exception PreProcessing of string (** Stores the result of the query if the program is single threaded or not @@ -40,7 +41,7 @@ let check_bounded ctx varinfo = (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a * lattice. *) -module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = @@ -79,7 +80,7 @@ struct M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) - + (* let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -98,21 +99,23 @@ struct () | _ -> () else () + *) - (* let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = - (* TODO: Implement check for our special loop exit indicator function *) if !AnalysisState.postsolving then match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> - let () = print_endline "schpecial" in let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created*) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () else () - *) (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From b9a5b3fdda1cc2a216937206cd60d89d6a6849a0 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:44:28 +0200 Subject: [PATCH 241/628] Clean up, make things look nicer --- src/analyses/loopTermination.ml | 42 ++++++++++----------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 307e76211d..beb1cbfd06 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -23,9 +23,6 @@ let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = VarToStmt.mem x !loop_counters -let is_loop_exit_indicator (x : varinfo) = - x = !loop_exit - let no_upjumping_gotos () = upjumping_gotos.contents = [] @@ -65,42 +62,24 @@ struct let exitstate = startstate let finalize () = - (* warning for detected possible non-termination *) - (*upjumping gotos *) + (* Warning for detected possible non-termination *) + (* Upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + [(Pretty.dprintf + "The program might not terminate! (Upjumping Goto)\n", + Some (M.Location.CilLocation x) + );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) ); - (* multithreaded *) + (* Multithreaded *) if not (!single_thread) then ( M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) - (* - let assign ctx (lval : lval) (rval : exp) = - if !AnalysisState.postsolving then - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created*) - if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - () - | _ -> () - else () - *) - let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with @@ -108,10 +87,13 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created*) + (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + [(Pretty.dprintf + "The program might not terminate! (Loop analysis)\n", + Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) + );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () From 6146c760cbf6279e7055448820ab4f5c787ecc4a Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:54:19 +0200 Subject: [PATCH 242/628] Wrap always_single_threaded in let-in clause --- src/analyses/loopTermination.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index beb1cbfd06..0211cc9cb5 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -115,10 +115,12 @@ struct Some b -> b | None -> false) | Queries.MustTermAllLoops -> + let always_single_threaded = must_be_single_threaded_since_start ctx in (* Must be the first to be evaluated! This has the side effect that * single_thread is set. In case of another order and due to lazy - * evaluation the correct value of single_thread can not be guaranteed! *) - must_be_single_threaded_since_start ctx + * evaluation, the correct value of single_thread can not be guaranteed! + * Therefore, we use a let-in clause here. *) + always_single_threaded && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From 847ea368bc746551371286a36bb4c3263294f962 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 15:55:43 +0200 Subject: [PATCH 243/628] Remove PreProcessing exception --- src/analyses/loopTermination.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 0211cc9cb5..942d38c0f3 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,9 +4,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -(* TODO: Remove *) -exception PreProcessing of string - (** Stores the result of the query if the program is single threaded or not since finalize does not has ctx as an argument*) let single_thread : bool ref = ref false @@ -33,7 +30,7 @@ let check_bounded ctx varinfo = match ctx.ask (EvalInt exp) with | `Top -> false | `Lifted v -> not (is_top_of (ikind v) v) - | `Bot -> raise (PreProcessing "Loop variable is Bot") + | `Bot -> failwith "Loop counter variable is Bot." (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a From 0a9c5d432888750cf0d860a6568fcb887cedc12f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 15 Jul 2023 14:54:57 +0200 Subject: [PATCH 244/628] Fix indentation --- src/analyses/base.ml | 578 +++++++++++++++++++++---------------------- 1 file changed, 289 insertions(+), 289 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 3a231ea396..fa45a7c38d 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2064,307 +2064,307 @@ struct s1_a, s1_typ, VD.top_value (unrollType s1_typ) in let st = match desc.special args, f.vname with - | Memset { dest; ch; count; }, _ -> - (* TODO: check count *) - let eval_ch = eval_rv (Analyses.ask_of_ctx ctx) gs st ch in - let dest_a, dest_typ = addr_type_of_exp dest in - let value = - match eval_ch with - | Int i when ID.to_int i = Some Z.zero -> - VD.zero_init_value dest_typ - | _ -> - VD.top_value dest_typ - in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Bzero { dest; count; }, _ -> - (* TODO: share something with memset special case? *) - (* TODO: check count *) - let dest_a, dest_typ = addr_type_of_exp dest in - let value = VD.zero_init_value dest_typ in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Memcpy { dest = dst; src }, _ -> - memory_copying dst src - (* strcpy(dest, src); *) - | Strcpy { dest = dst; src; n = None }, _ -> - let dest_a, dest_typ = addr_type_of_exp dst in - (* when dest surely isn't a string literal, try copying src to dest *) - if AD.string_writing_defined dest_a then - memory_copying dst src - else - (* else return top (after a warning was issued) *) - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) - (* strncpy(dest, src, n); *) - | Strcpy { dest = dst; src; n }, _ -> - begin match eval_n n with - | Some num -> - let dest_a, dest_typ, value = string_manipulation dst src None false None in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> failwith "already handled in case above" - end - | Strcat { dest = dst; src; n }, _ -> - let dest_a, dest_typ, value = string_manipulation dst src None false None in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Strlen s, _ -> - begin match lv with - | Some lv_val -> - let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st lv_val in - let dest_typ = Cilfacade.typeOfLval lv_val in - let lval = mkMem ~addr:(Cil.stripCasts s) ~off:NoOffset in - let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in - let (value:value) = Int(AD.to_string_length address) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Strstr { haystack; needle }, _ -> - begin match lv with - | Some _ -> - (* when haystack, needle and dest type coincide, check if needle is a substring of haystack: - if that is the case, assign the substring of haystack starting at the first occurrence of needle to dest, - else use top *) - let dest_a, dest_typ, value = string_manipulation haystack needle lv true (Some (fun h_a n_a -> Address(AD.substring_extraction h_a n_a))) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Strcmp { s1; s2; n }, _ -> - begin match lv with - | Some _ -> - (* when s1 and s2 type coincide, compare both both strings completely or their first n characters, otherwise use top *) - let dest_a, dest_typ, value = string_manipulation s1 s2 lv false (Some (fun s1_a s2_a -> Int(AD.string_comparison s1_a s2_a (eval_n n)))) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Abort, _ -> raise Deadcode - | ThreadExit { ret_val = exp }, _ -> - begin match ThreadId.get_current (Analyses.ask_of_ctx ctx) with - | `Lifted tid -> - ( - let rv = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in - ctx.sideg (V.thread tid) (G.create_thread rv); - (* TODO: emit thread return event so other analyses are aware? *) - (* TODO: publish still needed? *) - publish_all ctx `Return; (* like normal return *) - match ThreadId.get_current (Analyses.ask_of_ctx ctx) with - | `Lifted tid when ThreadReturn.is_current (Analyses.ask_of_ctx ctx) -> - ignore @@ Priv.thread_return (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) (priv_sideg ctx.sideg) tid st - | _ -> ()) - | _ -> () - end; - raise Deadcode - | MutexAttrSetType {attr = attr; typ = mtyp}, _ -> - begin - let get_type lval = - let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in - AD.type_of address + | Memset { dest; ch; count; }, _ -> + (* TODO: check count *) + let eval_ch = eval_rv (Analyses.ask_of_ctx ctx) gs st ch in + let dest_a, dest_typ = addr_type_of_exp dest in + let value = + match eval_ch with + | Int i when ID.to_int i = Some Z.zero -> + VD.zero_init_value dest_typ + | _ -> + VD.top_value dest_typ in - let dst_lval = mkMem ~addr:(Cil.stripCasts attr) ~off:NoOffset in - let dest_typ = get_type dst_lval in - let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st dst_lval in - match eval_rv (Analyses.ask_of_ctx ctx) gs st mtyp with - | Int x -> - begin - match ID.to_int x with - | Some z -> - if M.tracing then M.tracel "attr" "setting\n"; - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.of_int z)) - | None -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) - end - | _ -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) - end - | Identity e, _ -> - begin match lv with - | Some x -> assign ctx x e - | None -> ctx.local - end - (**Floating point classification and trigonometric functions defined in c99*) - | Math { fun_args; }, _ -> - let apply_unary fk float_fun x = - let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in - begin match eval_x with - | Float float_x -> float_fun (FD.cast_to fk float_x) - | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Bzero { dest; count; }, _ -> + (* TODO: share something with memset special case? *) + (* TODO: check count *) + let dest_a, dest_typ = addr_type_of_exp dest in + let value = VD.zero_init_value dest_typ in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Memcpy { dest = dst; src }, _ -> + memory_copying dst src + (* strcpy(dest, src); *) + | Strcpy { dest = dst; src; n = None }, _ -> + let dest_a, dest_typ = addr_type_of_exp dst in + (* when dest surely isn't a string literal, try copying src to dest *) + if AD.string_writing_defined dest_a then + memory_copying dst src + else + (* else return top (after a warning was issued) *) + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) + (* strncpy(dest, src, n); *) + | Strcpy { dest = dst; src; n }, _ -> + begin match eval_n n with + | Some num -> + let dest_a, dest_typ, value = string_manipulation dst src None false None in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> failwith "already handled in case above" end - in - let apply_binary fk float_fun x y = - let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in - let eval_y = eval_rv (Analyses.ask_of_ctx ctx) gs st y in - begin match eval_x, eval_y with - | Float float_x, Float float_y -> float_fun (FD.cast_to fk float_x) (FD.cast_to fk float_y) - | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + | Strcat { dest = dst; src; n }, _ -> + let dest_a, dest_typ, value = string_manipulation dst src None false None in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Strlen s, _ -> + begin match lv with + | Some lv_val -> + let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st lv_val in + let dest_typ = Cilfacade.typeOfLval lv_val in + let lval = mkMem ~addr:(Cil.stripCasts s) ~off:NoOffset in + let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in + let (value:value) = Int(AD.to_string_length address) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st end - in - let result:value = - begin match fun_args with - | Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk) - | Nan _ -> failwith ("non-pointer argument in call to function "^f.vname) - | Inf fk -> Float (FD.inf_of fk) - | Isfinite x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isfinite x)) - | Isinf x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isinf x)) - | Isnan x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnan x)) - | Isnormal x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnormal x)) - | Signbit x -> Int (ID.cast_to IInt (apply_unary FDouble FD.signbit x)) - | Ceil (fk,x) -> Float (apply_unary fk FD.ceil x) - | Floor (fk,x) -> Float (apply_unary fk FD.floor x) - | Fabs (fk, x) -> Float (apply_unary fk FD.fabs x) - | Acos (fk, x) -> Float (apply_unary fk FD.acos x) - | Asin (fk, x) -> Float (apply_unary fk FD.asin x) - | Atan (fk, x) -> Float (apply_unary fk FD.atan x) - | Atan2 (fk, y, x) -> Float (apply_binary fk (fun y' x' -> FD.atan (FD.div y' x')) y x) - | Cos (fk, x) -> Float (apply_unary fk FD.cos x) - | Sin (fk, x) -> Float (apply_unary fk FD.sin x) - | Tan (fk, x) -> Float (apply_unary fk FD.tan x) - | Isgreater (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.gt x y)) - | Isgreaterequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.ge x y)) - | Isless (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.lt x y)) - | Islessequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.le x y)) - | Islessgreater (x,y) -> Int(ID.logor (ID.cast_to IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to IInt (apply_binary FDouble FD.gt x y))) - | Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y)) - | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) - | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) + | Strstr { haystack; needle }, _ -> + begin match lv with + | Some _ -> + (* when haystack, needle and dest type coincide, check if needle is a substring of haystack: + if that is the case, assign the substring of haystack starting at the first occurrence of needle to dest, + else use top *) + let dest_a, dest_typ, value = string_manipulation haystack needle lv true (Some (fun h_a n_a -> Address(AD.substring_extraction h_a n_a))) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st end - in - begin match lv with - | Some lv_val -> set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st lv_val) (Cilfacade.typeOfLval lv_val) result - | None -> st - end - (* handling thread creations *) - | ThreadCreate _, _ -> - invalidate_ret_lv ctx.local (* actual results joined via threadspawn *) - (* handling thread joins... sort of *) - | ThreadJoin { thread = id; ret_var }, _ -> - let st' = - match (eval_rv (Analyses.ask_of_ctx ctx) gs st ret_var) with - | Int n when GobOption.exists (BI.equal BI.zero) (ID.to_int n) -> st - | Address ret_a -> - begin match eval_rv (Analyses.ask_of_ctx ctx) gs st id with - | Thread a -> - let v = List.fold VD.join (VD.bot ()) (List.map (fun x -> G.thread (ctx.global (V.thread x))) (ValueDomain.Threads.elements a)) in - (* TODO: is this type right? *) - set ~ctx (Analyses.ask_of_ctx ctx) gs st ret_a (Cilfacade.typeOf ret_var) v - | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] - end - | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] - in - let st' = invalidate_ret_lv st' in - Priv.thread_join (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st' - | Unknown, "__goblint_assume_join" -> - let id = List.hd args in - Priv.thread_join ~force:true (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st - | Malloc size, _ -> begin - match lv with - | Some lv -> - let heap_var = - if (get_bool "sem.malloc.fail") - then AD.join (AD.of_var (heap_var ctx)) AD.null_ptr - else AD.of_var (heap_var ctx) - in - (* ignore @@ printf "malloc will allocate %a bytes\n" ID.pretty (eval_int ctx.ask gs st size); *) - set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(heap_var, TVoid [], Blob (VD.bot (), eval_int (Analyses.ask_of_ctx ctx) gs st size, true)); - (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address heap_var)] - | _ -> st - end - | Calloc { count = n; size }, _ -> - begin match lv with - | Some lv -> (* array length is set to one, as num*size is done when turning into `Calloc *) - let heap_var = heap_var ctx in - let add_null addr = - if get_bool "sem.malloc.fail" - then AD.join addr AD.null_ptr (* calloc can fail and return NULL *) - else addr in - let ik = Cilfacade.ptrdiff_ikind () in - let blobsize = ID.mul (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st size) (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st n) in - (* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *) - set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false)))); - (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))] - | _ -> st - end - | Realloc { ptr = p; size }, _ -> - begin match lv with - | Some lv -> - let ask = Analyses.ask_of_ctx ctx in - let p_rv = eval_rv ask gs st p in - let p_addr = - match p_rv with - | Address a -> a - (* TODO: don't we already have logic for this? *) - | Int i when ID.to_int i = Some BI.zero -> AD.null_ptr - | Int i -> AD.top_ptr - | _ -> AD.top_ptr (* TODO: why does this ever happen? *) - in - let p_addr' = AD.remove NullPtr p_addr in (* realloc with NULL is same as malloc, remove to avoid unknown value from NullPtr access *) - let p_addr_get = get ask gs st p_addr' None in (* implicitly includes join of malloc value (VD.bot) *) - let size_int = eval_int ask gs st size in - let heap_val:value = Blob (p_addr_get, size_int, true) in (* copy old contents with new size *) - let heap_addr = AD.of_var (heap_var ctx) in - let heap_addr' = - if get_bool "sem.malloc.fail" then - AD.join heap_addr AD.null_ptr - else - heap_addr + | Strcmp { s1; s2; n }, _ -> + begin match lv with + | Some _ -> + (* when s1 and s2 type coincide, compare both both strings completely or their first n characters, otherwise use top *) + let dest_a, dest_typ, value = string_manipulation s1 s2 lv false (Some (fun s1_a s2_a -> Int(AD.string_comparison s1_a s2_a (eval_n n)))) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st + end + | Abort, _ -> raise Deadcode + | ThreadExit { ret_val = exp }, _ -> + begin match ThreadId.get_current (Analyses.ask_of_ctx ctx) with + | `Lifted tid -> + ( + let rv = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in + ctx.sideg (V.thread tid) (G.create_thread rv); + (* TODO: emit thread return event so other analyses are aware? *) + (* TODO: publish still needed? *) + publish_all ctx `Return; (* like normal return *) + match ThreadId.get_current (Analyses.ask_of_ctx ctx) with + | `Lifted tid when ThreadReturn.is_current (Analyses.ask_of_ctx ctx) -> + ignore @@ Priv.thread_return (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) (priv_sideg ctx.sideg) tid st + | _ -> ()) + | _ -> () + end; + raise Deadcode + | MutexAttrSetType {attr = attr; typ = mtyp}, _ -> + begin + let get_type lval = + let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in + AD.type_of address in - let lv_addr = eval_lv ask gs st lv in - set_many ~ctx ask gs st [ - (heap_addr, TVoid [], heap_val); - (lv_addr, Cilfacade.typeOfLval lv, Address heap_addr'); - ] (* TODO: free (i.e. invalidate) old blob if successful? *) - | None -> - st - end - | Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine - | Setjmp { env }, _ -> - let ask = Analyses.ask_of_ctx ctx in - let st' = match eval_rv ask gs st env with - | Address jmp_buf -> - let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false) in - let r = set ~ctx ask gs st jmp_buf (Cilfacade.typeOf env) value in - if M.tracing then M.tracel "setjmp" "setting setjmp %a on %a -> %a\n" d_exp env D.pretty st D.pretty r; - r - | _ -> failwith "problem?!" - in - begin match lv with - | Some lv -> - set ~ctx ask gs st' (eval_lv ask ctx.global st lv) (Cilfacade.typeOfLval lv) (Int (ID.of_int IInt BI.zero)) - | None -> st' - end - | Longjmp {env; value}, _ -> - let ask = Analyses.ask_of_ctx ctx in - let ensure_not_zero (rv:value) = match rv with - | Int i -> - begin match ID.to_bool i with - | Some true -> rv - | Some false -> - M.error "Must: Longjmp with a value of 0 is silently changed to 1"; - Int (ID.of_int (ID.ikind i) Z.one) - | None -> - M.warn "May: Longjmp with a value of 0 is silently changed to 1"; - let ik = ID.ikind i in - Int (ID.join (ID.meet i (ID.of_excl_list ik [Z.zero])) (ID.of_int ik Z.one)) + let dst_lval = mkMem ~addr:(Cil.stripCasts attr) ~off:NoOffset in + let dest_typ = get_type dst_lval in + let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st dst_lval in + match eval_rv (Analyses.ask_of_ctx ctx) gs st mtyp with + | Int x -> + begin + match ID.to_int x with + | Some z -> + if M.tracing then M.tracel "attr" "setting\n"; + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.of_int z)) + | None -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) + end + | _ -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) + end + | Identity e, _ -> + begin match lv with + | Some x -> assign ctx x e + | None -> ctx.local + end + (**Floating point classification and trigonometric functions defined in c99*) + | Math { fun_args; }, _ -> + let apply_unary fk float_fun x = + let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in + begin match eval_x with + | Float float_x -> float_fun (FD.cast_to fk float_x) + | _ -> failwith ("non-floating-point argument in call to function "^f.vname) end - | _ -> - M.warn ~category:Program "Arguments to longjmp are strange!"; - rv - in - let rv = ensure_not_zero @@ eval_rv ask ctx.global ctx.local value in - let t = Cilfacade.typeOf value in - set ~ctx ~t_override:t ask ctx.global ctx.local (AD.of_var !longjmp_return) t rv (* Not raising Deadcode here, deadcode is raised at a higher level! *) - | Rand, _ -> - begin match lv with - | Some x -> - let result:value = (Int (ID.starting IInt Z.zero)) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result - | None -> st - end - | _, _ -> - let st = - special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) gs st f args + in + let apply_binary fk float_fun x y = + let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in + let eval_y = eval_rv (Analyses.ask_of_ctx ctx) gs st y in + begin match eval_x, eval_y with + | Float float_x, Float float_y -> float_fun (FD.cast_to fk float_x) (FD.cast_to fk float_y) + | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + end + in + let result:value = + begin match fun_args with + | Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk) + | Nan _ -> failwith ("non-pointer argument in call to function "^f.vname) + | Inf fk -> Float (FD.inf_of fk) + | Isfinite x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isfinite x)) + | Isinf x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isinf x)) + | Isnan x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnan x)) + | Isnormal x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnormal x)) + | Signbit x -> Int (ID.cast_to IInt (apply_unary FDouble FD.signbit x)) + | Ceil (fk,x) -> Float (apply_unary fk FD.ceil x) + | Floor (fk,x) -> Float (apply_unary fk FD.floor x) + | Fabs (fk, x) -> Float (apply_unary fk FD.fabs x) + | Acos (fk, x) -> Float (apply_unary fk FD.acos x) + | Asin (fk, x) -> Float (apply_unary fk FD.asin x) + | Atan (fk, x) -> Float (apply_unary fk FD.atan x) + | Atan2 (fk, y, x) -> Float (apply_binary fk (fun y' x' -> FD.atan (FD.div y' x')) y x) + | Cos (fk, x) -> Float (apply_unary fk FD.cos x) + | Sin (fk, x) -> Float (apply_unary fk FD.sin x) + | Tan (fk, x) -> Float (apply_unary fk FD.tan x) + | Isgreater (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.gt x y)) + | Isgreaterequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.ge x y)) + | Isless (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.lt x y)) + | Islessequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.le x y)) + | Islessgreater (x,y) -> Int(ID.logor (ID.cast_to IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to IInt (apply_binary FDouble FD.gt x y))) + | Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y)) + | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) + | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) + end + in + begin match lv with + | Some lv_val -> set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st lv_val) (Cilfacade.typeOfLval lv_val) result + | None -> st + end + (* handling thread creations *) + | ThreadCreate _, _ -> + invalidate_ret_lv ctx.local (* actual results joined via threadspawn *) + (* handling thread joins... sort of *) + | ThreadJoin { thread = id; ret_var }, _ -> + let st' = + match (eval_rv (Analyses.ask_of_ctx ctx) gs st ret_var) with + | Int n when GobOption.exists (BI.equal BI.zero) (ID.to_int n) -> st + | Address ret_a -> + begin match eval_rv (Analyses.ask_of_ctx ctx) gs st id with + | Thread a -> + let v = List.fold VD.join (VD.bot ()) (List.map (fun x -> G.thread (ctx.global (V.thread x))) (ValueDomain.Threads.elements a)) in + (* TODO: is this type right? *) + set ~ctx (Analyses.ask_of_ctx ctx) gs st ret_a (Cilfacade.typeOf ret_var) v + | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] + end + | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] + in + let st' = invalidate_ret_lv st' in + Priv.thread_join (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st' + | Unknown, "__goblint_assume_join" -> + let id = List.hd args in + Priv.thread_join ~force:true (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st + | Malloc size, _ -> begin + match lv with + | Some lv -> + let heap_var = + if (get_bool "sem.malloc.fail") + then AD.join (AD.of_var (heap_var ctx)) AD.null_ptr + else AD.of_var (heap_var ctx) + in + (* ignore @@ printf "malloc will allocate %a bytes\n" ID.pretty (eval_int ctx.ask gs st size); *) + set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(heap_var, TVoid [], Blob (VD.bot (), eval_int (Analyses.ask_of_ctx ctx) gs st size, true)); + (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address heap_var)] + | _ -> st + end + | Calloc { count = n; size }, _ -> + begin match lv with + | Some lv -> (* array length is set to one, as num*size is done when turning into `Calloc *) + let heap_var = heap_var ctx in + let add_null addr = + if get_bool "sem.malloc.fail" + then AD.join addr AD.null_ptr (* calloc can fail and return NULL *) + else addr in + let ik = Cilfacade.ptrdiff_ikind () in + let blobsize = ID.mul (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st size) (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st n) in + (* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *) + set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false)))); + (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))] + | _ -> st + end + | Realloc { ptr = p; size }, _ -> + begin match lv with + | Some lv -> + let ask = Analyses.ask_of_ctx ctx in + let p_rv = eval_rv ask gs st p in + let p_addr = + match p_rv with + | Address a -> a + (* TODO: don't we already have logic for this? *) + | Int i when ID.to_int i = Some BI.zero -> AD.null_ptr + | Int i -> AD.top_ptr + | _ -> AD.top_ptr (* TODO: why does this ever happen? *) + in + let p_addr' = AD.remove NullPtr p_addr in (* realloc with NULL is same as malloc, remove to avoid unknown value from NullPtr access *) + let p_addr_get = get ask gs st p_addr' None in (* implicitly includes join of malloc value (VD.bot) *) + let size_int = eval_int ask gs st size in + let heap_val:value = Blob (p_addr_get, size_int, true) in (* copy old contents with new size *) + let heap_addr = AD.of_var (heap_var ctx) in + let heap_addr' = + if get_bool "sem.malloc.fail" then + AD.join heap_addr AD.null_ptr + else + heap_addr + in + let lv_addr = eval_lv ask gs st lv in + set_many ~ctx ask gs st [ + (heap_addr, TVoid [], heap_val); + (lv_addr, Cilfacade.typeOfLval lv, Address heap_addr'); + ] (* TODO: free (i.e. invalidate) old blob if successful? *) + | None -> + st + end + | Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine + | Setjmp { env }, _ -> + let ask = Analyses.ask_of_ctx ctx in + let st' = match eval_rv ask gs st env with + | Address jmp_buf -> + let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false) in + let r = set ~ctx ask gs st jmp_buf (Cilfacade.typeOf env) value in + if M.tracing then M.tracel "setjmp" "setting setjmp %a on %a -> %a\n" d_exp env D.pretty st D.pretty r; + r + | _ -> failwith "problem?!" + in + begin match lv with + | Some lv -> + set ~ctx ask gs st' (eval_lv ask ctx.global st lv) (Cilfacade.typeOfLval lv) (Int (ID.of_int IInt BI.zero)) + | None -> st' + end + | Longjmp {env; value}, _ -> + let ask = Analyses.ask_of_ctx ctx in + let ensure_not_zero (rv:value) = match rv with + | Int i -> + begin match ID.to_bool i with + | Some true -> rv + | Some false -> + M.error "Must: Longjmp with a value of 0 is silently changed to 1"; + Int (ID.of_int (ID.ikind i) Z.one) + | None -> + M.warn "May: Longjmp with a value of 0 is silently changed to 1"; + let ik = ID.ikind i in + Int (ID.join (ID.meet i (ID.of_excl_list ik [Z.zero])) (ID.of_int ik Z.one)) + end + | _ -> + M.warn ~category:Program "Arguments to longjmp are strange!"; + rv + in + let rv = ensure_not_zero @@ eval_rv ask ctx.global ctx.local value in + let t = Cilfacade.typeOf value in + set ~ctx ~t_override:t ask ctx.global ctx.local (AD.of_var !longjmp_return) t rv (* Not raising Deadcode here, deadcode is raised at a higher level! *) + | Rand, _ -> + begin match lv with + | Some x -> + let result:value = (Int (ID.starting IInt Z.zero)) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result + | None -> st + end + | _, _ -> + let st = + special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) gs st f args (* * TODO: invalidate vars reachable via args * publish globals * if single-threaded: *call f*, privatize globals * else: spawn f *) - in - (* invalidate lhs in case of assign *) - invalidate_ret_lv st + in + (* invalidate lhs in case of assign *) + invalidate_ret_lv st in if get_bool "sem.noreturn.dead_code" && Cil.hasAttribute "noreturn" f.vattr then raise Deadcode else st From 10260bde16acbb131cd2053eefe0099cf4ca03b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 16 Jul 2023 11:59:32 +0200 Subject: [PATCH 245/628] Added more recursive tests --- ...recursion-multiple-functions-terminating.c | 40 +++++++++++++++++++ ...ursion-multiple-functions-nonterminating.c | 40 +++++++++++++++++++ ...-recursion-different-context-terminating.c | 32 +++++++++++++++ ...cursion-different-context-nonterminating.c | 32 +++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 tests/regression/75-termination/44-recursion-multiple-functions-terminating.c create mode 100644 tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c create mode 100644 tests/regression/75-termination/46-recursion-different-context-terminating.c create mode 100644 tests/regression/75-termination/47-recursion-different-context-nonterminating.c diff --git a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c new file mode 100644 index 0000000000..c112c72a73 --- /dev/null +++ b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c @@ -0,0 +1,40 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionB(int n); +void functionC(int n); +void functionD(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionB(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionD(n - 1); + } +} + +void functionD(int n) { + if (n > 0) { + printf("Function D: %d\n", n); + functionA(n - 1); + } +} + +int main() { + int n = 15; + functionA(n); + return 0; +} diff --git a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c new file mode 100644 index 0000000000..47c13c0dca --- /dev/null +++ b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c @@ -0,0 +1,40 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionB(int n); +void functionC(int n); +void functionD(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionB(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionD(n + 1); + } +} + +void functionD(int n) { + if (n > 0) { + printf("Function D: %d\n", n); + functionA(n + 1); + } +} + +int main() { + int n = 15; + functionA(n); + return 0; +} diff --git a/tests/regression/75-termination/46-recursion-different-context-terminating.c b/tests/regression/75-termination/46-recursion-different-context-terminating.c new file mode 100644 index 0000000000..4c5dd13035 --- /dev/null +++ b/tests/regression/75-termination/46-recursion-different-context-terminating.c @@ -0,0 +1,32 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionC(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionC(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionC(n - 1); + } +} + +int main() { + int n = 5; + functionA(n + 1); + functionB(n + 7); + return 0; +} diff --git a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c new file mode 100644 index 0000000000..3216275748 --- /dev/null +++ b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c @@ -0,0 +1,32 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionC(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionC(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionC(n); + } +} + +int main() { + int n = 5; + functionA(n + 1); + functionB(n + 7); + return 0; +} From 4e365110bde212326e7d06867eef1801be85e732 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Sun, 16 Jul 2023 18:36:02 +0200 Subject: [PATCH 246/628] removed exit-indikator variable --- src/analyses/libraryDesc.ml | 2 +- src/analyses/loopTermination.ml | 5 +---- src/util/terminationPreprocessing.ml | 15 +++------------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index c3c8d0f85b..0557dc28a2 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,7 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } - | Bounded of { exp: Cil.exp} + | Bounded of { exp: Cil.exp} (** Used to check for bounds for termination analysis. *) | Rand | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 72743444b0..b07fb143b4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -14,9 +14,6 @@ let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] -(** Indicates the place in the code, right after a loop is exited. *) -let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) - let is_loop_counter_var (x : varinfo) = VarToStmt.mem x !loop_counters @@ -126,6 +123,6 @@ end let () = (* Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos loop_exit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1aa78ccae7..1432a2da98 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,5 +1,4 @@ open GoblintCil -include Printf module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) @@ -29,15 +28,8 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg le (fd : fundec) = object(self) +class loopCounterVisitor lc lg (fd : fundec) = object(self) inherit nopCilVisitor - method! vfunc (f:fundec) = - if !le.vname <> "term_exit-" then begin - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeGlobalVar exit_name typ; - end; - DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -46,14 +38,13 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: ss; + b.bstmts <- inc_stmt :: exit_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From d47e88e795b453c8453d75526f6b6f6cb59de0a8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 17 Jul 2023 14:09:02 +0200 Subject: [PATCH 247/628] removed debug print; Might solve cram tests --- src/util/terminationPreprocessing.ml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1432a2da98..e20ee9b375 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,18 +2,7 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let specialFunction name = - print_endline @@ "specialfunction done"; - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } -let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -30,7 +19,21 @@ let show_location_id l = class loopCounterVisitor lc lg (fd : fundec) = object(self) inherit nopCilVisitor + method! vstmt s = + + let specialFunction name = + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } in + + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in From 021ddaddbd44c0498324439a0672b42efb2dbd1e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 17 Jul 2023 14:28:27 +0200 Subject: [PATCH 248/628] Remove debug output --- src/util/terminationPreprocessing.ml | 97 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1432a2da98..c3c6e0500c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,60 +3,59 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) let specialFunction name = - print_endline @@ "specialfunction done"; - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) let extract_file_name s = (*There still may be a need to filter more chars*) - let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) - let ls = List.rev ls in - let s' = List.nth ls 0 in - let ls = String.split_on_char '.' s' in - let s' = List.nth ls 0 in - let without_spaces = String.split_on_char ' ' s' in - let s' = String.concat "" without_spaces in - s' + let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) + let ls = List.rev ls in + let s' = List.nth ls 0 in + let ls = String.split_on_char '.' s' in + let s' = List.nth ls 0 in + let without_spaces = String.split_on_char ' ' s' in + let s' = String.concat "" without_spaces in + s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor lc lg (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- inc_stmt :: exit_stmt :: ss; - ); - lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | Goto (sref, l) -> - let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) - s - | _ -> s - in ChangeDoChildrenPost (s, action); - end \ No newline at end of file + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + | ss -> + b.bstmts <- inc_stmt :: exit_stmt :: ss; + ); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s + | _ -> s + in ChangeDoChildrenPost (s, action); +end From 47440a3ec68a72e60e4597a679c8362807406584 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 14:55:13 +0200 Subject: [PATCH 249/628] Code style optimization --- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index f564354e51..3bd6e53d2d 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -18,7 +18,7 @@ int main() } printf("(%d, %d) ", i, j); } - outer_loop:; // Label for the outer loop + outer_loop: // Label for the outer loop printf("\n"); } From 91d331d588bae35c973b5c238a0dfe3a19a24f3b Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 16:10:51 +0200 Subject: [PATCH 250/628] Indentation --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2217fab707..ad05bbbcc6 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1719,7 +1719,7 @@ struct (* Tuple containing the fundec and context of the caller *) module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) - + (* Set containing multiple caller tuples *) module CallGraphSet = SetDomain.Make (CallGraphTuple) From fc427bc264800660f1dd250230fdb0b70803a279 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 17 Jul 2023 16:18:23 +0200 Subject: [PATCH 251/628] Fix indentation --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2217fab707..6883cc72d9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1718,16 +1718,16 @@ struct module V = GVarF(S.V) (* Tuple containing the fundec and context of the caller *) - module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) - + module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) + (* Set containing multiple caller tuples *) module CallGraphSet = SetDomain.Make (CallGraphTuple) (* Mapping from the callee context to the set of all caller tuples*) module CallGraphMap = MapDomain.MapBot (S.C) (CallGraphSet) - module G = - struct + module G = + struct include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) let spec = function From 3fb5d1442335772e389e4a4a9b8e17342b0a52dc Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 17:45:23 +0200 Subject: [PATCH 252/628] Test case 48 --- .../48-dynamic-recursion-nonterminating.c | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/regression/75-termination/48-dynamic-recursion-nonterminating.c diff --git a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c new file mode 100644 index 0000000000..066c2f51b1 --- /dev/null +++ b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c @@ -0,0 +1,10 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +void troll(void (*f) ()) +{ + f(f); +} + +int main() +{ + troll(troll); +} From 601698fa8bf3c25a0f1b739e38ac2c6b9eac7bdf Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 18 Jul 2023 15:37:07 +0200 Subject: [PATCH 253/628] Remove unused code; introduce basic error-handling --- src/analyses/loopTermination.ml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index b07fb143b4..afd86fc483 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -14,9 +14,6 @@ let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] -let is_loop_counter_var (x : varinfo) = - VarToStmt.mem x !loop_counters - let no_upjumping_gotos () = upjumping_gotos.contents = [] @@ -78,18 +75,23 @@ struct if !AnalysisState.postsolving then match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created. *) - if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Loop analysis)", - Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - () + (try + let loop_statement = VarToStmt.find x !loop_counters in + let is_bounded = check_bounded ctx x in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created. *) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Loop analysis)", + Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + () + with Not_found -> + (* This should not happen as long as __goblint_bounded is only used + * for this analysis. *) + ()) | _ -> () else () From 66115b1da109bf028bf6648ebb2724af95ab1fcb Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 24 Jul 2023 13:34:35 +0200 Subject: [PATCH 254/628] Annotate tests with skip as Apron ist used --- tests/regression/75-termination/01-simple-loop-terminating.c | 2 +- .../regression/75-termination/02-simple-loop-nonterminating.c | 2 +- tests/regression/75-termination/03-nested-loop-terminating.c | 2 +- .../regression/75-termination/04-nested-loop-nonterminating.c | 2 +- tests/regression/75-termination/05-for-loop-terminating.c | 2 +- tests/regression/75-termination/06-for-loop-nonterminating.c | 2 +- .../75-termination/07-nested-for-loop-terminating.c | 2 +- .../75-termination/08-nested-for-loop-nonterminating.c | 2 +- .../75-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/75-termination/10-complex-loop-terminating.c | 2 +- tests/regression/75-termination/11-loopless-termination.c | 2 +- .../75-termination/12-do-while-instant-terminating.c | 2 +- tests/regression/75-termination/13-do-while-terminating.c | 2 +- tests/regression/75-termination/14-do-while-nonterminating.c | 2 +- .../75-termination/15-complex-loop-combination-terminating.c | 2 +- .../75-termination/16-nested-loop-nontrivial-nonterminating.c | 2 +- tests/regression/75-termination/17-goto-terminating.c | 2 +- tests/regression/75-termination/18-goto-nonterminating.c | 2 +- tests/regression/75-termination/19-rand-terminating.c | 2 +- tests/regression/75-termination/20-rand-nonterminating.c | 2 +- .../75-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/75-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/75-termination/23-exit-on-rand-terminating.c | 2 +- .../75-termination/24-upjumping-goto-loopless-terminating.c | 2 +- .../75-termination/25-leave-loop-goto-terminating.c | 2 +- .../75-termination/26-enter-loop-goto-terminating.c | 2 +- .../75-termination/27-upjumping-goto-nonterminating.c | 2 +- .../75-termination/28-do-while-continue-terminating.c | 2 +- .../75-termination/29-do-while-continue-nonterminating.c | 2 +- .../75-termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-termination/31-goto-out-of-inner-loop-nonterminating.c | 2 +- tests/regression/75-termination/32-multithread-terminating.c | 2 +- .../regression/75-termination/33-multithread-nonterminating.c | 2 +- .../75-termination/34-nested-for-loop-nonterminating.c | 2 +- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- tests/regression/75-termination/36-recursion-terminating.c | 2 +- tests/regression/75-termination/37-recursion-nonterminating.c | 2 +- .../75-termination/38-recursion-nested-terminating.c | 2 +- .../75-termination/39-recursion-nested-nonterminating.c | 4 ++-- .../40-multi-expression-conditions-terminating.c | 2 +- tests/regression/75-termination/41-for-continue-terminating.c | 2 +- .../75-termination/42-downjumping-goto-loopless-terminating.c | 2 +- .../75-termination/43-return-from-endless-loop-terminating.c | 2 +- .../44-recursion-multiple-functions-terminating.c | 2 +- .../45-recursion-multiple-functions-nonterminating.c | 2 +- .../46-recursion-different-context-terminating.c | 2 +- .../47-recursion-different-context-nonterminating.c | 2 +- .../75-termination/48-dynamic-recursion-nonterminating.c | 2 +- 48 files changed, 49 insertions(+), 49 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index aaa2a7a895..8ca4610057 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index c6e1c6c8d6..d8847e2b74 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 70327c1016..fd1ee14f39 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 21a6d47051..21b6014509 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index bf58408487..7a2b789496 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 0f96209e35..6c6123251c 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index 1c43eeaada..f1dde17dc5 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index ec76f31534..cb65a0d267 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 9767b4bc1c..264c08f6ed 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 19091b1033..90317d5209 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index 51c0605757..9f1a7e0f13 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 3767430a51..5bc18902b3 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 8faeec1e64..6ac6946495 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 5522b61d88..0a9df3421f 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index d987397dd7..c2ab718200 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index bded788a90..267a2d2fd8 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 941db0c601..2f678d294b 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index f88088ad12..6de80effd7 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index 06deac6c34..a5b6c22941 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 394bce7709..21b25ed9dd 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 902ef2a4e2..5f82d91079 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index f14f7d4e3f..33838ca83d 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 013aff2dd5..e65c064c40 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 3f4e115445..ce257d11ef 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 2cda3d3a03..b882759bff 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 0de9a95d6c..aa85f22b3e 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index 5ce295872c..e0eb633b11 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 61bd578dcf..a61174d295 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 34766ab2e7..dd931c012f 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index 5cdadf4396..999ee6d3fd 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index d7ff329396..f9b9275620 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index fbac273776..eb8b796a47 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but as the termination analysis is meant to not handle multithreaded programs we expect NonTerm here #include #include diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index dad62aa0f4..8a6274c7ab 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 24605ad478..2f21f9e996 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 3bd6e53d2d..0554a0bc25 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 7336417c91..179efabeea 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 21316de9bd..c47fbcdd49 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index bef05eb1a0..a471cfc386 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index b3aa8bf21b..a8d7107442 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,7 +1,7 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function +void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function but can not as dead code is not analysed { printf("Nested recursive call\n"); diff --git a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c index 8e7b4e273d..80f8c5a1e8 100644 --- a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c +++ b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/41-for-continue-terminating.c b/tests/regression/75-termination/41-for-continue-terminating.c index 1d3b96fcf8..d87a705868 100644 --- a/tests/regression/75-termination/41-for-continue-terminating.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c index 54bcfdc508..48864883f7 100644 --- a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { // Currently not able to detect up-jumping loop free gotos diff --git a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c index 06bda24bd7..fb48e1cdbe 100644 --- a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c +++ b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c index c112c72a73..7f9b63527e 100644 --- a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c +++ b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionB(int n); diff --git a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c index 47c13c0dca..be47fde704 100644 --- a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c +++ b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionB(int n); diff --git a/tests/regression/75-termination/46-recursion-different-context-terminating.c b/tests/regression/75-termination/46-recursion-different-context-terminating.c index 4c5dd13035..2fa42f58fc 100644 --- a/tests/regression/75-termination/46-recursion-different-context-terminating.c +++ b/tests/regression/75-termination/46-recursion-different-context-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionC(int n); diff --git a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c index 3216275748..b0e44bce92 100644 --- a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c +++ b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionC(int n); diff --git a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c index 066c2f51b1..d54c49fb43 100644 --- a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c +++ b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra void troll(void (*f) ()) { f(f); From 3c31cb7846582c9f37e62a32ba04b2ec4a4a0c59 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 24 Jul 2023 17:34:55 +0200 Subject: [PATCH 255/628] Revert src/analyses/termination.ml --- src/analyses/termination.ml | 169 +++++++++--------------------------- 1 file changed, 43 insertions(+), 126 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 6112eb0eaf..6da9225d3f 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -5,8 +5,6 @@ open GoblintCil open Analyses module M = Messages -(* J: returns if a and b contain a value - if yes: return this x, otherwise nothing *) let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None module TermDomain = struct @@ -14,22 +12,15 @@ module TermDomain = struct end (* some kind of location string suitable for variable names? *) -(* J: returns a string_ "lineNr_columnNr" *) -(* J: for location (10,5) it evaluates to: 10_5*) let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column -(* J: the new variable is created here and inserted into the code - in the code the variable is set to 0 (before the loop) and incremented (after the loop) - is it ever checked if the newly created variable is really new???*) -(* J: ??? Who defines the Loop, what are the variables*) class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> (* insert loop counter variable *) - (* J: for location (10,5) it evaluates to: term10_5*) let name = "term"^show_location_id loc in let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) let v = Cilfacade.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in @@ -38,20 +29,14 @@ class loopCounterVisitor (fd : fundec) = object(self) (* increment it every iteration *) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* J: s.kind = Loop(b, loc, eloc, ...)*) + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | _ -> s in ChangeDoChildrenPost (s, action) end -(* J: creates a new hash table with size 13 for loop breaks*) -(* J: int: is a number which is unique in a function*) -(* J: ??? Why 13*) let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) -(* J: if there is some break associated with the loop (?) we add this break to the hash table - key = break.sid - data = location *) class loopBreaksVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -63,15 +48,10 @@ class loopBreaksVisitor (fd : fundec) = object(self) end (* if the given block contains a goto while_break.* we have the termination condition for a loop *) -(* J: returns binding from loopBreaks hash table associated with a number which is uniquely identifie with the statement - if there is a Goto, otherwise nothing*) -(* J: stmt.sid = A number (>= 0) that is unique in a function. *) -(* J: ???*) let exits = function | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid | _ -> None (* TODO handle return (need to find out what loop we are in) *) -(* J: ???*) let lvals_of_expr = let rec f a = function | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a @@ -81,187 +61,125 @@ let lvals_of_expr = | Question (c,t,e,_) -> f a c @ f a t @ f a e in f [] -(* J: create hash table of size 13 for variables*) let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) -(* J: adds the location and left varibale to the loopVars, if one block of the if statement contains a goto block*) class loopVarsVisitor (fd : fundec) = object inherit nopCilVisitor method! vstmt s = let add_exit_cond e loc = match lvals_of_expr e with - (* J: ??? Same as when isArithmeticType Cilfacade.typeOf e*) | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval - (* J : add lval to hash table when the expression on location loc is of arithmetic type*) | _ -> () in (match s.skind with - (* J: map_default f x (Some v) returns f v and map_default f x None returns x.*) - (* J: If there exists a goto statement: call add_exit_cond e (SOME exits tb ||? exits fb) - If e is of arithmetic type: add the location to the loopVars hash table *) | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) | _ -> ()); DoChildren end -(* J: ??? visits the expression e and removes all casts from the expression*) let stripCastsDeep e = let v = object inherit nopCilVisitor - (* J: ChangeTo: Replace the expression with the given one*) - (* J: Removes casts from this expression, but ignores casts within other expression constructs. - So we delete the (A) and (B) casts from "(A)(B)(x + (C)y)", but leave the (C) cast.*) method! vexpr e = ChangeTo (stripCasts e) end in visitCilExpr v e (* keep the enclosing loop for statements *) -(* J: store pointer pointing to Nothing for loops*) let cur_loop = ref None (* current loop *) let cur_loop' = ref None (* for nested loops *) -(* J: searches if the variable name___ for the given location is present in the function definition - if not: the variable is created and initialized to 0*) let makeVar fd loc name = - (* J: for location = (10,5) and name = "hi" the id evaluates to: hi__10_5*) let id = name ^ "__" ^ show_location_id loc in - (* J: fd.slocals = Locals of the function definition*) - (* J: returns the first element which is a local and which name is id (for example hi__10_5)*) try List.find (fun v -> v.vname = id) fd.slocals - (* J: when the variable is not found in the function definition then it is newly created and initialized with 0*) with Not_found -> let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) Cilfacade.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) -(* J: creates an empty function with name "__goblint_assume" and makes a lvalue out of it*) let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) -(* J: creates an empty function with name "__goblint_check" and makes a lvalue out of it*) let f_check = Lval (var (emptyFunction "__goblint_check").svar) -(* J: ??? Loop pointer handling: Why do we fist set cur_loop' = cur_loop and then reverse this operation???*) -(* J: inserts new variable t with init and increment and adds a check if t is bounded*) class loopInstrVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = (* TODO: use Loop eloc? *) (match s.skind with - (* J: if the statement is a loop adjust the loop pointer*) | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; (* J: set the nested loop to the current loop*) - cur_loop := Some loc (* J: set the newly found loop as current loop*) + cur_loop' := !cur_loop; + cur_loop := Some loc | _ -> ()); - (* J: adds the variable t to the loop, increments it and checks after the loop if it is bounded - adds also the variables d1 and d2, with incrementation, which affects t - depending on the structure, d1 and d2 are set differently*) let action s = (* first, restore old cur_loop *) - (* J: if the statement is a loop set the nested loop as the current loop*) (match s.skind with | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; (* J: current loop is the nested loop*) + cur_loop := !cur_loop'; | _ -> ()); - (* J: true if the current loop variable is set and this variable is bound in the hash table*) let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in - (* J: t is the new variable which should be bounded - if there is a loop with bounded variable: add code for init and increment (for t, d1, d2) - if there is a loop with unbounded variable: do nothing - if a loop ended: check if t is bounded - if there is an instruction with an assignment: increment d1 and d2 if the assignment affects the loop var - do this recursively for all children*) match s.skind with - (* J: if the statement is a loop, and when the location is bound in the hash table: - - add the creational and initializational code for t, d1, d2 before the loop - - add the incrementational code for t, d1, d2 in the loop - *) | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> (* find loop var for current loop *) let x = Hashtbl.find loopVars loc in (* insert loop counter and diff to loop var *) - (* J: create variables t, d1, d2 with names: t___, d1___, d2___*) let t = var @@ makeVar fd loc "t" in let d1 = var @@ makeVar fd loc "d1" in let d2 = var @@ makeVar fd loc "d2" in (* make init stmts *) - (* J: set t=0, d1, d2 = lvalue of x = value in the hashtable associated with the loop variable*) let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in (* increment/decrement in every iteration *) - (* J: increment t and d2, decrement d1*) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in (* J: t = t + 1*) - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in (* J: d1 = d1 - 1*) - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in (* J: d2 = d2 + 1*) - let typ = intType in (* J: Note: x is the loop variable*) - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in (* J: t = (x - d1) *) - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in (* J: t = (d2 - x) *) - (* J: make a statement for e1 and e2*) - (* J: ??? what happens with the call*) + let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in + let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in + let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in + let typ = intType in + let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in + let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with (* J: we are still in a loop*) + (match b.bstmts with | cont :: cond :: ss -> (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - (* from: cont :: cond :: ss - to: cont :: - cond :: - t = (x - d1) :: t = (d2 - x) :: (??? Is this correct with the call???) - d1 = d1 - 1 :: d2 = d2 + 1 :: t = t + 1 :: - ss - *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; (* J: in the loop*) - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in (* J: make a block out of the init statements before the loop*) + b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; + let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in s.skind <- Block nb; | _ -> ()); - s (* J: return s with added code for init and increment*) - (* J: if the variable in the loops is not bounded, it is not possible to continue*) + s | Loop (b, loc, eloc, Some continue, Some break) -> print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; s - (* J: when the statement is not a loop and a loop ended: - - add t >= 0 in the code after the loop*) | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in (* J: holds the current binding of the number of the current function in the hash table*) - let t = var @@ makeVar fd loc "t" in (* J: get the name for variable t = t___*) - let e3 = BinOp (Ge, Lval t, zero, intType) in (* J: t >= 0*) - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in (* J: make a statement to check t >= 0*) - let nb = mkBlock [mkStmt s.skind; inv3] in (* J: add the statement to the block*) + let loc = Hashtbl.find loopBreaks s.sid in + let t = var @@ makeVar fd loc "t" in + let e3 = BinOp (Ge, Lval t, zero, intType) in + let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in + let nb = mkBlock [mkStmt s.skind; inv3] in s.skind <- Block nb; - s (* J: return s with the added check*) - (* J: If there is an instruction (containing an assignment) and it is in a loop: - If the loop variable and lvalue of Set are structural unequal - Do nothing - else - add an incrementation step for d1 and d2 (depending on the binOp)*) + s | Instr [Set (lval, e, loc, eloc)] when in_loop () -> (* find loop var for current loop *) let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in (* J: holds the current binding of the number of the current function in the hash table*) - if x <> lval then (* J: x and lval are structural unequal*) + let x = Hashtbl.find loopVars cur_loop in + if x <> lval then s else (* we only care about the loop var *) - (* J: create the variables d1 and d2 with name: d1___, d2___*) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in (* J: d2 = d2 + e2*) - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in (* J: add the incrementation steps at the front*) + let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in + let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in + let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in s.skind <- Block nb; - s (* J: return s with the added incrementation*) + s | _ -> (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in (* J: varibale name for t*) - let te = Cilfacade.typeOf e in (* J: type of e*) - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d1 = x - t*) - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d2 = x - t*) - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in (* J: add the incrementation steps at the end*) + let t = makeVar fd cur_loop "t" in + let te = Cilfacade.typeOf e in + let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in + let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in + let nb = mkBlock [mkStmt s.skind; dt1; dt2] in s.skind <- Block nb; s ) | _ -> s in - (* J: *) - ChangeDoChildrenPost (s, action) (* J: continue with the children*) + ChangeDoChildrenPost (s, action) end @@ -298,25 +216,24 @@ struct (* ctx.local *) (* | _ -> ctx.local *) - let startstate v = D.bot () (* J: start with bottom*) - let threadenter ctx lval f args = [D.bot ()] (* J: enter threads with bottom*) + let startstate v = D.bot () + let threadenter ctx lval f args = [D.bot ()] let exitstate v = D.bot () end class recomputeVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc fd = - computeCFGInfo fd true; (* J: make the cfg and return a list of statements with global statement number*) - SkipChildren (* J: don't visit children*) + computeCFGInfo fd true; + SkipChildren end let _ = (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: fill hash table loopBreaks: containing breaks ?*) - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); (* J: fill hash table loopVars: containing varibales identified with loops ?*) - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); (* J: inserts new variable with init, increment, and bounded check to code*) - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) - Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* A: register this (termination) analysis withing the master control program, which - collects all active analyses and represents the combination of them as a new, single analysis to FromSpec *) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); + Hashtbl.clear loopBreaks; (* because the sids are now different *) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); + MCP.register_analysis (module Spec : MCPSpec) From a9c9c7d2f84d10945ec0031f2433048dd0ad0cb8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 25 Jul 2023 19:46:48 +0200 Subject: [PATCH 256/628] changed initial value of lcv to min int; swaped sequence of increment and special function call, to retain top of intdomain at special function call --- runningGob.sh | 8 ++++---- src/maingoblint.ml | 2 +- src/util/terminationPreprocessing.ml | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 61dbad53b6..e70b34af7c 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -13,7 +13,7 @@ cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminatin cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" -cfile_loop1="tests/regression/74-loop_termination/01-simple-loop-terminating.c" +cfile_loop1="tests/regression/75-termination/02-simple-loop-nonterminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" @@ -22,10 +22,10 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loop30 $options_term --enable justcil > output.txt -./goblint -v $cfile_loop30 $options_term --html +./goblint $cfile_loop1 $options_term --enable justcil > output.txt +./goblint $cfile_loop1 $options_term --html # set up server to see visualizatino -python3 -m http.server --directory result 8080 +python3 -m http.server --directory result 8082 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 371deb989a..f9abd9637b 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,7 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); - (*set_string "sem.int.signed_overflow" "assume_none";*) + set_string "sem.int.signed_overflow" "assume_none"; warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" ) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 0ff459718a..768dac0df9 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -31,7 +31,9 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) smaxstmtid = None; sallstmts = []; } in - + + let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in let action s = match s.skind with @@ -39,15 +41,15 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) let name = "term"^show_location_id loc in let typ = Cil.intType in let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: exit_stmt :: ss; + b.bstmts <- exit_stmt :: inc_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 782b21c4a65521e0104f789df853e4bf140669f1 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 25 Jul 2023 21:31:18 +0200 Subject: [PATCH 257/628] Fix indentation --- src/util/terminationPreprocessing.ml | 90 ++++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 768dac0df9..74aca11824 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,50 +18,50 @@ let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor lc lg (fd : fundec) = object(self) - inherit nopCilVisitor - - method! vstmt s = + inherit nopCilVisitor - let specialFunction name = - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } in + method! vstmt s = - let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in - - let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in - - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- exit_stmt :: inc_stmt :: ss; - ); - lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | Goto (sref, l) -> - let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) - s - | _ -> s - in ChangeDoChildrenPost (s, action); - end \ No newline at end of file + let specialFunction name = + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } in + + let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; + | ss -> + b.bstmts <- exit_stmt :: inc_stmt :: ss; + ); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s + | _ -> s + in ChangeDoChildrenPost (s, action); +end From c53f0b84d29dc077d9eeddf354dd10acb572b826 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 14:38:32 +0200 Subject: [PATCH 258/628] Polish comments --- src/analyses/loopTermination.ml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index afd86fc483..89976b7627 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,20 +4,20 @@ open Analyses open GoblintCil open TerminationPreprocessing -(** Stores the result of the query if the program is single threaded or not - since finalize does not has ctx as an argument*) +(** Stores the result of the query whether the program is single threaded or not + since finalize does not have access to ctx. *) let single_thread : bool ref = ref false (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty -(** Contains the locations of the upjumping gotos *) +(** Contains the locations of the upjumping gotos. *) let upjumping_gotos : location list ref = ref [] let no_upjumping_gotos () = upjumping_gotos.contents = [] -(** Checks whether a variable can be bounded *) +(** Checks whether a variable can be bounded. *) let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in @@ -35,7 +35,6 @@ module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) module Spec : Analyses.MCPSpec = struct - (** Provides some default implementations *) include Analyses.IdentitySpec let name () = "termination" @@ -52,8 +51,8 @@ struct let startstate _ = () let exitstate = startstate + (** Warnings for detected possible non-termination *) let finalize () = - (* Warning for detected possible non-termination *) (* Upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter @@ -71,6 +70,8 @@ struct M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) + (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the + * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with @@ -95,14 +96,13 @@ struct | _ -> () else () - (** Checks whether a new thread was spawned some time. We want to discard - * any knowledge about termination then (see query function) *) + (** Checks whether a new thread was spawned some time. We want to always + * assume non-termination then (see query function). *) let must_be_single_threaded_since_start ctx = let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded - (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> @@ -124,7 +124,5 @@ struct end let () = - (* Register the preprocessing *) Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); - (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From c52cf476cf170a9b1374adf03ef31283e1565435 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 14:58:27 +0200 Subject: [PATCH 259/628] Remove runningGob.sh --- runningGob.sh | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100755 runningGob.sh diff --git a/runningGob.sh b/runningGob.sh deleted file mode 100755 index e70b34af7c..0000000000 --- a/runningGob.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -make -make install -clear - -# set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron -options_signs="--set "ana.activated[+]" signs --enable warn.debug" -options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" - -cfile_loop30="tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c" -cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c" -cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" -cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" -cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" -cfile_loop1="tests/regression/75-termination/02-simple-loop-nonterminating.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" -cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" - -# run analysis, write cil output to file and enable visualization via html -#./goblint $cfile_loops $options_apron --enable justcil > output.txt -#./goblint $cfile_loops $options_apron --html - -# run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loop1 $options_term --enable justcil > output.txt -./goblint $cfile_loop1 $options_term --html - -# set up server to see visualizatino -python3 -m http.server --directory result 8082 -#./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt - From 867e6ca5e408a973a2c5150395132deb032b8d24 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:33:53 +0200 Subject: [PATCH 260/628] Restore indentation; remove unused include Printf NOTE: This commit makes the indendation of several files wrong again on purpose! --- src/cdomains/intDomain.mli | 10 +-- src/framework/analyses.ml | 2 + src/framework/constraints.ml | 12 ++-- src/framework/control.ml | 118 +++++++++++++++++------------------ src/util/cilCfg.ml | 5 +- src/witness/witness.ml | 44 ++++++------- 6 files changed, 95 insertions(+), 96 deletions(-) diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index c7b59e4c23..a853c8acca 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -232,7 +232,7 @@ sig val invariant: Cil.exp -> t -> Invariant.t end (** Interface of IntDomain implementations that do not take ikinds for arithmetic operations yet. - TODO: Should be ported to S in the future. *) + TODO: Should be ported to S in the future. *) module type S = sig @@ -412,10 +412,10 @@ module IntervalSetFunctor(Ints_t : IntOps.IntOps): SOverflow with type int_t = I module Interval32 :Y with (* type t = (IntOps.Int64Ops.t * IntOps.Int64Ops.t) option and *) type int_t = IntOps.Int64Ops.t module BigInt: -sig - include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) - val cast_to: Cil.ikind -> Z.t -> Z.t -end + sig + include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) + val cast_to: Cil.ikind -> Z.t -> Z.t + end module Interval : SOverflow with type int_t = IntOps.BigIntOps.t diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 23b75a4097..dd57f40c70 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,6 +42,7 @@ struct let var_id = Node.show_id end + module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -118,6 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6883cc72d9..5e99720364 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 @@ -1127,7 +1126,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" @@ -1457,7 +1456,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module LongjmpLifter (S: Spec): Spec = struct include S @@ -1920,10 +1918,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 b98ec20e8d..69cdf1bdac 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,25 +20,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 termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) 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 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) @@ -303,10 +303,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 *) @@ -530,9 +530,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 = Version.goblint; 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 = Version.goblint; 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 *) @@ -584,10 +584,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; @@ -619,35 +619,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 diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 0d4d5f3a1e..0d1f06da01 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -42,7 +42,6 @@ let loopCount file = let createCFG (fileAST: file) = - (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -59,7 +58,7 @@ let createCFG (fileAST: file) = * See https://github.com/goblint/cil/issues/31#issuecomment-824939793. *) let loops = loopCount fileAST in - + iterGlobals fileAST (fun glob -> match glob with | GFun(fd,_) -> @@ -70,5 +69,5 @@ let createCFG (fileAST: file) = | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); Cilfacade.do_preprocess fileAST diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 94ffea0a0a..ae6b80b3cb 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -23,7 +23,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module IsInteresting = struct (* type node = N.t - type edge = TaskResult.Arg.Edge.t *) + type edge = TaskResult.Arg.Edge.t *) let minwitness = get_bool "witness.minimize" let is_interesting_real from_node edge to_node = (* TODO: don't duplicate this logic with write_node, write_edge *) @@ -59,11 +59,11 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module GML = XmlGraphMlWriter in let module GML = (val match get_string "witness.id" with - | "node" -> - (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) - | "enumerate" -> - (module EnumerateNodeGraphMlWriter (N) (GML)) - | _ -> failwith "witness.id: illegal value" + | "node" -> + (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) + | "enumerate" -> + (module EnumerateNodeGraphMlWriter (N) (GML)) + | _ -> failwith "witness.id: illegal value" ) in let module GML = DeDupGraphMlWriter (N) (GML) in @@ -107,16 +107,16 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) GML.write_key g "edge" "goblintLine" "string" None; (* TODO: remove *) (* GML.write_key g "edge" "enterFunction2" "string" None; - GML.write_key g "edge" "returnFromFunction2" "string" None; *) + GML.write_key g "edge" "returnFromFunction2" "string" None; *) GML.start_graph g; GML.write_metadata g "witness-type" ( - match TaskResult.result with - | Result.True -> "correctness_witness" - | Result.False _ -> "violation_witness" - | Result.Unknown -> "unknown_witness" - ); + match TaskResult.result with + | Result.True -> "correctness_witness" + | Result.False _ -> "violation_witness" + | Result.Unknown -> "unknown_witness" + ); GML.write_metadata g "sourcecodelang" "C"; GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Version.goblint); GML.write_metadata g "specification" (Svcomp.Specification.to_string Task.specification); @@ -141,7 +141,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement _, `Lifted i -> let i = InvariantCil.exp_replace_original_name i in [("invariant", CilType.Exp.show i); - ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] + ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] | _ -> (* ignore entry and return invariants, variables of wrong scopes *) (* TODO: don't? fix scopes? *) @@ -150,10 +150,10 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) [] end; (* begin match cfgnode with - | Statement s -> + | Statement s -> [("sourcecode", GobPretty.sprint Basetype.CilStmt.pretty s)] (* TODO: sourcecode not official? especially on node? *) - | _ -> [] - end; *) + | _ -> [] + end; *) (* violation actually only allowed in violation witness *) (* maybe should appear on from_node of entry edge instead *) begin if TaskResult.is_violation node then @@ -170,7 +170,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement stmt -> Printf.sprintf "s%d" stmt.sid | Function f -> Printf.sprintf "ret%d%s" f.vid f.vname | FunctionEntry f -> Printf.sprintf "fun%d%s" f.vid f.vname - )] *) + )] *) (* [("goblintNode", N.to_string node)] *) ]) in @@ -213,9 +213,9 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) (* enter and return on other side of nodes, more correct loc (startline) but had some scope problem? *) (* | MyARG.CFGEdge (Entry f) -> - [("enterFunction2", f.svar.vname)] - | MyARG.CFGEdge (Ret (_, f)) -> - [("returnFromFunction2", f.svar.vname)] *) + [("enterFunction2", f.svar.vname)] + | MyARG.CFGEdge (Ret (_, f)) -> + [("returnFromFunction2", f.svar.vname)] *) | _ -> [] end; [("goblintEdge", Arg.Edge.to_string edge)] @@ -394,12 +394,12 @@ struct struct let path = observer_path end - ) + ) in MCP.register_analysis (module Spec); (* TODO: don't modify JSON but have ref vars for these instead *) (* GobConfig.set_list "ana.activated" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.activated"); - GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) + GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) (* TODO: don't append to end; currently done to get observer order to be nice *) GobConfig.set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String (Spec.name ())]); GobConfig.set_list "ana.path_sens" (GobConfig.get_list "ana.path_sens" @ [`String (Spec.name ())]); From 0f94aaa98f2b463963f113a17e1a5e1fdf208ff0 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:41:58 +0200 Subject: [PATCH 261/628] More indentation restoring --- src/util/cilCfg.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 0d1f06da01..72143e97d7 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -68,6 +68,6 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); + Cilfacade.do_preprocess fileAST From f4fd0c22d3bf65e16bfbfcb15d6063bbd5ed0af3 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:48:30 +0200 Subject: [PATCH 262/628] Fix a typo --- src/framework/analysisState.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index c2d977af9c..913fe88a4e 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,7 +7,7 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false -(** Whether the termination analysis detectes the program as non-terminating**) +(** Whether the termination analysis detects the program as non-terminating *) let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) From 1be8c9c94ae7c4c83064b858cb8147ea674fead8 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 17:58:08 +0200 Subject: [PATCH 263/628] Remove goto stuff from loopTermination analysis --- src/analyses/loopTermination.ml | 21 +-------------------- src/util/terminationPreprocessing.ml | 4 +++- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 89976b7627..563d6574bb 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -11,12 +11,6 @@ let single_thread : bool ref = ref false (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty -(** Contains the locations of the upjumping gotos. *) -let upjumping_gotos : location list ref = ref [] - -let no_upjumping_gotos () = - upjumping_gotos.contents = [] - (** Checks whether a variable can be bounded. *) let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in @@ -53,18 +47,6 @@ struct (** Warnings for detected possible non-termination *) let finalize () = - (* Upjumping gotos *) - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Upjumping Goto)", - Some (M.Location.CilLocation x) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); (* Multithreaded *) if not (!single_thread) then ( M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" @@ -117,12 +99,11 @@ struct * evaluation, the correct value of single_thread can not be guaranteed! * Therefore, we use a let-in clause here. *) always_single_threaded - && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end let () = - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 74aca11824..f5e520104b 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -17,7 +17,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -55,6 +55,7 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s + (* | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in let loc_stmt = get_stmtLoc goto_jmp_stmt in @@ -62,6 +63,7 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) then lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) s + *) | _ -> s in ChangeDoChildrenPost (s, action); end From cf594b66a11bcef2fe12892fb54c1ae385c9d07d Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 18:03:56 +0200 Subject: [PATCH 264/628] Add goto-fundec list in cilfacade.ml --- src/util/cilfacade.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 2a81444e41..284c01a76c 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -606,3 +606,7 @@ let add_function_declarations (file: Cil.file): unit = let fun_decls = List.filter_map declaration_from_GFun functions in let globals = upto_last_type @ fun_decls @ non_types @ functions in file.globals <- globals + +(** Contains the locations of the upjumping gotos and the respective functions + * they are being called in. *) +let upjumping_gotos : (location * fundec) list ref = ref [] From eabf6b7888911d862d8ab745903a9e8bb4f7ae14 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Wed, 26 Jul 2023 19:05:17 +0200 Subject: [PATCH 265/628] add gotos with their respective function to new list in Cilfacade --- src/util/terminationPreprocessing.ml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index f5e520104b..32a9468233 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,8 +2,6 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) - - let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -55,15 +53,13 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s - (* | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in + let loc_stmt = Cil.get_stmtLoc goto_jmp_stmt in if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + Cilfacade.upjumping_gotos := List.append !Cilfacade.upjumping_gotos ([(l, fd)] : (location * fundec) list); (*problem: the program might not terminate!*) s - *) | _ -> s in ChangeDoChildrenPost (s, action); end From 19addab0d94f75486291e2bef9b9dff7e644a1a8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:14:06 +0200 Subject: [PATCH 266/628] added code for control to only print upjumping goto message when goto is not in dead code function --- src/framework/control.ml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 69cdf1bdac..dfb0859438 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -136,6 +136,25 @@ struct try StringMap.find fn (StringMap.find file !live_lines) with Not_found -> BatISet.empty in + (*check if we have upjumping gotos*) + List.iter + (fun x -> + let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) + let fname = fd.svar.vname in + StringMap.iter + (fun fi _ -> + let fundec_live = live fi fname in + if (not (BatISet.is_empty fundec_live)) then ( + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Upjumping Goto)", + Some (M.Location.CilLocation l) + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + ) + (!dead_lines)) + (!Cilfacade.upjumping_gotos); + dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; From 72e2e22b62f026693c404b6edf3b41930fef7e18 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:29:17 +0200 Subject: [PATCH 267/628] now everything should work :), now iterating over live_lines --- src/framework/control.ml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index dfb0859438..b2125ef9a7 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -139,12 +139,15 @@ struct (*check if we have upjumping gotos*) List.iter (fun x -> + print_endline @@ "halloooo"; let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) - let fname = fd.svar.vname in + let fname = fd.svar.vname in + print_endline @@ "halloooo2"; StringMap.iter (fun fi _ -> let fundec_live = live fi fname in - if (not (BatISet.is_empty fundec_live)) then ( + print_endline @@ "halloooo3"; + if ( not (BatISet.is_empty fundec_live)) then ( let msgs = [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", @@ -152,9 +155,8 @@ struct );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); ) - (!dead_lines)) + (!live_lines)) (!Cilfacade.upjumping_gotos); - dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; From 6090c62b650696aa9ddb915cd4ab6da494e5e23b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:31:05 +0200 Subject: [PATCH 268/628] now without prints :))) --- src/framework/control.ml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index b2125ef9a7..8185dc6053 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -139,14 +139,11 @@ struct (*check if we have upjumping gotos*) List.iter (fun x -> - print_endline @@ "halloooo"; let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) let fname = fd.svar.vname in - print_endline @@ "halloooo2"; StringMap.iter (fun fi _ -> let fundec_live = live fi fname in - print_endline @@ "halloooo3"; if ( not (BatISet.is_empty fundec_live)) then ( let msgs = [(Pretty.dprintf From e96433b1ab65970da5aa1d4388d88676c0aedef5 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 26 Jul 2023 20:52:56 +0200 Subject: [PATCH 269/628] Handle skipped (NON-)TERM-Tests other than TODO --- scripts/update_suite.rb | 2 +- .../75-termination/09-complex-for-loop-terminating.c | 3 ++- tests/regression/75-termination/10-complex-loop-terminating.c | 3 ++- .../75-termination/15-complex-loop-combination-terminating.c | 3 ++- .../regression/75-termination/25-leave-loop-goto-terminating.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 60a7ec06be..313b6b75f9 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -331,7 +331,7 @@ def parse_tests (lines) end end case lines[0] - when /TODO|SKIP/ + when /TODO/ case lines[0] when /NONTERM/ tests[-1] = "nonterm" diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 264c08f6ed..fb2acaf569 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 90317d5209..738fe78683 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index c2ab718200..1365611410 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index b882759bff..61c8b8f58d 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From e1f8319a7e72aab0e4ec57a11a3998105448fc4d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 30 Aug 2023 17:54:10 +0200 Subject: [PATCH 270/628] Set sv-comp flag for upjumping gotos --- src/framework/control.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 8185dc6053..32e0a8c038 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -145,6 +145,7 @@ struct (fun fi _ -> let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( + AnalysisState.svcomp_may_not_terminate := true; let msgs = [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", From b832f31cb647ac0f632bbc335a89817564b140dd Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 1 Sep 2023 15:42:17 +0200 Subject: [PATCH 271/628] Increase indentation in switch-case in update_suite.rb. --- scripts/update_suite.rb | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 313b6b75f9..e91b1d116a 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -151,27 +151,27 @@ def collect_warnings ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" - end + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn From a6e4af4083db6751e35f996d374b6fa5fa229016 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 1 Sep 2023 15:56:15 +0200 Subject: [PATCH 272/628] Rename must_be_single_threaded_since_start to must_always_be_single_threaded --- src/analyses/loopTermination.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 563d6574bb..bfc600f830 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -78,9 +78,9 @@ struct | _ -> () else () - (** Checks whether a new thread was spawned some time. We want to always - * assume non-termination then (see query function). *) - let must_be_single_threaded_since_start ctx = + (* Checks whether the program always remains single-threaded. + If the program does not remain single-threaded, we assume non-termination (see query function). *) + let must_always_be_single_threaded ctx = let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded @@ -88,12 +88,12 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_be_single_threaded_since_start ctx + must_always_be_single_threaded ctx && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) | Queries.MustTermAllLoops -> - let always_single_threaded = must_be_single_threaded_since_start ctx in + let always_single_threaded = must_always_be_single_threaded ctx in (* Must be the first to be evaluated! This has the side effect that * single_thread is set. In case of another order and due to lazy * evaluation, the correct value of single_thread can not be guaranteed! From dac7983d06e05f4180c7d53513d5b03cfe2d01b3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 6 Sep 2023 10:05:31 +0200 Subject: [PATCH 273/628] Fix numbering --- .../{74-use_after_free => 78-use_after_free}/01-simple-uaf.c | 0 .../{74-use_after_free => 78-use_after_free}/02-conditional-uaf.c | 0 .../{74-use_after_free => 78-use_after_free}/03-nested-ptr-uaf.c | 0 .../04-function-call-uaf.c | 0 .../05-uaf-free-in-wrapper-fun.c | 0 .../{74-use_after_free => 78-use_after_free}/06-uaf-struct.c | 0 .../{74-use_after_free => 78-use_after_free}/07-itc-double-free.c | 0 .../08-itc-no-double-free.c | 0 .../{74-use_after_free => 78-use_after_free}/09-juliet-uaf.c | 0 .../10-juliet-double-free.c | 0 .../11-wrapper-funs-uaf.c | 0 .../12-multi-threaded-uaf.c | 0 .../13-multi-threaded-uaf-with-joined-thread.c | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{74-use_after_free => 78-use_after_free}/01-simple-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/02-conditional-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/03-nested-ptr-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/04-function-call-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/05-uaf-free-in-wrapper-fun.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/06-uaf-struct.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/07-itc-double-free.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/08-itc-no-double-free.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/09-juliet-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/10-juliet-double-free.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/11-wrapper-funs-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/12-multi-threaded-uaf.c (100%) rename tests/regression/{74-use_after_free => 78-use_after_free}/13-multi-threaded-uaf-with-joined-thread.c (100%) diff --git a/tests/regression/74-use_after_free/01-simple-uaf.c b/tests/regression/78-use_after_free/01-simple-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/01-simple-uaf.c rename to tests/regression/78-use_after_free/01-simple-uaf.c diff --git a/tests/regression/74-use_after_free/02-conditional-uaf.c b/tests/regression/78-use_after_free/02-conditional-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/02-conditional-uaf.c rename to tests/regression/78-use_after_free/02-conditional-uaf.c diff --git a/tests/regression/74-use_after_free/03-nested-ptr-uaf.c b/tests/regression/78-use_after_free/03-nested-ptr-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/03-nested-ptr-uaf.c rename to tests/regression/78-use_after_free/03-nested-ptr-uaf.c diff --git a/tests/regression/74-use_after_free/04-function-call-uaf.c b/tests/regression/78-use_after_free/04-function-call-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/04-function-call-uaf.c rename to tests/regression/78-use_after_free/04-function-call-uaf.c diff --git a/tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c b/tests/regression/78-use_after_free/05-uaf-free-in-wrapper-fun.c similarity index 100% rename from tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c rename to tests/regression/78-use_after_free/05-uaf-free-in-wrapper-fun.c diff --git a/tests/regression/74-use_after_free/06-uaf-struct.c b/tests/regression/78-use_after_free/06-uaf-struct.c similarity index 100% rename from tests/regression/74-use_after_free/06-uaf-struct.c rename to tests/regression/78-use_after_free/06-uaf-struct.c diff --git a/tests/regression/74-use_after_free/07-itc-double-free.c b/tests/regression/78-use_after_free/07-itc-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/07-itc-double-free.c rename to tests/regression/78-use_after_free/07-itc-double-free.c diff --git a/tests/regression/74-use_after_free/08-itc-no-double-free.c b/tests/regression/78-use_after_free/08-itc-no-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/08-itc-no-double-free.c rename to tests/regression/78-use_after_free/08-itc-no-double-free.c diff --git a/tests/regression/74-use_after_free/09-juliet-uaf.c b/tests/regression/78-use_after_free/09-juliet-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/09-juliet-uaf.c rename to tests/regression/78-use_after_free/09-juliet-uaf.c diff --git a/tests/regression/74-use_after_free/10-juliet-double-free.c b/tests/regression/78-use_after_free/10-juliet-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/10-juliet-double-free.c rename to tests/regression/78-use_after_free/10-juliet-double-free.c diff --git a/tests/regression/74-use_after_free/11-wrapper-funs-uaf.c b/tests/regression/78-use_after_free/11-wrapper-funs-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/11-wrapper-funs-uaf.c rename to tests/regression/78-use_after_free/11-wrapper-funs-uaf.c diff --git a/tests/regression/74-use_after_free/12-multi-threaded-uaf.c b/tests/regression/78-use_after_free/12-multi-threaded-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/12-multi-threaded-uaf.c rename to tests/regression/78-use_after_free/12-multi-threaded-uaf.c diff --git a/tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c b/tests/regression/78-use_after_free/13-multi-threaded-uaf-with-joined-thread.c similarity index 100% rename from tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c rename to tests/regression/78-use_after_free/13-multi-threaded-uaf-with-joined-thread.c From b3d9fe1ad02a2fd84455af118a3797922ba976d5 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 6 Sep 2023 11:07:26 +0200 Subject: [PATCH 274/628] Set the global SV-COMP analysis state vars at all necessary places --- src/analyses/base.ml | 28 ++++++++++++++++++++-------- src/analyses/memLeak.ml | 12 +++++++++--- src/analyses/memOutOfBounds.ml | 5 ++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index f237ca8296..79ac13b861 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1050,10 +1050,16 @@ struct | Mem n, ofs -> begin match (eval_rv a gs st n) with | Address adr -> - (if AD.is_null adr - then M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" - else if AD.may_be_null adr - then M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer"); + ( + if AD.is_null adr then ( + AnalysisState.svcomp_may_invalid_deref := true; + M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" + ) + else if AD.may_be_null adr then ( + AnalysisState.svcomp_may_invalid_deref := true; + M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" + ) + ); AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr | _ -> M.debug ~category:Analyzer "Failed evaluating %a to lvalue" d_lval lval; @@ -2023,12 +2029,18 @@ struct match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with | Address a -> let points_to_set = addrToLvalSet a in - if Q.LS.is_top points_to_set then - M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname - else if (Q.LS.exists (fun (v, _) -> not (ctx.ask (Q.IsHeapVar v))) points_to_set) || (AD.mem Addr.UnknownPtr a) then + if Q.LS.is_top points_to_set then ( + AnalysisState.svcomp_may_invalid_free := true; + M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590; CWE 761] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname + ) + else if (Q.LS.exists (fun (v, _) -> not (ctx.ask (Q.IsHeapVar v))) points_to_set) || (AD.mem Addr.UnknownPtr a) then ( + AnalysisState.svcomp_may_invalid_free := true; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr - else if Q.LS.exists (fun (_, o) -> Offset.Exp.cmp_zero_offset o <> `MustZero) points_to_set then + ) + else if Q.LS.exists (fun (_, o) -> Offset.Exp.cmp_zero_offset o <> `MustZero) points_to_set then ( + AnalysisState.svcomp_may_invalid_free := true; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr + ) | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname let special ctx (lv:lval option) (f: varinfo) (args: exp list) = diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 99df5695a7..688ce1024a 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -19,15 +19,21 @@ struct (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then + if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( + AnalysisState.svcomp_may_invalid_memtrack := true; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" + ) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in if not @@ D.is_empty state then match assert_exp_imprecise, exp with - | true, Some exp -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state - | _ -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state + | true, Some exp -> + AnalysisState.svcomp_may_invalid_memtrack := true; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state + | _ -> + AnalysisState.svcomp_may_invalid_memtrack := true; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 0e93adb295..a7e95282fd 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -194,7 +194,10 @@ struct IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () end | _ -> - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + ( + AnalysisState.svcomp_may_invalid_deref :=true; + M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr + ); IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = From 46ae6ee1d5bfacbed5ced3b475249d724d540601 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 6 Sep 2023 16:43:53 +0200 Subject: [PATCH 275/628] Add extra parentheses in witness.ml for memory safety result generation --- src/witness/witness.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 264e0bc066..31034a2d9a 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -512,7 +512,7 @@ struct let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_free then + if not !AnalysisState.svcomp_may_invalid_free then ( let module TaskResult = struct module Arg = Arg @@ -523,7 +523,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg @@ -542,7 +542,7 @@ struct let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_deref then + if not !AnalysisState.svcomp_may_invalid_deref then ( let module TaskResult = struct module Arg = Arg @@ -553,7 +553,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg @@ -572,7 +572,7 @@ struct let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_memtrack then + if not !AnalysisState.svcomp_may_invalid_memtrack then ( let module TaskResult = struct module Arg = Arg @@ -583,7 +583,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg From d4ef55594e2f388febfb31e598e47691b7dafc90 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 6 Sep 2023 17:21:58 +0200 Subject: [PATCH 276/628] Add quick and dirty workaround attempt for working with SV-COMP's memory-safety category --- src/autoTune.ml | 1 + src/witness/svcomp.ml | 1 + src/witness/svcompSpec.ml | 14 ++++++++---- src/witness/witness.ml | 46 ++++++++++++++++++++++++++++++++------- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index d532081799..9e3508ccd2 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -226,6 +226,7 @@ let focusOnSpecification () = (* TODO: Finish these two below later *) | ValidDeref | ValidMemtrack -> () + | MemorySafety -> () (* TODO: This is here for now just to complete the pattern match *) (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index f1ee18ed72..15d41c0210 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -55,6 +55,7 @@ struct | ValidFree -> "valid-free" | ValidDeref -> "valid-deref" | ValidMemtrack -> "valid-memtrack" + | MemorySafety -> "memory-safety" (* TODO: Currently here only to complete the pattern match *) in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 8dafb8873c..f066610953 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -9,10 +9,11 @@ type t = | ValidFree | ValidDeref | ValidMemtrack + | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) let of_string s = let s = String.strip s in - let regexp = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in @@ -28,13 +29,17 @@ let of_string s = else failwith "Svcomp.Specification.of_string: unknown global not expression" else if Str.string_match regexp s 0 then - let global = Str.matched_group 1 s in - if global = "valid-free" then + let global1 = Str.matched_group 1 s in + let global2 = Str.matched_group 2 s in + let global3 = Str.matched_group 3 s in + if global1 = "valid-free" && global2 = "valid-deref" && global3 = "valid-memtrack" then + MemorySafety + (* if global = "valid-free" then ValidFree else if global = "valid-deref" then ValidDeref else if global = "valid-memtrack" then - ValidMemtrack + ValidMemtrack *) else failwith "Svcomp.Specification.of_string: unknown global expression" else @@ -65,5 +70,6 @@ let to_string spec = | ValidFree -> "valid-free", false | ValidDeref -> "valid-deref", false | ValidMemtrack -> "valid-memtrack", false + | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) in print_output spec_str is_neg diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 31034a2d9a..437ba187ae 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -505,8 +505,8 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidFree -> - let module TrivialArg = + | ValidFree (*->*) + (* let module TrivialArg = struct include Arg let next _ = [] @@ -534,9 +534,9 @@ struct end in (module TaskResult:WitnessTaskResult) - ) - | ValidDeref -> - let module TrivialArg = + ) *) + | ValidDeref (*->*) + (* let module TrivialArg = struct include Arg let next _ = [] @@ -564,9 +564,9 @@ struct end in (module TaskResult:WitnessTaskResult) - ) - | ValidMemtrack -> - let module TrivialArg = + ) *) + | ValidMemtrack (*->*) + (* let module TrivialArg = struct include Arg let next _ = [] @@ -583,6 +583,36 @@ struct end in (module TaskResult:WitnessTaskResult) + ) else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) *) + | MemorySafety -> + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + if not !AnalysisState.svcomp_may_invalid_free || not !AnalysisState.svcomp_may_invalid_deref || not !AnalysisState.svcomp_may_invalid_memtrack then ( + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) ) else ( let module TaskResult = struct From 2fb4d743374fd4322ad2fa2ce98bcaf91d8870ee Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 6 Sep 2023 18:59:51 +0200 Subject: [PATCH 277/628] Use logical AND and not OR for the memory-safety category in witness --- src/witness/witness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 437ba187ae..66a62d1b03 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -602,7 +602,7 @@ struct let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_free || not !AnalysisState.svcomp_may_invalid_deref || not !AnalysisState.svcomp_may_invalid_memtrack then ( + if not !AnalysisState.svcomp_may_invalid_free && not !AnalysisState.svcomp_may_invalid_deref && not !AnalysisState.svcomp_may_invalid_memtrack then ( let module TaskResult = struct module Arg = Arg From 9cbf2ab8d10c064a1c1714e700b3b405478b81ae Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 9 Sep 2023 23:13:03 +0200 Subject: [PATCH 278/628] Add util function for setting mem safety global vars Make sure to do this only if we're in postsolving --- src/analyses/base.ml | 10 +++++----- src/analyses/memLeak.ml | 7 ++++--- src/analyses/memOutOfBounds.ml | 13 +++++++------ src/analyses/useAfterFree.ml | 17 ++++++----------- src/util/analysisStateUtil.ml | 11 +++++++++++ 5 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 src/util/analysisStateUtil.ml diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 79ac13b861..0cdcf98fc0 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1052,11 +1052,11 @@ struct | Address adr -> ( if AD.is_null adr then ( - AnalysisState.svcomp_may_invalid_deref := true; + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" ) else if AD.may_be_null adr then ( - AnalysisState.svcomp_may_invalid_deref := true; + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" ) ); @@ -2030,15 +2030,15 @@ struct | Address a -> let points_to_set = addrToLvalSet a in if Q.LS.is_top points_to_set then ( - AnalysisState.svcomp_may_invalid_free := true; + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590; CWE 761] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname ) else if (Q.LS.exists (fun (v, _) -> not (ctx.ask (Q.IsHeapVar v))) points_to_set) || (AD.mem Addr.UnknownPtr a) then ( - AnalysisState.svcomp_may_invalid_free := true; + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr ) else if Q.LS.exists (fun (_, o) -> Offset.Exp.cmp_zero_offset o <> `MustZero) points_to_set then ( - AnalysisState.svcomp_may_invalid_free := true; + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr ) | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 688ce1024a..0ea4fc96b1 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) @@ -20,7 +21,7 @@ struct (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( - AnalysisState.svcomp_may_invalid_memtrack := true; + set_mem_safety_flag InvalidMemTrack; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" ) @@ -29,10 +30,10 @@ struct if not @@ D.is_empty state then match assert_exp_imprecise, exp with | true, Some exp -> - AnalysisState.svcomp_may_invalid_memtrack := true; + AnalysisStateUtil.set_mem_safety_flag InvalidMemTrack; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state | _ -> - AnalysisState.svcomp_may_invalid_memtrack := true; + AnalysisStateUtil.set_mem_safety_flag InvalidMemTrack; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index a7e95282fd..a5cf7d2ca2 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -1,6 +1,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module AS = AnalysisState module VDQ = ValueDomainQueries @@ -195,7 +196,7 @@ struct end | _ -> ( - AnalysisState.svcomp_may_invalid_deref :=true; + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr ); IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () @@ -229,12 +230,12 @@ struct | Some t -> begin match VDQ.ID.is_top ptr_size with | true -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a not known. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | false -> let offs = `Lifted addr_offs in if ptr_size < offs then begin - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer is %a (in bytes). It is offset by %a (in bytes) due to pointer arithmetic. Memory out-of-bounds access must occur" VDQ.ID.pretty ptr_size VDQ.ID.pretty offs end end @@ -287,14 +288,14 @@ struct in begin match VDQ.ID.is_top ptr_size, VDQ.ID.is_top offset_size_with_addr_size with | true, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a not known. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, true -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a not known. Memory out-of-bounds access might occur" d_exp binopexp | false, false -> if ptr_size < offset_size_with_addr_size then begin - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer in expression %a is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" d_exp binopexp VDQ.ID.pretty ptr_size VDQ.ID.pretty offset_size_with_addr_size end end diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 9af1b8ca7a..9dac016ce5 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) module ThreadIdToJoinedThreadsMap = MapDomain.MapBot(ThreadIdDomain.ThreadLifted)(ConcDomain.MustThreadSet) @@ -24,12 +25,6 @@ struct (* HELPER FUNCTIONS *) - let set_global_svcomp_var is_double_free = - if is_double_free then - AnalysisState.svcomp_may_invalid_free := true - else - AnalysisState.svcomp_may_invalid_deref := true - let get_current_threadid ctx = ctx.ask Queries.CurrentThreadId @@ -65,23 +60,23 @@ struct | `Lifted current -> let possibly_started = G.exists (possibly_started current) freeing_threads in if possibly_started then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "There's a thread that's been started in parallel with the memory-freeing threads for heap variable %a. %s might occur" CilType.Varinfo.pretty heap_var bug_name end else begin let current_is_unique = ThreadId.Thread.is_unique current in let any_equal_current threads = G.exists (equal_current current) threads in if not current_is_unique && any_equal_current freeing_threads then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Current thread is not unique and a %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var end else if D.mem heap_var ctx.local then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "%s might occur in current unique thread %a for heap variable %a" bug_name ThreadIdDomain.FlagConfiguredTID.pretty current CilType.Varinfo.pretty heap_var end end | `Top -> - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "CurrentThreadId is top. %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var | `Bot -> M.warn ~category:MessageCategory.Analyzer "CurrentThreadId is bottom" @@ -110,7 +105,7 @@ struct | a when not (Queries.LS.is_top a) && not (Queries.LS.mem (dummyFunDec.svar, `NoOffset) a) -> let warn_for_heap_var var = if D.mem var state then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior undefined_behavior) ~tags:[CWE cwe_number] "lval (%s) in \"%s\" points to a maybe freed memory region" var.vname transfer_fn_name end in diff --git a/src/util/analysisStateUtil.ml b/src/util/analysisStateUtil.ml new file mode 100644 index 0000000000..25914f8c8e --- /dev/null +++ b/src/util/analysisStateUtil.ml @@ -0,0 +1,11 @@ +type mem_safety_violation = + | InvalidFree + | InvalidDeref + | InvalidMemTrack + +let set_mem_safety_flag violation_type = + if !AnalysisState.postsolving then + match violation_type with + | InvalidFree -> AnalysisState.svcomp_may_invalid_free := true + | InvalidDeref -> AnalysisState.svcomp_may_invalid_deref := true + | InvalidMemTrack -> AnalysisState.svcomp_may_invalid_memtrack := true \ No newline at end of file From 3258cce90b88ea14db99c5e6466b43b7fd8a01a5 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 9 Sep 2023 23:35:54 +0200 Subject: [PATCH 279/628] Don't warn for pointers that only contain strings in their pts --- src/analyses/memOutOfBounds.ml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index a5cf7d2ca2..4c2576ec24 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -161,6 +161,13 @@ struct let remaining_offset = offs_to_idx typ o in IntDomain.IntDomTuple.add bytes_offset remaining_offset + let ptr_only_has_str_addr ctx ptr = + ctx.ask (Queries.MayPointTo ptr) + |> VDQ.LS.elements + |> List.map (fun (v, o) -> ValueDomain.Addr.of_mval (v, ValueDomain.Addr.Offs.of_exp o)) + |> ValueDomain.AD.of_list + |> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) + let rec get_addr_offs ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with | a when not (VDQ.LS.is_top a) -> @@ -202,7 +209,8 @@ struct IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = - if not @@ lval_contains_a_ptr lval then () + (* If the lval does not contain a pointer or if it does contain a pointer, but only points to string addresses, then no need to WARN *) + if (not @@ lval_contains_a_ptr lval) || ptr_only_has_str_addr ctx (Lval lval) then () else (* If the lval doesn't indicate an explicit dereference, we still need to check for an implicit dereference *) (* An implicit dereference is, e.g., printf("%p", ptr), where ptr is a pointer *) From 0881fb786b7a4a17c0fd5adadc50378580c99a73 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 9 Sep 2023 23:39:05 +0200 Subject: [PATCH 280/628] Set global mem safety flags upon array oob as well --- src/cdomains/arrayDomain.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cdomains/arrayDomain.ml b/src/cdomains/arrayDomain.ml index c099a94f96..2f91e47663 100644 --- a/src/cdomains/arrayDomain.ml +++ b/src/cdomains/arrayDomain.ml @@ -787,14 +787,19 @@ let array_oob_check ( type a ) (module Idx: IntDomain.Z with type t = a) (x, l) | Some true, Some true -> (* Certainly in bounds on both sides.*) () | Some true, Some false -> (* The following matching differentiates the must and may cases*) + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "Must access array past end" | Some true, None -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "May access array past end" | Some false, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "Must access array before start" | None, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "May access array before start" | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.unknown "May access array out of bounds" else () From b9faa8f039a6ad5faeb2ea16483c9c1b179b71da Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 9 Sep 2023 23:47:58 +0200 Subject: [PATCH 281/628] Cast pointer arithmetic offsets without using Option.get --- src/analyses/memOutOfBounds.ml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 4c2576ec24..a2c180a453 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -138,11 +138,12 @@ struct let eval_ptr_offset_in_binop ctx exp ptr_contents_typ = let eval_offset = ctx.ask (Queries.EvalInt exp) in - let eval_offset = Option.get @@ VDQ.ID.to_int eval_offset in - let eval_offset = VDQ.ID.of_int (Cilfacade.ptrdiff_ikind ()) eval_offset in let ptr_contents_typ_size_in_bytes = size_of_type_in_bytes ptr_contents_typ in match eval_offset with - | `Lifted i -> `Lifted (IntDomain.IntDomTuple.mul i ptr_contents_typ_size_in_bytes) + | `Lifted i -> + (* The offset must be casted to ptrdiff_ikind in order to have matching ikinds for the multiplication below *) + let casted_offset = IntDomain.IntDomTuple.cast_to (Cilfacade.ptrdiff_ikind ()) i in + `Lifted (IntDomain.IntDomTuple.mul casted_offset ptr_contents_typ_size_in_bytes) | `Top -> `Top | `Bot -> `Bot From 8a6cf0a10258cd6c433f6067111b10f93323002d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 10 Sep 2023 02:11:41 +0200 Subject: [PATCH 282/628] Check and warn everywhere for a top points-to set in memOutOfBounds --- src/analyses/memOutOfBounds.ml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index a2c180a453..781c48d8e9 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -88,7 +88,9 @@ struct match ctx.ask (Queries.MayPointTo ptr) with | a when not (Queries.LS.is_top a) && not (Queries.LS.mem (dummyFunDec.svar, `NoOffset) a) -> Queries.LS.for_all (fun (v, _) -> ctx.ask (Queries.IsHeapVar v)) a - | _ -> false + | _ -> + M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; + false let get_size_of_ptr_target ctx ptr = if points_to_heap_only ctx ptr then @@ -124,7 +126,7 @@ struct ) x xs end | _ -> - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; VDQ.ID.top () let get_ptr_deref_type ptr_typ = @@ -163,11 +165,16 @@ struct IntDomain.IntDomTuple.add bytes_offset remaining_offset let ptr_only_has_str_addr ctx ptr = - ctx.ask (Queries.MayPointTo ptr) - |> VDQ.LS.elements - |> List.map (fun (v, o) -> ValueDomain.Addr.of_mval (v, ValueDomain.Addr.Offs.of_exp o)) - |> ValueDomain.AD.of_list - |> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (VDQ.LS.is_top a) -> + VDQ.LS.elements a + |> List.map (fun (v, o) -> ValueDomain.Addr.of_mval (v, ValueDomain.Addr.Offs.of_exp o)) + |> ValueDomain.AD.of_list + |> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) + | _ -> + M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; + (* Intuition: if the points-to set is top, then we don't know with certainty if there are only string addresses inside *) + false let rec get_addr_offs ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with @@ -203,10 +210,8 @@ struct IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () end | _ -> - ( - set_mem_safety_flag InvalidDeref; - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr - ); + set_mem_safety_flag InvalidDeref; + M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = From 29f13a281aa183722b375c163d427c434d70dcbd Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 10 Sep 2023 14:06:34 +0200 Subject: [PATCH 283/628] Simplify string address check and remove extra warning --- src/analyses/memOutOfBounds.ml | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 781c48d8e9..de18021278 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -88,9 +88,7 @@ struct match ctx.ask (Queries.MayPointTo ptr) with | a when not (Queries.LS.is_top a) && not (Queries.LS.mem (dummyFunDec.svar, `NoOffset) a) -> Queries.LS.for_all (fun (v, _) -> ctx.ask (Queries.IsHeapVar v)) a - | _ -> - M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; - false + | _ -> false let get_size_of_ptr_target ctx ptr = if points_to_heap_only ctx ptr then @@ -165,16 +163,14 @@ struct IntDomain.IntDomTuple.add bytes_offset remaining_offset let ptr_only_has_str_addr ctx ptr = - match ctx.ask (Queries.MayPointTo ptr) with - | a when not (VDQ.LS.is_top a) -> - VDQ.LS.elements a - |> List.map (fun (v, o) -> ValueDomain.Addr.of_mval (v, ValueDomain.Addr.Offs.of_exp o)) - |> ValueDomain.AD.of_list - |> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) - | _ -> - M.warn "Pointer %a has a points-to set of top. An invalid memory access might occur" d_exp ptr; - (* Intuition: if the points-to set is top, then we don't know with certainty if there are only string addresses inside *) - false + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could all sorts of things and not only string addresses *) + | _ -> false let rec get_addr_offs ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with From 7bdce29722c52c4366f0ff7457ad2b6c12f2ebeb Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 10 Sep 2023 14:17:25 +0200 Subject: [PATCH 284/628] Add check for dereferencing a pointer containing an unknown address --- src/analyses/memOutOfBounds.ml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index de18021278..9f9708335f 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -162,6 +162,22 @@ struct let remaining_offset = offs_to_idx typ o in IntDomain.IntDomTuple.add bytes_offset remaining_offset + let check_unknown_addr_deref ctx ptr = + let may_contain_unknown_addr = + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.may_be_unknown a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could potentially evaluate to the unknown address *) + | _ -> true + in + if may_contain_unknown_addr then begin + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior (Undefined Other)) "Pointer %a contains an unknown address. Invalid dereference may occur" d_exp ptr + end + let ptr_only_has_str_addr ctx ptr = match ctx.ask (Queries.EvalValue ptr) with | a when not (Queries.VD.is_top a) -> @@ -230,6 +246,7 @@ struct end and check_no_binop_deref ctx lval_exp = + check_unknown_addr_deref ctx lval_exp; let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in let ptr_size = get_size_of_ptr_target ctx lval_exp in @@ -276,6 +293,7 @@ struct | AddrOf lval -> check_lval_for_oob_access ctx ~is_implicitly_derefed lval and check_binop_exp ctx binop e1 e2 t = + check_unknown_addr_deref ctx e1; let binopexp = BinOp (binop, e1, e2, t) in let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in From 3c014186d9f77bec2e734828aee0c1caf8a24b6b Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 13 Sep 2023 15:14:54 +0200 Subject: [PATCH 285/628] Remove unused function --- src/analyses/memOutOfBounds.ml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 9f9708335f..01bc12d7cb 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -23,33 +23,6 @@ struct let intdom_of_int x = IntDomain.IntDomTuple.of_int (Cilfacade.ptrdiff_ikind ()) (Z.of_int x) - let to_index ?typ offs = - let idx_of_int x = - IntDomain.IntDomTuple.of_int (Cilfacade.ptrdiff_ikind ()) (Z.of_int (x / 8)) - in - let rec offset_to_index_offset ?typ offs = match offs with - | `NoOffset -> idx_of_int 0 - | `Field (field, o) -> - let field_as_offset = Field (field, NoOffset) in - let bits_offset, _size = GoblintCil.bitsOffset (TComp (field.fcomp, [])) field_as_offset in - let bits_offset = idx_of_int bits_offset in - let remaining_offset = offset_to_index_offset ~typ:field.ftype o in - IntDomain.IntDomTuple.add bits_offset remaining_offset - | `Index (x, o) -> - let (item_typ, item_size_in_bits) = - match Option.map unrollType typ with - | Some TArray(item_typ, _, _) -> - let item_size_in_bits = bitsSizeOf item_typ in - (Some item_typ, idx_of_int item_size_in_bits) - | _ -> - (None, IntDomain.IntDomTuple.top_of @@ Cilfacade.ptrdiff_ikind ()) - in - let bits_offset = IntDomain.IntDomTuple.mul item_size_in_bits x in - let remaining_offset = offset_to_index_offset ?typ:item_typ o in - IntDomain.IntDomTuple.add bits_offset remaining_offset - in - offset_to_index_offset ?typ offs - let rec exp_contains_a_ptr (exp:exp) = match exp with | Const _ From 15f782b9efd276da84cbbf8121f04eb2e47101b8 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 13 Sep 2023 15:25:44 +0200 Subject: [PATCH 286/628] Add exception handling for intdom arithmetic in memOutOfBounds --- src/analyses/memOutOfBounds.ml | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 01bc12d7cb..61e1b1a808 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -77,7 +77,11 @@ struct let item_typ_size_in_bytes = (bitsSizeOf item_typ) / 8 in let item_typ_size_in_bytes = intdom_of_int item_typ_size_in_bytes in begin match ctx.ask (Queries.EvalLength ptr) with - | `Lifted arr_len -> `Lifted (IntDomain.IntDomTuple.mul item_typ_size_in_bytes arr_len) + | `Lifted arr_len -> + begin + try `Lifted (IntDomain.IntDomTuple.mul item_typ_size_in_bytes arr_len) + with IntDomain.ArithmeticOnIntegerBot _ -> VDQ.ID.bot () + end | `Bot -> VDQ.ID.bot () | `Top -> VDQ.ID.top () end @@ -116,7 +120,10 @@ struct | `Lifted i -> (* The offset must be casted to ptrdiff_ikind in order to have matching ikinds for the multiplication below *) let casted_offset = IntDomain.IntDomTuple.cast_to (Cilfacade.ptrdiff_ikind ()) i in - `Lifted (IntDomain.IntDomTuple.mul casted_offset ptr_contents_typ_size_in_bytes) + begin + try `Lifted (IntDomain.IntDomTuple.mul casted_offset ptr_contents_typ_size_in_bytes) + with IntDomain.ArithmeticOnIntegerBot _ -> `Bot + end | `Top -> `Top | `Bot -> `Bot @@ -128,12 +135,18 @@ struct let bits_offset, _size = GoblintCil.bitsOffset (TComp (field.fcomp, [])) field_as_offset in let bytes_offset = intdom_of_int (bits_offset / 8) in let remaining_offset = offs_to_idx field.ftype o in - IntDomain.IntDomTuple.add bytes_offset remaining_offset + begin + try IntDomain.IntDomTuple.add bytes_offset remaining_offset + with IntDomain.ArithmeticOnIntegerBot _ -> IntDomain.IntDomTuple.bot_of @@ Cilfacade.ptrdiff_ikind () + end | `Index (x, o) -> - let typ_size_in_bytes = size_of_type_in_bytes typ in - let bytes_offset = IntDomain.IntDomTuple.mul typ_size_in_bytes x in - let remaining_offset = offs_to_idx typ o in - IntDomain.IntDomTuple.add bytes_offset remaining_offset + begin try + let typ_size_in_bytes = size_of_type_in_bytes typ in + let bytes_offset = IntDomain.IntDomTuple.mul typ_size_in_bytes x in + let remaining_offset = offs_to_idx typ o in + IntDomain.IntDomTuple.add bytes_offset remaining_offset + with IntDomain.ArithmeticOnIntegerBot _ -> IntDomain.IntDomTuple.bot_of @@ Cilfacade.ptrdiff_ikind () + end let check_unknown_addr_deref ctx ptr = let may_contain_unknown_addr = @@ -283,7 +296,11 @@ struct let offset_size = eval_ptr_offset_in_binop ctx e2 t in (* Make sure to add the address offset to the binop offset *) let offset_size_with_addr_size = match offset_size with - | `Lifted os -> `Lifted (IntDomain.IntDomTuple.add os addr_offs) + | `Lifted os -> + begin + try `Lifted (IntDomain.IntDomTuple.add os addr_offs) + with IntDomain.ArithmeticOnIntegerBot _ -> `Bot + end | `Top -> `Top | `Bot -> `Bot in From 20433e34c968f8c413bb1042f1165f547a70f203 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 13 Sep 2023 17:15:58 +0200 Subject: [PATCH 287/628] Ignore info messages for test case 77/05 due to MacOS CI --- tests/regression/77-mem-oob/05-oob-implicit-deref.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/regression/77-mem-oob/05-oob-implicit-deref.c b/tests/regression/77-mem-oob/05-oob-implicit-deref.c index 088493d3b9..8bec6a72e0 100644 --- a/tests/regression/77-mem-oob/05-oob-implicit-deref.c +++ b/tests/regression/77-mem-oob/05-oob-implicit-deref.c @@ -1,4 +1,8 @@ -// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info +/* + Note: the "--disable warn.info" above is a temporary workaround, + since the GitHub CI seems to be considering Info messages as violations of NOWARN (cf. https://github.com/goblint/analyzer/issues/1151) +*/ #include #include #include From 1116ef622f21fb53e82780317c19088c9bad25de Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 24 Sep 2023 14:22:35 +0200 Subject: [PATCH 288/628] No shortcut `meet` and `narrow` w/ int refinement --- src/domains/lattice.ml | 9 +++++++-- .../regression/38-int-refinements/06-narrow.c | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/regression/38-int-refinements/06-narrow.c diff --git a/src/domains/lattice.ml b/src/domains/lattice.ml index 4cdaa8fb9f..841d1d61b7 100644 --- a/src/domains/lattice.ml +++ b/src/domains/lattice.ml @@ -151,10 +151,15 @@ end module HConsed (Base:S) = struct include Printable.HConsed (Base) + + (* We do refine int values on narrow and meet {!IntDomain.IntDomTupleImpl}, which can lead to fixpoint issues *) + (* see https://github.com/goblint/analyzer/issues/1005 *) + let int_refine_active = GobConfig.get_string "ana.int.refinement" <> "never" + let lift_f2 f x y = f (unlift x) (unlift y) - let narrow x y = if x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.narrow x y) + let narrow x y = if (not int_refine_active) && x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.narrow x y) let widen x y = if x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.widen x y) - let meet x y = if x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.meet x y) + let meet x y = if (not int_refine_active) && x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.meet x y) let join x y = if x.BatHashcons.tag == y.BatHashcons.tag then x else lift (lift_f2 Base.join x y) let leq x y = (x.BatHashcons.tag == y.BatHashcons.tag) || lift_f2 Base.leq x y let is_top = lift_f Base.is_top diff --git a/tests/regression/38-int-refinements/06-narrow.c b/tests/regression/38-int-refinements/06-narrow.c new file mode 100644 index 0000000000..513e9dde60 --- /dev/null +++ b/tests/regression/38-int-refinements/06-narrow.c @@ -0,0 +1,18 @@ +// PARAM: --set ana.int.refinement fixpoint --enable ana.int.interval +// FIXPOINT +#include + +int g = 0; + +void main() +{ + int i = 0; + while (1) { + i++; + for (int j=0; j < 10; j++) { + if (i > 100) g = 1; + } + if (i>9) i=0; + } + return; +} From 2f691be58f2367cdf2f8fb51e7fcf947b0571df3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 24 Sep 2023 14:23:42 +0200 Subject: [PATCH 289/628] Make comment a bit longer --- src/domains/lattice.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domains/lattice.ml b/src/domains/lattice.ml index 841d1d61b7..3e1207b8b1 100644 --- a/src/domains/lattice.ml +++ b/src/domains/lattice.ml @@ -152,7 +152,7 @@ module HConsed (Base:S) = struct include Printable.HConsed (Base) - (* We do refine int values on narrow and meet {!IntDomain.IntDomTupleImpl}, which can lead to fixpoint issues *) + (* We do refine int values on narrow and meet {!IntDomain.IntDomTupleImpl}, which can lead to fixpoint issues if we assume x op x = x *) (* see https://github.com/goblint/analyzer/issues/1005 *) let int_refine_active = GobConfig.get_string "ana.int.refinement" <> "never" From 08d56aa0d8e6e13b1ff87fd11d3bdffc8218611a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 24 Sep 2023 16:51:17 +0200 Subject: [PATCH 290/628] Add argument to `threadenter` --- src/analyses/abortUnless.ml | 2 +- src/analyses/accessAnalysis.ml | 2 +- src/analyses/activeLongjmp.ml | 2 +- src/analyses/activeSetjmp.ml | 2 +- src/analyses/apron/relationAnalysis.apron.ml | 2 +- src/analyses/base.ml | 2 +- src/analyses/condVars.ml | 2 +- src/analyses/expsplit.ml | 2 +- src/analyses/extractPthread.ml | 2 +- src/analyses/fileUse.ml | 2 +- src/analyses/locksetAnalysis.ml | 2 +- src/analyses/mCP.ml | 12 ++++----- src/analyses/mallocFresh.ml | 2 +- src/analyses/malloc_null.ml | 2 +- src/analyses/modifiedSinceLongjmp.ml | 2 +- src/analyses/mutexTypeAnalysis.ml | 2 +- src/analyses/poisonVariables.ml | 2 +- src/analyses/pthreadSignals.ml | 2 +- src/analyses/region.ml | 2 +- src/analyses/spec.ml | 2 +- src/analyses/stackTrace.ml | 4 +-- src/analyses/symbLocks.ml | 2 +- src/analyses/taintPartialContexts.ml | 2 +- src/analyses/termination.ml | 2 +- src/analyses/threadAnalysis.ml | 2 +- src/analyses/threadEscape.ml | 2 +- src/analyses/threadFlag.ml | 2 +- src/analyses/threadId.ml | 8 +++--- src/analyses/threadReturn.ml | 2 +- src/analyses/tmpSpecial.ml | 2 +- src/analyses/tutorials/taint.ml | 2 +- src/analyses/tutorials/unitAnalysis.ml | 2 +- src/analyses/uninit.ml | 2 +- src/analyses/useAfterFree.ml | 4 +-- src/analyses/varEq.ml | 2 +- src/analyses/vla.ml | 2 +- src/analyses/wrapperFunctionAnalysis.ml | 2 +- src/framework/analyses.ml | 6 ++--- src/framework/constraints.ml | 27 ++++++++++---------- src/framework/control.ml | 6 ++--- src/framework/resultQuery.ml | 6 ++--- src/util/wideningTokens.ml | 2 +- src/witness/observerAnalysis.ml | 2 +- src/witness/witnessConstraints.ml | 4 +-- 44 files changed, 74 insertions(+), 73 deletions(-) diff --git a/src/analyses/abortUnless.ml b/src/analyses/abortUnless.ml index 813d999ac3..1c77803c7e 100644 --- a/src/analyses/abortUnless.ml +++ b/src/analyses/abortUnless.ml @@ -65,7 +65,7 @@ struct false let startstate v = false - let threadenter ctx lval f args = [false] + let threadenter ?(multiple=false) ctx lval f args = [false] let threadspawn ctx lval f args fctx = false let exitstate v = false end diff --git a/src/analyses/accessAnalysis.ml b/src/analyses/accessAnalysis.ml index e99aefa0e5..bd1ca528a7 100644 --- a/src/analyses/accessAnalysis.ml +++ b/src/analyses/accessAnalysis.ml @@ -54,7 +54,7 @@ struct (** We just lift start state, global and dependency functions: *) let startstate v = () - let threadenter ctx lval f args = [()] + let threadenter ?(multiple=false) ctx lval f args = [()] let exitstate v = () let context fd d = () diff --git a/src/analyses/activeLongjmp.ml b/src/analyses/activeLongjmp.ml index 9c9868e32f..43da8c6512 100644 --- a/src/analyses/activeLongjmp.ml +++ b/src/analyses/activeLongjmp.ml @@ -26,7 +26,7 @@ struct (* Initial values don't really matter: overwritten at longjmp call. *) let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/activeSetjmp.ml b/src/analyses/activeSetjmp.ml index 069111d3ba..a69bf4db95 100644 --- a/src/analyses/activeSetjmp.ml +++ b/src/analyses/activeSetjmp.ml @@ -25,7 +25,7 @@ struct | _ -> ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 46c620f390..d56064a42f 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -647,7 +647,7 @@ struct (* Thread transfer functions. *) - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = let st = ctx.local in match Cilfacade.find_varinfo_fundec f with | fd -> diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 71e2661997..cb29cbc0ab 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2503,7 +2503,7 @@ struct in combine_one ctx.local after - let threadenter ctx (lval: lval option) (f: varinfo) (args: exp list): D.t list = + let threadenter ?(multiple=false) ctx (lval: lval option) (f: varinfo) (args: exp list): D.t list = match Cilfacade.find_varinfo_fundec f with | fd -> [make_entry ~thread:true ctx fd args] diff --git a/src/analyses/condVars.ml b/src/analyses/condVars.ml index 04b148dd02..3a2cc5798d 100644 --- a/src/analyses/condVars.ml +++ b/src/analyses/condVars.ml @@ -155,7 +155,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/expsplit.ml b/src/analyses/expsplit.ml index f121d0380e..9c610a96bf 100644 --- a/src/analyses/expsplit.ml +++ b/src/analyses/expsplit.ml @@ -84,7 +84,7 @@ struct in emit_splits ctx d - let threadenter ctx lval f args = [ctx.local] + let threadenter ?(multiple=false) ctx lval f args = [ctx.local] let threadspawn ctx lval f args fctx = emit_splits_ctx ctx diff --git a/src/analyses/extractPthread.ml b/src/analyses/extractPthread.ml index 60e389fedf..591704cc70 100644 --- a/src/analyses/extractPthread.ml +++ b/src/analyses/extractPthread.ml @@ -1238,7 +1238,7 @@ module Spec : Analyses.MCPSpec = struct (Ctx.top ()) - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = let d : D.t = ctx.local in let tasks = ctx.global tasks_var in (* TODO: optimize finding *) diff --git a/src/analyses/fileUse.ml b/src/analyses/fileUse.ml index a9088a4bb2..b12953c71c 100644 --- a/src/analyses/fileUse.ml +++ b/src/analyses/fileUse.ml @@ -287,7 +287,7 @@ struct | _ -> m let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/locksetAnalysis.ml b/src/analyses/locksetAnalysis.ml index 2e9e08f03d..56fe960a47 100644 --- a/src/analyses/locksetAnalysis.ml +++ b/src/analyses/locksetAnalysis.ml @@ -18,7 +18,7 @@ struct module C = D let startstate v = D.empty () - let threadenter ctx lval f args = [D.empty ()] + let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] let exitstate v = D.empty () end diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 1b6a7e5a1d..e305e9c7f6 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -140,9 +140,9 @@ struct f ((k,v::a')::a) b in f [] xs - let do_spawns ctx (xs:(varinfo * (lval option * exp list)) list) = + let do_spawns ctx (xs:(varinfo * (lval option * exp list * bool)) list) = let spawn_one v d = - List.iter (fun (lval, args) -> ctx.spawn lval v args) d + List.iter (fun (lval, args, multiple) -> ctx.spawn ~multiple lval v args) d in if not (get_bool "exp.single-threaded") then iter (uncurry spawn_one) @@ group_assoc_eq Basetype.Variables.equal xs @@ -322,8 +322,8 @@ struct and outer_ctx tfname ?spawns ?sides ?emits ctx = let spawn = match spawns with - | Some spawns -> (fun l v a -> spawns := (v,(l,a)) :: !spawns) - | None -> (fun v d -> failwith ("Cannot \"spawn\" in " ^ tfname ^ " context.")) + | Some spawns -> (fun ?(multiple=false) l v a -> spawns := (v,(l,a,multiple)) :: !spawns) + | None -> (fun ?(multiple=false) v d -> failwith ("Cannot \"spawn\" in " ^ tfname ^ " context.")) in let sideg = match sides with | Some sides -> (fun v g -> sides := (v, (!WideningTokens.side_tokens, g)) :: !sides) @@ -565,13 +565,13 @@ struct let d = do_emits ctx !emits d q in if q then raise Deadcode else d - let threadenter (ctx:(D.t, G.t, C.t, V.t) ctx) lval f a = + let threadenter ?(multiple=false) (ctx:(D.t, G.t, C.t, V.t) ctx) lval f a = let sides = ref [] in let emits = ref [] in let ctx'' = outer_ctx "threadenter" ~sides ~emits ctx in let f (n,(module S:MCPSpec),d) = let ctx' : (S.D.t, S.G.t, S.C.t, S.V.t) ctx = inner_ctx "threadenter" ctx'' n d in - map (fun d -> (n, repr d)) @@ S.threadenter ctx' lval f a + map (fun d -> (n, repr d)) @@ (S.threadenter ~multiple) ctx' lval f a in let css = map f @@ spec_list ctx.local in do_sideg ctx !sides; diff --git a/src/analyses/mallocFresh.ml b/src/analyses/mallocFresh.ml index 2c2b99a075..861e4958bd 100644 --- a/src/analyses/mallocFresh.ml +++ b/src/analyses/mallocFresh.ml @@ -52,7 +52,7 @@ struct | None -> ctx.local | Some lval -> assign_lval (Analyses.ask_of_ctx ctx) lval ctx.local - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = diff --git a/src/analyses/malloc_null.ml b/src/analyses/malloc_null.ml index 4d5871cb80..2d90112636 100644 --- a/src/analyses/malloc_null.ml +++ b/src/analyses/malloc_null.ml @@ -215,7 +215,7 @@ struct let name () = "malloc_null" let startstate v = D.empty () - let threadenter ctx lval f args = [D.empty ()] + let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.empty () diff --git a/src/analyses/modifiedSinceLongjmp.ml b/src/analyses/modifiedSinceLongjmp.ml index 0375bd3f74..d9c8f5102c 100644 --- a/src/analyses/modifiedSinceLongjmp.ml +++ b/src/analyses/modifiedSinceLongjmp.ml @@ -63,7 +63,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/mutexTypeAnalysis.ml b/src/analyses/mutexTypeAnalysis.ml index 806c35f464..7051173bd0 100644 --- a/src/analyses/mutexTypeAnalysis.ml +++ b/src/analyses/mutexTypeAnalysis.ml @@ -65,7 +65,7 @@ struct | _ -> ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/poisonVariables.ml b/src/analyses/poisonVariables.ml index 1bd4b6d544..8c79626cc9 100644 --- a/src/analyses/poisonVariables.ml +++ b/src/analyses/poisonVariables.ml @@ -61,7 +61,7 @@ struct VS.join au ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.top () let event ctx e octx = diff --git a/src/analyses/pthreadSignals.ml b/src/analyses/pthreadSignals.ml index 0b776282e8..83455965ec 100644 --- a/src/analyses/pthreadSignals.ml +++ b/src/analyses/pthreadSignals.ml @@ -73,7 +73,7 @@ struct | _ -> ctx.local let startstate v = Signals.empty () - let threadenter ctx lval f args = [ctx.local] + let threadenter ?(multiple=false) ctx lval f args = [ctx.local] let exitstate v = Signals.empty () end diff --git a/src/analyses/region.ml b/src/analyses/region.ml index 6d2ae246c3..9d68221fcd 100644 --- a/src/analyses/region.ml +++ b/src/analyses/region.ml @@ -175,7 +175,7 @@ struct let startstate v = `Lifted (RegMap.bot ()) - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = [`Lifted (RegMap.bot ())] let threadspawn ctx lval f args fctx = ctx.local diff --git a/src/analyses/spec.ml b/src/analyses/spec.ml index 54ffcd2697..e5434eb264 100644 --- a/src/analyses/spec.ml +++ b/src/analyses/spec.ml @@ -487,7 +487,7 @@ struct let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/stackTrace.ml b/src/analyses/stackTrace.ml index 4dc62f1873..3d70c50856 100644 --- a/src/analyses/stackTrace.ml +++ b/src/analyses/stackTrace.ml @@ -21,7 +21,7 @@ struct ctx.local (* keep local as opposed to IdentitySpec *) let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.top () end @@ -45,7 +45,7 @@ struct let startstate v = D.bot () let exitstate v = D.top () - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = [D.push !Tracing.current_loc ctx.local] end diff --git a/src/analyses/symbLocks.ml b/src/analyses/symbLocks.ml index d8cebf51d2..b99ef93039 100644 --- a/src/analyses/symbLocks.ml +++ b/src/analyses/symbLocks.ml @@ -29,7 +29,7 @@ struct let name () = "symb_locks" let startstate v = D.top () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/taintPartialContexts.ml b/src/analyses/taintPartialContexts.ml index d053cd103b..25e981dcbf 100644 --- a/src/analyses/taintPartialContexts.ml +++ b/src/analyses/taintPartialContexts.ml @@ -101,7 +101,7 @@ struct d let startstate v = D.bot () - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = match lval with diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 6da9225d3f..5e5e0d36f1 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -217,7 +217,7 @@ struct (* | _ -> ctx.local *) let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let exitstate v = D.bot () end diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index 1e679a4707..26e6702c25 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -84,7 +84,7 @@ struct | _ -> Queries.Result.top q let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = let creator = ThreadId.get_current (Analyses.ask_of_ctx ctx) in let tid = ThreadId.get_current_unlift (Analyses.ask_of_ctx fctx) in diff --git a/src/analyses/threadEscape.ml b/src/analyses/threadEscape.ml index 9ed62e7422..0674ebf3d1 100644 --- a/src/analyses/threadEscape.ml +++ b/src/analyses/threadEscape.ml @@ -150,7 +150,7 @@ struct let startstate v = D.bot () let exitstate v = D.bot () - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = diff --git a/src/analyses/threadFlag.ml b/src/analyses/threadFlag.ml index f2ebf82be1..f3b132918a 100644 --- a/src/analyses/threadFlag.ml +++ b/src/analyses/threadFlag.ml @@ -58,7 +58,7 @@ struct let access ctx _ = is_currently_multi (Analyses.ask_of_ctx ctx) - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = if not (has_ever_been_multi (Analyses.ask_of_ctx ctx)) then ctx.emit Events.EnterMultiThreaded; [create_tid f] diff --git a/src/analyses/threadId.ml b/src/analyses/threadId.ml index 4acf88a7ef..f1de1dfdcb 100644 --- a/src/analyses/threadId.ml +++ b/src/analyses/threadId.ml @@ -56,9 +56,9 @@ struct Hashtbl.replace !tids tid (); (N.bot (), `Lifted (tid), (TD.bot (), TD.bot ())) - let create_tid (_, current, (td, _)) ((node, index): Node.t * int option) v = + let create_tid ?(multiple=false) (_, current, (td, _)) ((node, index): Node.t * int option) v = match current with - | `Lifted current -> + | `Lifted current when not multiple -> let+ tid = Thread.threadenter (current, td) node index v in if GobConfig.get_bool "dbg.print_tids" then Hashtbl.replace !tids tid (); @@ -133,9 +133,9 @@ struct | `Lifted node, count -> node, Some count | (`Bot | `Top), _ -> ctx.prev_node, None - let threadenter ctx lval f args:D.t list = + let threadenter ?(multiple=false) ctx lval f args:D.t list = let n, i = indexed_node_for_ctx ctx in - let+ tid = create_tid ctx.local (n, i) f in + let+ tid = create_tid ~multiple ctx.local (n, i) f in (`Lifted (f, n, i), tid, (TD.bot (), TD.bot ())) let threadspawn ctx lval f args fctx = diff --git a/src/analyses/threadReturn.ml b/src/analyses/threadReturn.ml index 470c4ceaa8..176a4d3465 100644 --- a/src/analyses/threadReturn.ml +++ b/src/analyses/threadReturn.ml @@ -28,7 +28,7 @@ struct ctx.local (* keep local as opposed to IdentitySpec *) let startstate v = true - let threadenter ctx lval f args = [true] + let threadenter ?(multiple=false) ctx lval f args = [true] let exitstate v = D.top () let query (ctx: (D.t, _, _, _) ctx) (type a) (x: a Queries.t): a Queries.result = diff --git a/src/analyses/tmpSpecial.ml b/src/analyses/tmpSpecial.ml index 2d38972d7a..f3d092e59e 100644 --- a/src/analyses/tmpSpecial.ml +++ b/src/analyses/tmpSpecial.ml @@ -88,7 +88,7 @@ struct | _ -> Queries.Result.top q let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/tutorials/taint.ml b/src/analyses/tutorials/taint.ml index 3067449e31..166ce2c3f6 100644 --- a/src/analyses/tutorials/taint.ml +++ b/src/analyses/tutorials/taint.ml @@ -129,7 +129,7 @@ struct (* You may leave these alone *) let startstate v = D.bot () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/tutorials/unitAnalysis.ml b/src/analyses/tutorials/unitAnalysis.ml index d3b8c69bfd..b5fb4d6367 100644 --- a/src/analyses/tutorials/unitAnalysis.ml +++ b/src/analyses/tutorials/unitAnalysis.ml @@ -39,7 +39,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/uninit.ml b/src/analyses/uninit.ml index f8759d9134..abdcd67aaa 100644 --- a/src/analyses/uninit.ml +++ b/src/analyses/uninit.ml @@ -25,7 +25,7 @@ struct let name () = "uninit" let startstate v : D.t = D.empty () - let threadenter ctx lval f args = [D.empty ()] + let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v : D.t = D.empty () diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 0aafbd1ad4..6033c689e1 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -196,7 +196,7 @@ struct end | _ -> state - let threadenter ctx lval f args = [ctx.local] + let threadenter ?(multiple=false) ctx lval f args = [ctx.local] let threadspawn ctx lval f args fctx = ctx.local let startstate v = D.bot () @@ -205,4 +205,4 @@ struct end let _ = - MCP.register_analysis (module Spec : MCPSpec) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/varEq.ml b/src/analyses/varEq.ml index 634a684c7c..7bd3453b8a 100644 --- a/src/analyses/varEq.ml +++ b/src/analyses/varEq.ml @@ -43,7 +43,7 @@ struct let name () = "var_eq" let startstate v = D.top () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/vla.ml b/src/analyses/vla.ml index 865f22b20a..8bd0168de0 100644 --- a/src/analyses/vla.ml +++ b/src/analyses/vla.ml @@ -33,7 +33,7 @@ struct ctx.local || Cilfacade.isVLAType v.vtype let startstate v = D.bot () - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let exitstate v = D.top () end diff --git a/src/analyses/wrapperFunctionAnalysis.ml b/src/analyses/wrapperFunctionAnalysis.ml index d9bbdb6197..89242e044e 100644 --- a/src/analyses/wrapperFunctionAnalysis.ml +++ b/src/analyses/wrapperFunctionAnalysis.ml @@ -87,7 +87,7 @@ struct let startstate v = D.bot () - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = (* The new thread receives a fresh counter *) [D.bot ()] diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index df3346af93..54a3a18f1a 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -342,7 +342,7 @@ type ('d,'g,'c,'v) ctx = ; edge : MyCFG.edge ; local : 'd ; global : 'v -> 'g - ; spawn : lval option -> varinfo -> exp list -> unit + ; spawn : ?multiple:bool -> lval option -> varinfo -> exp list -> unit ; split : 'd -> Events.t list -> unit ; sideg : 'v -> 'g -> unit } @@ -444,7 +444,7 @@ sig val paths_as_set : (D.t, G.t, C.t, V.t) ctx -> D.t list (** Returns initial state for created thread. *) - val threadenter : (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> D.t list + val threadenter : ?multiple:bool -> (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> D.t list (** Updates the local state of the creator thread using initial state of created thread. *) val threadspawn : (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> (D.t, G.t, C.t, V.t) ctx -> D.t @@ -696,7 +696,7 @@ struct let special ctx (lval: lval option) (f:varinfo) (arglist:exp list) = ctx.local - let threadenter ctx lval f args = [ctx.local] + let threadenter ?(multiple=false) ctx lval f args = [ctx.local] let threadspawn ctx lval f args fctx = ctx.local end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..a7683fb6b3 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -83,8 +83,8 @@ struct let combine_assign ctx r fe f args fc es f_ask = D.lift @@ S.combine_assign (conv ctx) r fe f args fc (D.unlift es) f_ask - let threadenter ctx lval f args = - List.map D.lift @@ S.threadenter (conv ctx) lval f args + let threadenter ?(multiple=false) ctx lval f args = + List.map D.lift @@ (S.threadenter ~multiple) (conv ctx) lval f args let threadspawn ctx lval f args fctx = D.lift @@ S.threadspawn (conv ctx) lval f args (conv fctx) @@ -167,8 +167,8 @@ struct let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.map C.unlift fc) es f_ask - let threadenter ctx lval f args = - S.threadenter (conv ctx) lval f args + let threadenter ?(multiple=false) ctx lval f args = + S.threadenter ~multiple (conv ctx) lval f args let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) @@ -249,7 +249,7 @@ struct let combine_env' ctx r fe f args fc es f_ask = lift_fun ctx (lift ctx) S.combine_env (fun p -> p r fe f args fc (fst es) f_ask) let combine_assign' ctx r fe f args fc es f_ask = lift_fun ctx (lift ctx) S.combine_assign (fun p -> p r fe f args fc (fst es) f_ask) - let threadenter ctx lval f args = lift_fun ctx (List.map lift_start_level) S.threadenter ((|>) args % (|>) f % (|>) lval) + let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (List.map lift_start_level) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) let threadspawn ctx lval f args fctx = lift_fun ctx (lift ctx) S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let leq0 = function @@ -394,7 +394,7 @@ struct let event ctx e octx = lift_fun ctx S.event ((|>) (conv octx) % (|>) e) - let threadenter ctx lval f args = S.threadenter (conv ctx) lval f args |> List.map (fun d -> (d, snd ctx.local)) + let threadenter ?(multiple=false) ctx lval f args = S.threadenter ~multiple (conv ctx) lval f args |> List.map (fun d -> (d, snd ctx.local)) let threadspawn ctx lval f args fctx = lift_fun ctx S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let enter ctx r f args = @@ -485,7 +485,7 @@ struct let combine_env ctx r fe f args fc es f_ask = lift_fun ctx D.lift S.combine_env (fun p -> p r fe f args fc (D.unlift es) f_ask) `Bot let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx D.lift S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) `Bot - let threadenter ctx lval f args = lift_fun ctx (List.map D.lift) S.threadenter ((|>) args % (|>) f % (|>) lval) [] + let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (List.map D.lift) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) [] let threadspawn ctx lval f args fctx = lift_fun ctx D.lift S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) `Bot 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 @@ -581,7 +581,7 @@ struct ; split = (fun (d:D.t) es -> assert (List.is_empty es); r := d::!r) ; sideg = (fun g d -> sideg (GVar.spec g) (G.create_spec d)) } - and spawn lval f args = + and spawn ?(multiple=false) lval f args = (* TODO: adjust ctx node/edge? *) (* TODO: don't repeat for all paths that spawn same *) let ds = S.threadenter ctx lval f args in @@ -898,7 +898,7 @@ struct ; edge = MyCFG.Skip ; local = S.startstate Cil.dummyFunDec.svar (* bot and top both silently raise and catch Deadcode in DeadcodeLifter *) ; global = (fun g -> G.spec (getg (GVar.spec g))) - ; spawn = (fun v d -> failwith "Cannot \"spawn\" in query context.") + ; spawn = (fun ?(multiple=false) v d -> failwith "Cannot \"spawn\" in query context.") ; split = (fun d es -> failwith "Cannot \"split\" in query context.") ; sideg = (fun v g -> failwith "Cannot \"split\" in query context.") } @@ -1262,9 +1262,10 @@ struct let fd1 = D.choose octx.local in map ctx Spec.event (fun h -> h e (conv octx fd1)) - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = let g xs ys = (List.map (fun y -> D.singleton y) ys) @ xs in - fold' ctx Spec.threadenter (fun h -> h lval f args) g [] + fold' ctx (Spec.threadenter ~multiple) (fun h -> h lval f args) g [] + let threadspawn ctx lval f args fctx = let fd1 = D.choose fctx.local in map ctx Spec.threadspawn (fun h -> h lval f args (conv fctx fd1)) @@ -1448,7 +1449,7 @@ struct let combine_env ctx = S.combine_env (conv ctx) let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) + let threadenter ?(multiple=false) ctx = S.threadenter ~multiple (conv ctx) let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) @@ -1684,7 +1685,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); S.D.bot () | _ -> S.special conv_ctx lv f args - let threadenter ctx = S.threadenter (conv ctx) + let threadenter ?(multiple=false) ctx = S.threadenter ~multiple (conv ctx) let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index 5cefc1a7de..72890be4b4 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -280,7 +280,7 @@ struct ; edge = MyCFG.Skip ; local = Spec.D.top () ; global = (fun g -> EQSys.G.spec (getg (EQSys.GVar.spec g))) - ; spawn = (fun _ -> failwith "Global initializers should never spawn threads. What is going on?") + ; spawn = (fun ?(multiple=false) _ -> failwith "Global initializers should never spawn threads. What is going on?") ; split = (fun _ -> failwith "Global initializers trying to split paths.") ; sideg = (fun g d -> sideg (EQSys.GVar.spec g) (EQSys.G.create_spec d)) } @@ -385,7 +385,7 @@ struct ; edge = MyCFG.Skip ; local = st ; global = (fun g -> EQSys.G.spec (getg (EQSys.GVar.spec g))) - ; spawn = (fun _ -> failwith "Bug1: Using enter_func for toplevel functions with 'otherstate'.") + ; spawn = (fun ?(multiple=false) _ -> failwith "Bug1: Using enter_func for toplevel functions with 'otherstate'.") ; split = (fun _ -> failwith "Bug2: Using enter_func for toplevel functions with 'otherstate'.") ; sideg = (fun g d -> sideg (EQSys.GVar.spec g) (EQSys.G.create_spec d)) } @@ -417,7 +417,7 @@ struct ; edge = MyCFG.Skip ; local = st ; global = (fun g -> EQSys.G.spec (getg (EQSys.GVar.spec g))) - ; spawn = (fun _ -> failwith "Bug1: Using enter_func for toplevel functions with 'otherstate'.") + ; spawn = (fun ?(multiple=false) _ -> failwith "Bug1: Using enter_func for toplevel functions with 'otherstate'.") ; split = (fun _ -> failwith "Bug2: Using enter_func for toplevel functions with 'otherstate'.") ; sideg = (fun g d -> sideg (EQSys.GVar.spec g) (EQSys.G.create_spec d)) } diff --git a/src/framework/resultQuery.ml b/src/framework/resultQuery.ml index ce5839ef30..c676c41c14 100644 --- a/src/framework/resultQuery.ml +++ b/src/framework/resultQuery.ml @@ -18,7 +18,7 @@ struct ; edge = MyCFG.Skip ; local = local ; global = (fun g -> try EQSys.G.spec (GHT.find gh (EQSys.GVar.spec g)) with Not_found -> Spec.G.bot ()) (* see 29/29 on why fallback is needed *) - ; spawn = (fun v d -> failwith "Cannot \"spawn\" in witness context.") + ; spawn = (fun ?(multiple=false) v d -> failwith "Cannot \"spawn\" in witness context.") ; split = (fun d es -> failwith "Cannot \"split\" in witness context.") ; sideg = (fun v g -> failwith "Cannot \"sideg\" in witness context.") } @@ -37,7 +37,7 @@ struct ; edge = MyCFG.Skip ; local = local ; global = (fun g -> try EQSys.G.spec (GHT.find gh (EQSys.GVar.spec g)) with Not_found -> Spec.G.bot ()) (* TODO: how can be missing? *) - ; spawn = (fun v d -> failwith "Cannot \"spawn\" in witness context.") + ; spawn = (fun ?(multiple=false) v d -> failwith "Cannot \"spawn\" in witness context.") ; split = (fun d es -> failwith "Cannot \"split\" in witness context.") ; sideg = (fun v g -> failwith "Cannot \"sideg\" in witness context.") } @@ -57,7 +57,7 @@ struct ; edge = MyCFG.Skip ; local = Spec.startstate GoblintCil.dummyFunDec.svar (* bot and top both silently raise and catch Deadcode in DeadcodeLifter *) (* TODO: is this startstate bad? *) ; global = (fun v -> EQSys.G.spec (try GHT.find gh (EQSys.GVar.spec v) with Not_found -> EQSys.G.bot ())) (* TODO: how can be missing? *) - ; spawn = (fun v d -> failwith "Cannot \"spawn\" in query context.") + ; spawn = (fun ?(multiple=false) v d -> failwith "Cannot \"spawn\" in query context.") ; split = (fun d es -> failwith "Cannot \"split\" in query context.") ; sideg = (fun v g -> failwith "Cannot \"split\" in query context.") } diff --git a/src/util/wideningTokens.ml b/src/util/wideningTokens.ml index 75f0e4f81d..c88f3f00c1 100644 --- a/src/util/wideningTokens.ml +++ b/src/util/wideningTokens.ml @@ -179,7 +179,7 @@ struct let combine_env ctx r fe f args fc es f_ask = lift_fun ctx lift' S.combine_env (fun p -> p r fe f args fc (D.unlift es) f_ask) (* TODO: use tokens from es *) let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx lift' S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) (* TODO: use tokens from es *) - let threadenter ctx lval f args = lift_fun ctx (fun l ts -> List.map (Fun.flip lift' ts) l) S.threadenter ((|>) args % (|>) f % (|>) lval) + let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (fun l ts -> List.map (Fun.flip lift' ts) l) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval ) let threadspawn ctx lval f args fctx = lift_fun ctx lift' S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let event ctx e octx = lift_fun ctx lift' S.event ((|>) (conv octx) % (|>) e) end diff --git a/src/witness/observerAnalysis.ml b/src/witness/observerAnalysis.ml index c8d8563909..3c702d199f 100644 --- a/src/witness/observerAnalysis.ml +++ b/src/witness/observerAnalysis.ml @@ -76,7 +76,7 @@ struct step_ctx ctx let startstate v = `Lifted Automaton.initial - let threadenter ctx lval f args = [D.top ()] + let threadenter ?(multiple=false) ctx lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/witness/witnessConstraints.ml b/src/witness/witnessConstraints.ml index 2ce16a5997..ad32713fa8 100644 --- a/src/witness/witnessConstraints.ml +++ b/src/witness/witnessConstraints.ml @@ -199,7 +199,7 @@ struct let r = Dom.bindings a in List.map (fun (x,v) -> (Dom.singleton x v, b)) r - let threadenter ctx lval f args = + let threadenter ?(multiple=false) ctx lval f args = let g xs x' ys = let ys' = List.map (fun y -> let yr = step ctx.prev_node (ctx.context ()) x' (ThreadEntry (lval, f, args)) (nosync x') in (* threadenter called on before-sync state *) @@ -208,7 +208,7 @@ struct in ys' @ xs in - fold' ctx Spec.threadenter (fun h -> h lval f args) g [] + fold' ctx (Spec.threadenter ~multiple) (fun h -> h lval f args) g [] let threadspawn ctx lval f args fctx = let fd1 = Dom.choose_key (fst fctx.local) in map ctx Spec.threadspawn (fun h -> h lval f args (conv fctx fd1)) From a32513936348d54c724697aba3943c409585f46a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 24 Sep 2023 17:28:01 +0200 Subject: [PATCH 291/628] Spawn non-unique threads --- src/analyses/base.ml | 14 +++++++------- src/analyses/threadAnalysis.ml | 8 +++++++- src/framework/constraints.ml | 2 +- tests/regression/40-threadid/09-multiple.c | 15 +++++++++++++++ .../regression/40-threadid/10-multiple-thread.c | 16 ++++++++++++++++ 5 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/regression/40-threadid/09-multiple.c create mode 100644 tests/regression/40-threadid/10-multiple-thread.c diff --git a/src/analyses/base.ml b/src/analyses/base.ml index cb29cbc0ab..3b6be2eff8 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1902,7 +1902,7 @@ struct - let forkfun (ctx:(D.t, G.t, C.t, V.t) Analyses.ctx) (lv: lval option) (f: varinfo) (args: exp list) : (lval option * varinfo * exp list) list = + let forkfun (ctx:(D.t, G.t, C.t, V.t) Analyses.ctx) (lv: lval option) (f: varinfo) (args: exp list) : (lval option * varinfo * exp list) list * bool = let create_thread lval arg v = try (* try to get function declaration *) @@ -1943,7 +1943,7 @@ struct else start_funvars in - List.filter_map (create_thread (Some (Mem id, NoOffset)) (Some ptc_arg)) start_funvars_with_unknown + List.filter_map (create_thread (Some (Mem id, NoOffset)) (Some ptc_arg)) start_funvars_with_unknown, false end | _, _ when get_bool "sem.unknown_function.spawn" -> (* TODO: Remove sem.unknown_function.spawn check because it is (and should be) really done in LibraryFunctions. @@ -1956,9 +1956,9 @@ struct let deep_flist = collect_invalidate ~deep:true (Analyses.ask_of_ctx ctx) ctx.global ctx.local deep_args in let flist = shallow_flist @ deep_flist in let addrs = List.concat_map AD.to_var_may flist in - if addrs <> [] then M.debug ~category:Analyzer "Spawning functions from unknown function: %a" (d_list ", " CilType.Varinfo.pretty) addrs; - List.filter_map (create_thread None None) addrs - | _, _ -> [] + if addrs <> [] then M.debug ~category:Analyzer "Spawning non-unique functions from unknown function: %a" (d_list ", " CilType.Varinfo.pretty) addrs; + List.filter_map (create_thread None None) addrs, true + | _, _ -> [], false let assert_fn ctx e refine = (* make the state meet the assertion in the rest of the code *) @@ -2024,9 +2024,9 @@ struct let addr = eval_lv (Analyses.ask_of_ctx ctx) ctx.global ctx.local lval in (addr, AD.type_of addr) in - let forks = forkfun ctx lv f args in + let forks, multiple = forkfun ctx lv f args in if M.tracing then if not (List.is_empty forks) then M.tracel "spawn" "Base.special %s: spawning functions %a\n" f.vname (d_list "," CilType.Varinfo.pretty) (List.map BatTuple.Tuple3.second forks); - List.iter (BatTuple.Tuple3.uncurry ctx.spawn) forks; + List.iter (BatTuple.Tuple3.uncurry (ctx.spawn ~multiple)) forks; let st: store = ctx.local in let gs = ctx.global in let desc = LF.find f in diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index 26e6702c25..740cca3a53 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -84,7 +84,13 @@ struct | _ -> Queries.Result.top q let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + + let threadenter ?(multiple=false) ctx lval f args = + if multiple then + (let tid = ThreadId.get_current_unlift (Analyses.ask_of_ctx ctx) in + ctx.sideg tid (true, TS.bot (), false)); + [D.bot ()] + let threadspawn ctx lval f args fctx = let creator = ThreadId.get_current (Analyses.ask_of_ctx ctx) in let tid = ThreadId.get_current_unlift (Analyses.ask_of_ctx fctx) in diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a7683fb6b3..62b8d46efa 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -584,7 +584,7 @@ struct and spawn ?(multiple=false) lval f args = (* TODO: adjust ctx node/edge? *) (* TODO: don't repeat for all paths that spawn same *) - let ds = S.threadenter ctx lval f args in + let ds = S.threadenter ~multiple ctx lval f args in List.iter (fun d -> spawns := (lval, f, args, d) :: !spawns; match Cilfacade.find_varinfo_fundec f with diff --git a/tests/regression/40-threadid/09-multiple.c b/tests/regression/40-threadid/09-multiple.c new file mode 100644 index 0000000000..5510e5ae07 --- /dev/null +++ b/tests/regression/40-threadid/09-multiple.c @@ -0,0 +1,15 @@ +#include +#include + +int myglobal; + +void *t_fun(void *arg) { + myglobal=40; //RACE + return NULL; +} + +int main(void) { + // This should spawn a non-unique thread + unknown(t_fun); + return 0; +} diff --git a/tests/regression/40-threadid/10-multiple-thread.c b/tests/regression/40-threadid/10-multiple-thread.c new file mode 100644 index 0000000000..0024d268ec --- /dev/null +++ b/tests/regression/40-threadid/10-multiple-thread.c @@ -0,0 +1,16 @@ +// PARAM: --set ana.activated[+] thread +#include +#include + +int myglobal; + +void *t_fun(void *arg) { + myglobal=40; //RACE + return NULL; +} + +int main(void) { + // This should spawn a non-unique thread + unknown(t_fun); + return 0; +} From ccaffc592932a7c6ca219aadc28d6f7b74188fcf Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Mon, 25 Sep 2023 13:07:31 +0200 Subject: [PATCH 292/628] Turn optional argument into named argument --- src/analyses/abortUnless.ml | 2 +- src/analyses/accessAnalysis.ml | 2 +- src/analyses/activeLongjmp.ml | 2 +- src/analyses/activeSetjmp.ml | 2 +- src/analyses/apron/relationAnalysis.apron.ml | 2 +- src/analyses/base.ml | 2 +- src/analyses/condVars.ml | 2 +- src/analyses/expsplit.ml | 2 +- src/analyses/extractPthread.ml | 2 +- src/analyses/fileUse.ml | 2 +- src/analyses/locksetAnalysis.ml | 2 +- src/analyses/mCP.ml | 2 +- src/analyses/mallocFresh.ml | 2 +- src/analyses/malloc_null.ml | 2 +- src/analyses/modifiedSinceLongjmp.ml | 2 +- src/analyses/mutexTypeAnalysis.ml | 2 +- src/analyses/poisonVariables.ml | 2 +- src/analyses/pthreadSignals.ml | 2 +- src/analyses/region.ml | 2 +- src/analyses/spec.ml | 2 +- src/analyses/stackTrace.ml | 4 ++-- src/analyses/symbLocks.ml | 2 +- src/analyses/taintPartialContexts.ml | 2 +- src/analyses/termination.ml | 2 +- src/analyses/threadAnalysis.ml | 2 +- src/analyses/threadEscape.ml | 2 +- src/analyses/threadFlag.ml | 2 +- src/analyses/threadId.ml | 2 +- src/analyses/threadReturn.ml | 2 +- src/analyses/tmpSpecial.ml | 2 +- src/analyses/tutorials/taint.ml | 2 +- src/analyses/tutorials/unitAnalysis.ml | 2 +- src/analyses/uninit.ml | 2 +- src/analyses/useAfterFree.ml | 2 +- src/analyses/varEq.ml | 2 +- src/analyses/vla.ml | 2 +- src/analyses/wrapperFunctionAnalysis.ml | 2 +- src/framework/analyses.ml | 4 ++-- src/framework/constraints.ml | 20 ++++++++++---------- src/framework/control.ml | 2 +- src/util/wideningTokens.ml | 2 +- src/witness/observerAnalysis.ml | 2 +- src/witness/witnessConstraints.ml | 2 +- 43 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/analyses/abortUnless.ml b/src/analyses/abortUnless.ml index 1c77803c7e..5c24e61f7c 100644 --- a/src/analyses/abortUnless.ml +++ b/src/analyses/abortUnless.ml @@ -65,7 +65,7 @@ struct false let startstate v = false - let threadenter ?(multiple=false) ctx lval f args = [false] + let threadenter ctx ~multiple lval f args = [false] let threadspawn ctx lval f args fctx = false let exitstate v = false end diff --git a/src/analyses/accessAnalysis.ml b/src/analyses/accessAnalysis.ml index bd1ca528a7..f0025c2f1c 100644 --- a/src/analyses/accessAnalysis.ml +++ b/src/analyses/accessAnalysis.ml @@ -54,7 +54,7 @@ struct (** We just lift start state, global and dependency functions: *) let startstate v = () - let threadenter ?(multiple=false) ctx lval f args = [()] + let threadenter ctx ~multiple lval f args = [()] let exitstate v = () let context fd d = () diff --git a/src/analyses/activeLongjmp.ml b/src/analyses/activeLongjmp.ml index 43da8c6512..9baa601ddc 100644 --- a/src/analyses/activeLongjmp.ml +++ b/src/analyses/activeLongjmp.ml @@ -26,7 +26,7 @@ struct (* Initial values don't really matter: overwritten at longjmp call. *) let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/activeSetjmp.ml b/src/analyses/activeSetjmp.ml index a69bf4db95..be13489993 100644 --- a/src/analyses/activeSetjmp.ml +++ b/src/analyses/activeSetjmp.ml @@ -25,7 +25,7 @@ struct | _ -> ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index d56064a42f..c232ccae9b 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -647,7 +647,7 @@ struct (* Thread transfer functions. *) - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = let st = ctx.local in match Cilfacade.find_varinfo_fundec f with | fd -> diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 3b6be2eff8..e824fac013 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2503,7 +2503,7 @@ struct in combine_one ctx.local after - let threadenter ?(multiple=false) ctx (lval: lval option) (f: varinfo) (args: exp list): D.t list = + let threadenter ctx ~multiple (lval: lval option) (f: varinfo) (args: exp list): D.t list = match Cilfacade.find_varinfo_fundec f with | fd -> [make_entry ~thread:true ctx fd args] diff --git a/src/analyses/condVars.ml b/src/analyses/condVars.ml index 3a2cc5798d..820ff69efa 100644 --- a/src/analyses/condVars.ml +++ b/src/analyses/condVars.ml @@ -155,7 +155,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/expsplit.ml b/src/analyses/expsplit.ml index 9c610a96bf..141a04283b 100644 --- a/src/analyses/expsplit.ml +++ b/src/analyses/expsplit.ml @@ -84,7 +84,7 @@ struct in emit_splits ctx d - let threadenter ?(multiple=false) ctx lval f args = [ctx.local] + let threadenter ctx ~multiple lval f args = [ctx.local] let threadspawn ctx lval f args fctx = emit_splits_ctx ctx diff --git a/src/analyses/extractPthread.ml b/src/analyses/extractPthread.ml index 591704cc70..f72f72c1fe 100644 --- a/src/analyses/extractPthread.ml +++ b/src/analyses/extractPthread.ml @@ -1238,7 +1238,7 @@ module Spec : Analyses.MCPSpec = struct (Ctx.top ()) - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = let d : D.t = ctx.local in let tasks = ctx.global tasks_var in (* TODO: optimize finding *) diff --git a/src/analyses/fileUse.ml b/src/analyses/fileUse.ml index b12953c71c..b8e7fd78f5 100644 --- a/src/analyses/fileUse.ml +++ b/src/analyses/fileUse.ml @@ -287,7 +287,7 @@ struct | _ -> m let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/locksetAnalysis.ml b/src/analyses/locksetAnalysis.ml index 56fe960a47..6a816b9e6c 100644 --- a/src/analyses/locksetAnalysis.ml +++ b/src/analyses/locksetAnalysis.ml @@ -18,7 +18,7 @@ struct module C = D let startstate v = D.empty () - let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] + let threadenter ctx ~multiple lval f args = [D.empty ()] let exitstate v = D.empty () end diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index e305e9c7f6..5259bdb6c7 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -565,7 +565,7 @@ struct let d = do_emits ctx !emits d q in if q then raise Deadcode else d - let threadenter ?(multiple=false) (ctx:(D.t, G.t, C.t, V.t) ctx) lval f a = + let threadenter (ctx:(D.t, G.t, C.t, V.t) ctx) ~multiple lval f a = let sides = ref [] in let emits = ref [] in let ctx'' = outer_ctx "threadenter" ~sides ~emits ctx in diff --git a/src/analyses/mallocFresh.ml b/src/analyses/mallocFresh.ml index 861e4958bd..e171ad4ea1 100644 --- a/src/analyses/mallocFresh.ml +++ b/src/analyses/mallocFresh.ml @@ -52,7 +52,7 @@ struct | None -> ctx.local | Some lval -> assign_lval (Analyses.ask_of_ctx ctx) lval ctx.local - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = diff --git a/src/analyses/malloc_null.ml b/src/analyses/malloc_null.ml index 2d90112636..41c251dfce 100644 --- a/src/analyses/malloc_null.ml +++ b/src/analyses/malloc_null.ml @@ -215,7 +215,7 @@ struct let name () = "malloc_null" let startstate v = D.empty () - let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] + let threadenter ctx ~multiple lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.empty () diff --git a/src/analyses/modifiedSinceLongjmp.ml b/src/analyses/modifiedSinceLongjmp.ml index d9c8f5102c..7da0030b9a 100644 --- a/src/analyses/modifiedSinceLongjmp.ml +++ b/src/analyses/modifiedSinceLongjmp.ml @@ -63,7 +63,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/mutexTypeAnalysis.ml b/src/analyses/mutexTypeAnalysis.ml index 7051173bd0..66e60aede1 100644 --- a/src/analyses/mutexTypeAnalysis.ml +++ b/src/analyses/mutexTypeAnalysis.ml @@ -65,7 +65,7 @@ struct | _ -> ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/poisonVariables.ml b/src/analyses/poisonVariables.ml index 8c79626cc9..87dddd1e54 100644 --- a/src/analyses/poisonVariables.ml +++ b/src/analyses/poisonVariables.ml @@ -61,7 +61,7 @@ struct VS.join au ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.top () let event ctx e octx = diff --git a/src/analyses/pthreadSignals.ml b/src/analyses/pthreadSignals.ml index 83455965ec..70f1624922 100644 --- a/src/analyses/pthreadSignals.ml +++ b/src/analyses/pthreadSignals.ml @@ -73,7 +73,7 @@ struct | _ -> ctx.local let startstate v = Signals.empty () - let threadenter ?(multiple=false) ctx lval f args = [ctx.local] + let threadenter ctx ~multiple lval f args = [ctx.local] let exitstate v = Signals.empty () end diff --git a/src/analyses/region.ml b/src/analyses/region.ml index 9d68221fcd..86cad5684b 100644 --- a/src/analyses/region.ml +++ b/src/analyses/region.ml @@ -175,7 +175,7 @@ struct let startstate v = `Lifted (RegMap.bot ()) - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = [`Lifted (RegMap.bot ())] let threadspawn ctx lval f args fctx = ctx.local diff --git a/src/analyses/spec.ml b/src/analyses/spec.ml index e5434eb264..c44edd6c87 100644 --- a/src/analyses/spec.ml +++ b/src/analyses/spec.ml @@ -487,7 +487,7 @@ struct let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/stackTrace.ml b/src/analyses/stackTrace.ml index 3d70c50856..3c3bd56640 100644 --- a/src/analyses/stackTrace.ml +++ b/src/analyses/stackTrace.ml @@ -21,7 +21,7 @@ struct ctx.local (* keep local as opposed to IdentitySpec *) let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.top () end @@ -45,7 +45,7 @@ struct let startstate v = D.bot () let exitstate v = D.top () - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = [D.push !Tracing.current_loc ctx.local] end diff --git a/src/analyses/symbLocks.ml b/src/analyses/symbLocks.ml index b99ef93039..32be32f73d 100644 --- a/src/analyses/symbLocks.ml +++ b/src/analyses/symbLocks.ml @@ -29,7 +29,7 @@ struct let name () = "symb_locks" let startstate v = D.top () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/taintPartialContexts.ml b/src/analyses/taintPartialContexts.ml index 25e981dcbf..b45ea54877 100644 --- a/src/analyses/taintPartialContexts.ml +++ b/src/analyses/taintPartialContexts.ml @@ -101,7 +101,7 @@ struct d let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = match lval with diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 5e5e0d36f1..0563730fb2 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -217,7 +217,7 @@ struct (* | _ -> ctx.local *) let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let exitstate v = D.bot () end diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index 740cca3a53..ff4b4d5c63 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -85,7 +85,7 @@ struct let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = if multiple then (let tid = ThreadId.get_current_unlift (Analyses.ask_of_ctx ctx) in ctx.sideg tid (true, TS.bot (), false)); diff --git a/src/analyses/threadEscape.ml b/src/analyses/threadEscape.ml index 0674ebf3d1..0948a3976d 100644 --- a/src/analyses/threadEscape.ml +++ b/src/analyses/threadEscape.ml @@ -150,7 +150,7 @@ struct let startstate v = D.bot () let exitstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = diff --git a/src/analyses/threadFlag.ml b/src/analyses/threadFlag.ml index f3b132918a..81e05af679 100644 --- a/src/analyses/threadFlag.ml +++ b/src/analyses/threadFlag.ml @@ -58,7 +58,7 @@ struct let access ctx _ = is_currently_multi (Analyses.ask_of_ctx ctx) - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = if not (has_ever_been_multi (Analyses.ask_of_ctx ctx)) then ctx.emit Events.EnterMultiThreaded; [create_tid f] diff --git a/src/analyses/threadId.ml b/src/analyses/threadId.ml index f1de1dfdcb..a9f3fa35f7 100644 --- a/src/analyses/threadId.ml +++ b/src/analyses/threadId.ml @@ -133,7 +133,7 @@ struct | `Lifted node, count -> node, Some count | (`Bot | `Top), _ -> ctx.prev_node, None - let threadenter ?(multiple=false) ctx lval f args:D.t list = + let threadenter ctx ~multiple lval f args:D.t list = let n, i = indexed_node_for_ctx ctx in let+ tid = create_tid ~multiple ctx.local (n, i) f in (`Lifted (f, n, i), tid, (TD.bot (), TD.bot ())) diff --git a/src/analyses/threadReturn.ml b/src/analyses/threadReturn.ml index 176a4d3465..0aed06851a 100644 --- a/src/analyses/threadReturn.ml +++ b/src/analyses/threadReturn.ml @@ -28,7 +28,7 @@ struct ctx.local (* keep local as opposed to IdentitySpec *) let startstate v = true - let threadenter ?(multiple=false) ctx lval f args = [true] + let threadenter ctx ~multiple lval f args = [true] let exitstate v = D.top () let query (ctx: (D.t, _, _, _) ctx) (type a) (x: a Queries.t): a Queries.result = diff --git a/src/analyses/tmpSpecial.ml b/src/analyses/tmpSpecial.ml index f3d092e59e..046345e627 100644 --- a/src/analyses/tmpSpecial.ml +++ b/src/analyses/tmpSpecial.ml @@ -88,7 +88,7 @@ struct | _ -> Queries.Result.top q let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.bot ()] + let threadenter ctx ~multiple lval f args = [D.bot ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/tutorials/taint.ml b/src/analyses/tutorials/taint.ml index 166ce2c3f6..7fc3fd7343 100644 --- a/src/analyses/tutorials/taint.ml +++ b/src/analyses/tutorials/taint.ml @@ -129,7 +129,7 @@ struct (* You may leave these alone *) let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/tutorials/unitAnalysis.ml b/src/analyses/tutorials/unitAnalysis.ml index b5fb4d6367..3ecddc2bc0 100644 --- a/src/analyses/tutorials/unitAnalysis.ml +++ b/src/analyses/tutorials/unitAnalysis.ml @@ -39,7 +39,7 @@ struct ctx.local let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/uninit.ml b/src/analyses/uninit.ml index abdcd67aaa..2b388d1190 100644 --- a/src/analyses/uninit.ml +++ b/src/analyses/uninit.ml @@ -25,7 +25,7 @@ struct let name () = "uninit" let startstate v : D.t = D.empty () - let threadenter ?(multiple=false) ctx lval f args = [D.empty ()] + let threadenter ctx ~multiple lval f args = [D.empty ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v : D.t = D.empty () diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 6033c689e1..0c7a46c35f 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -196,7 +196,7 @@ struct end | _ -> state - let threadenter ?(multiple=false) ctx lval f args = [ctx.local] + let threadenter ctx ~multiple lval f args = [ctx.local] let threadspawn ctx lval f args fctx = ctx.local let startstate v = D.bot () diff --git a/src/analyses/varEq.ml b/src/analyses/varEq.ml index 7bd3453b8a..3aaef95265 100644 --- a/src/analyses/varEq.ml +++ b/src/analyses/varEq.ml @@ -43,7 +43,7 @@ struct let name () = "var_eq" let startstate v = D.top () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/vla.ml b/src/analyses/vla.ml index 8bd0168de0..665612aa99 100644 --- a/src/analyses/vla.ml +++ b/src/analyses/vla.ml @@ -33,7 +33,7 @@ struct ctx.local || Cilfacade.isVLAType v.vtype let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let exitstate v = D.top () end diff --git a/src/analyses/wrapperFunctionAnalysis.ml b/src/analyses/wrapperFunctionAnalysis.ml index 89242e044e..a1bec69a8c 100644 --- a/src/analyses/wrapperFunctionAnalysis.ml +++ b/src/analyses/wrapperFunctionAnalysis.ml @@ -87,7 +87,7 @@ struct let startstate v = D.bot () - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = (* The new thread receives a fresh counter *) [D.bot ()] diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 54a3a18f1a..3bb88a6ead 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -444,7 +444,7 @@ sig val paths_as_set : (D.t, G.t, C.t, V.t) ctx -> D.t list (** Returns initial state for created thread. *) - val threadenter : ?multiple:bool -> (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> D.t list + val threadenter : (D.t, G.t, C.t, V.t) ctx -> multiple:bool -> lval option -> varinfo -> exp list -> D.t list (** Updates the local state of the creator thread using initial state of created thread. *) val threadspawn : (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> (D.t, G.t, C.t, V.t) ctx -> D.t @@ -696,7 +696,7 @@ struct let special ctx (lval: lval option) (f:varinfo) (arglist:exp list) = ctx.local - let threadenter ?(multiple=false) ctx lval f args = [ctx.local] + let threadenter ctx ~multiple lval f args = [ctx.local] let threadspawn ctx lval f args fctx = ctx.local end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 62b8d46efa..ed492f4237 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -83,8 +83,8 @@ struct let combine_assign ctx r fe f args fc es f_ask = D.lift @@ S.combine_assign (conv ctx) r fe f args fc (D.unlift es) f_ask - let threadenter ?(multiple=false) ctx lval f args = - List.map D.lift @@ (S.threadenter ~multiple) (conv ctx) lval f args + let threadenter ctx ~multiple lval f args = + List.map D.lift @@ S.threadenter (conv ctx) ~multiple lval f args let threadspawn ctx lval f args fctx = D.lift @@ S.threadspawn (conv ctx) lval f args (conv fctx) @@ -167,8 +167,8 @@ struct let combine_assign ctx r fe f args fc es f_ask = S.combine_assign (conv ctx) r fe f args (Option.map C.unlift fc) es f_ask - let threadenter ?(multiple=false) ctx lval f args = - S.threadenter ~multiple (conv ctx) lval f args + let threadenter ctx ~multiple lval f args = + S.threadenter (conv ctx) ~multiple lval f args let threadspawn ctx lval f args fctx = S.threadspawn (conv ctx) lval f args (conv fctx) @@ -249,7 +249,7 @@ struct let combine_env' ctx r fe f args fc es f_ask = lift_fun ctx (lift ctx) S.combine_env (fun p -> p r fe f args fc (fst es) f_ask) let combine_assign' ctx r fe f args fc es f_ask = lift_fun ctx (lift ctx) S.combine_assign (fun p -> p r fe f args fc (fst es) f_ask) - let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (List.map lift_start_level) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) + let threadenter ctx ~multiple lval f args = lift_fun ctx (List.map lift_start_level) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) let threadspawn ctx lval f args fctx = lift_fun ctx (lift ctx) S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let leq0 = function @@ -394,7 +394,7 @@ struct let event ctx e octx = lift_fun ctx S.event ((|>) (conv octx) % (|>) e) - let threadenter ?(multiple=false) ctx lval f args = S.threadenter ~multiple (conv ctx) lval f args |> List.map (fun d -> (d, snd ctx.local)) + let threadenter ctx ~multiple lval f args = S.threadenter (conv ctx) ~multiple lval f args |> List.map (fun d -> (d, snd ctx.local)) let threadspawn ctx lval f args fctx = lift_fun ctx S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let enter ctx r f args = @@ -485,7 +485,7 @@ struct let combine_env ctx r fe f args fc es f_ask = lift_fun ctx D.lift S.combine_env (fun p -> p r fe f args fc (D.unlift es) f_ask) `Bot let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx D.lift S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) `Bot - let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (List.map D.lift) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) [] + let threadenter ctx ~multiple lval f args = lift_fun ctx (List.map D.lift) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) [] let threadspawn ctx lval f args fctx = lift_fun ctx D.lift S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) `Bot 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 @@ -1262,7 +1262,7 @@ struct let fd1 = D.choose octx.local in map ctx Spec.event (fun h -> h e (conv octx fd1)) - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = let g xs ys = (List.map (fun y -> D.singleton y) ys) @ xs in fold' ctx (Spec.threadenter ~multiple) (fun h -> h lval f args) g [] @@ -1449,7 +1449,7 @@ struct let combine_env ctx = S.combine_env (conv ctx) let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) - let threadenter ?(multiple=false) ctx = S.threadenter ~multiple (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) @@ -1685,7 +1685,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); S.D.bot () | _ -> S.special conv_ctx lv f args - let threadenter ?(multiple=false) ctx = S.threadenter ~multiple (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index 72890be4b4..3ec428014b 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -423,7 +423,7 @@ struct } in (* TODO: don't hd *) - List.hd (Spec.threadenter ctx None v []) + List.hd (Spec.threadenter ctx ~multiple:false None v []) (* TODO: do threadspawn to mainfuns? *) in let prestartstate = Spec.startstate MyCFG.dummy_func.svar in (* like in do_extern_inits *) diff --git a/src/util/wideningTokens.ml b/src/util/wideningTokens.ml index c88f3f00c1..73c160e3bb 100644 --- a/src/util/wideningTokens.ml +++ b/src/util/wideningTokens.ml @@ -179,7 +179,7 @@ struct let combine_env ctx r fe f args fc es f_ask = lift_fun ctx lift' S.combine_env (fun p -> p r fe f args fc (D.unlift es) f_ask) (* TODO: use tokens from es *) let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx lift' S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) (* TODO: use tokens from es *) - let threadenter ?(multiple=false) ctx lval f args = lift_fun ctx (fun l ts -> List.map (Fun.flip lift' ts) l) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval ) + let threadenter ctx ~multiple lval f args = lift_fun ctx (fun l ts -> List.map (Fun.flip lift' ts) l) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval ) let threadspawn ctx lval f args fctx = lift_fun ctx lift' S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let event ctx e octx = lift_fun ctx lift' S.event ((|>) (conv octx) % (|>) e) end diff --git a/src/witness/observerAnalysis.ml b/src/witness/observerAnalysis.ml index 3c702d199f..45a547c471 100644 --- a/src/witness/observerAnalysis.ml +++ b/src/witness/observerAnalysis.ml @@ -76,7 +76,7 @@ struct step_ctx ctx let startstate v = `Lifted Automaton.initial - let threadenter ?(multiple=false) ctx lval f args = [D.top ()] + let threadenter ctx ~multiple lval f args = [D.top ()] let threadspawn ctx lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/witness/witnessConstraints.ml b/src/witness/witnessConstraints.ml index ad32713fa8..1bf6294020 100644 --- a/src/witness/witnessConstraints.ml +++ b/src/witness/witnessConstraints.ml @@ -199,7 +199,7 @@ struct let r = Dom.bindings a in List.map (fun (x,v) -> (Dom.singleton x v, b)) r - let threadenter ?(multiple=false) ctx lval f args = + let threadenter ctx ~multiple lval f args = let g xs x' ys = let ys' = List.map (fun y -> let yr = step ctx.prev_node (ctx.context ()) x' (ThreadEntry (lval, f, args)) (nosync x') in (* threadenter called on before-sync state *) From c4bf1ccbeb23c2f8248fa755a8f4949efbe328e9 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 26 Sep 2023 15:16:51 +0300 Subject: [PATCH 293/628] Add some library functions for zstd --- src/analyses/libraryFunctions.ml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 137a3103a5..9ee9dc8c9d 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -209,6 +209,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("strnlen", unknown [drop "s" [r]; drop "maxlen" []]); ("chmod", unknown [drop "pathname" [r]; drop "mode" []]); ("fchmod", unknown [drop "fd" []; drop "mode" []]); + ("chown", unknown [drop "pathname" [r]; drop "owner" []; drop "group" []]); ("fchown", unknown [drop "fd" []; drop "owner" []; drop "group" []]); ("lchown", unknown [drop "pathname" [r]; drop "owner" []; drop "group" []]); ("clock_gettime", unknown [drop "clockid" []; drop "tp" [w]]); @@ -245,6 +246,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("timer_settime", unknown [drop "timerid" []; drop "flags" []; drop "new_value" [r_deep]; drop "old_value" [w_deep]]); ("timer_gettime", unknown [drop "timerid" []; drop "curr_value" [w_deep]]); ("timer_getoverrun", unknown [drop "timerid" []]); + ("fstat", unknown [drop "fd" []; drop "statbuf" [w]]); ("lstat", unknown [drop "pathname" [r]; drop "statbuf" [w]]); ("getpwnam", unknown [drop "name" [r]]); ("chdir", unknown [drop "path" [r]]); @@ -833,12 +835,23 @@ let zlib_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("inflateInit2", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []]); ("inflateInit2_", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []; drop "version" [r]; drop "stream_size" []]); ("inflateEnd", unknown [drop "strm" [f_deep]]); + ("deflate", unknown [drop "strm" [r_deep; w_deep]; drop "flush" []]); + ("deflateInit2", unknown [drop "strm" [r_deep; w_deep]; drop "level" []; drop "method" []; drop "windowBits" []; drop "memLevel" []; drop "strategy" []]); + ("deflateInit2_", unknown [drop "strm" [r_deep; w_deep]; drop "level" []; drop "method" []; drop "windowBits" []; drop "memLevel" []; drop "strategy" []; drop "version" [r]; drop "stream_size" []]); + ("deflateEnd", unknown [drop "strm" [f_deep]]); + ("zlibVersion", unknown []); ] let liblzma_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("lzma_code", unknown [drop "strm" [r_deep; w_deep]; drop "action" []]); ("lzma_auto_decoder", unknown [drop "strm" [r_deep; w_deep]; drop "memlimit" []; drop "flags" []]); + ("lzma_alone_decoder", unknown [drop "strm" [r_deep; w_deep]; drop "memlimit" []]); + ("lzma_stream_decoder", unknown [drop "strm" [r_deep; w_deep]; drop "memlimit" []; drop "flags" []]); + ("lzma_alone_encoder", unknown [drop "strm" [r_deep; w_deep]; drop "options" [r_deep]]); + ("lzma_easy_encoder", unknown [drop "strm" [r_deep; w_deep]; drop "preset" []; drop "check" []]); ("lzma_end", unknown [drop "strm" [r_deep; w_deep; f_deep]]); + ("lzma_version_string", unknown []); + ("lzma_lzma_preset", unknown [drop "options" [w_deep]; drop "preset" []]); ] let libraries = Hashtbl.of_list [ From 7ebddbc89f20e16927eafb6abafa3e79abde2fe8 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 28 Sep 2023 13:48:47 +0200 Subject: [PATCH 294/628] Also pass to threadspawn for history TID + uniqueness --- src/analyses/abortUnless.ml | 2 +- src/analyses/accessAnalysis.ml | 2 +- src/analyses/apron/relationAnalysis.apron.ml | 2 +- src/analyses/base.ml | 2 +- src/analyses/condVars.ml | 2 +- src/analyses/expsplit.ml | 2 +- src/analyses/extractPthread.ml | 2 +- src/analyses/fileUse.ml | 2 +- src/analyses/mCP.ml | 4 +- src/analyses/mallocFresh.ml | 2 +- src/analyses/malloc_null.ml | 2 +- src/analyses/mutexTypeAnalysis.ml | 2 +- src/analyses/region.ml | 2 +- src/analyses/spec.ml | 2 +- src/analyses/symbLocks.ml | 2 +- src/analyses/taintPartialContexts.ml | 2 +- src/analyses/threadAnalysis.ml | 2 +- src/analyses/threadEscape.ml | 2 +- src/analyses/threadFlag.ml | 2 +- src/analyses/threadId.ml | 8 +-- src/analyses/threadJoins.ml | 2 +- src/analyses/tmpSpecial.ml | 2 +- src/analyses/tutorials/taint.ml | 2 +- src/analyses/tutorials/unitAnalysis.ml | 2 +- src/analyses/uninit.ml | 2 +- src/analyses/useAfterFree.ml | 2 +- src/analyses/varEq.ml | 2 +- src/cdomains/threadIdDomain.ml | 55 ++++++++++---------- src/framework/analyses.ml | 4 +- src/framework/constraints.ml | 30 +++++------ src/util/wideningTokens.ml | 2 +- src/witness/observerAnalysis.ml | 2 +- src/witness/witnessConstraints.ml | 4 +- 33 files changed, 80 insertions(+), 79 deletions(-) diff --git a/src/analyses/abortUnless.ml b/src/analyses/abortUnless.ml index 5c24e61f7c..ee4db69820 100644 --- a/src/analyses/abortUnless.ml +++ b/src/analyses/abortUnless.ml @@ -66,7 +66,7 @@ struct let startstate v = false let threadenter ctx ~multiple lval f args = [false] - let threadspawn ctx lval f args fctx = false + let threadspawn ctx ~multiple lval f args fctx = false let exitstate v = false end diff --git a/src/analyses/accessAnalysis.ml b/src/analyses/accessAnalysis.ml index f0025c2f1c..b181a1c70e 100644 --- a/src/analyses/accessAnalysis.ml +++ b/src/analyses/accessAnalysis.ml @@ -121,7 +121,7 @@ struct ctx.local - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = (* must explicitly access thread ID lval because special to pthread_create doesn't if singlethreaded before *) begin match lval with | None -> () diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index c232ccae9b..13f549fc44 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -665,7 +665,7 @@ struct (* TODO: do something like base? *) failwith "relation.threadenter: unknown function" - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = ctx.local let event ctx e octx = diff --git a/src/analyses/base.ml b/src/analyses/base.ml index e824fac013..01646a54cf 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2513,7 +2513,7 @@ struct let st = special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) ctx.global st f args in [st] - let threadspawn ctx (lval: lval option) (f: varinfo) (args: exp list) fctx: D.t = + let threadspawn ctx ~multiple (lval: lval option) (f: varinfo) (args: exp list) fctx: D.t = begin match lval with | Some lval -> begin match ThreadId.get_current (Analyses.ask_of_ctx fctx) with diff --git a/src/analyses/condVars.ml b/src/analyses/condVars.ml index 820ff69efa..3b23dc03fc 100644 --- a/src/analyses/condVars.ml +++ b/src/analyses/condVars.ml @@ -156,7 +156,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/expsplit.ml b/src/analyses/expsplit.ml index 141a04283b..fef3d9ff9f 100644 --- a/src/analyses/expsplit.ml +++ b/src/analyses/expsplit.ml @@ -86,7 +86,7 @@ struct let threadenter ctx ~multiple lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = emit_splits_ctx ctx let event ctx (event: Events.t) octx = diff --git a/src/analyses/extractPthread.ml b/src/analyses/extractPthread.ml index f72f72c1fe..f084a21edb 100644 --- a/src/analyses/extractPthread.ml +++ b/src/analyses/extractPthread.ml @@ -1254,7 +1254,7 @@ module Spec : Analyses.MCPSpec = struct [ { f_d with pred = d.pred } ] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () diff --git a/src/analyses/fileUse.ml b/src/analyses/fileUse.ml index b8e7fd78f5..58257b7843 100644 --- a/src/analyses/fileUse.ml +++ b/src/analyses/fileUse.ml @@ -288,7 +288,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/mCP.ml b/src/analyses/mCP.ml index 5259bdb6c7..7a7e787ad7 100644 --- a/src/analyses/mCP.ml +++ b/src/analyses/mCP.ml @@ -578,7 +578,7 @@ struct (* TODO: this do_emits is now different from everything else *) map (fun d -> do_emits ctx !emits d false) @@ map topo_sort_an @@ n_cartesian_product css - let threadspawn (ctx:(D.t, G.t, C.t, V.t) ctx) lval f a fctx = + let threadspawn (ctx:(D.t, G.t, C.t, V.t) ctx) ~multiple lval f a fctx = let sides = ref [] in let emits = ref [] in let ctx'' = outer_ctx "threadspawn" ~sides ~emits ctx in @@ -586,7 +586,7 @@ struct let f post_all (n,(module S:MCPSpec),(d,fd)) = let ctx' : (S.D.t, S.G.t, S.C.t, S.V.t) ctx = inner_ctx "threadspawn" ~post_all ctx'' n d in let fctx' : (S.D.t, S.G.t, S.C.t, S.V.t) ctx = inner_ctx "threadspawn" ~post_all fctx'' n fd in - n, repr @@ S.threadspawn ctx' lval f a fctx' + n, repr @@ S.threadspawn ~multiple ctx' lval f a fctx' in let d, q = map_deadcode f @@ spec_list2 ctx.local fctx.local in do_sideg ctx !sides; diff --git a/src/analyses/mallocFresh.ml b/src/analyses/mallocFresh.ml index e171ad4ea1..b45573a801 100644 --- a/src/analyses/mallocFresh.ml +++ b/src/analyses/mallocFresh.ml @@ -55,7 +55,7 @@ struct let threadenter ctx ~multiple lval f args = [D.empty ()] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = D.empty () module A = diff --git a/src/analyses/malloc_null.ml b/src/analyses/malloc_null.ml index 41c251dfce..f993db0c6e 100644 --- a/src/analyses/malloc_null.ml +++ b/src/analyses/malloc_null.ml @@ -216,7 +216,7 @@ struct let startstate v = D.empty () let threadenter ctx ~multiple lval f args = [D.empty ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.empty () let init marshal = diff --git a/src/analyses/mutexTypeAnalysis.ml b/src/analyses/mutexTypeAnalysis.ml index 66e60aede1..e640a261cd 100644 --- a/src/analyses/mutexTypeAnalysis.ml +++ b/src/analyses/mutexTypeAnalysis.ml @@ -66,7 +66,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/analyses/region.ml b/src/analyses/region.ml index 86cad5684b..652526543c 100644 --- a/src/analyses/region.ml +++ b/src/analyses/region.ml @@ -177,7 +177,7 @@ struct let threadenter ctx ~multiple lval f args = [`Lifted (RegMap.bot ())] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = `Lifted (RegMap.bot ()) diff --git a/src/analyses/spec.ml b/src/analyses/spec.ml index c44edd6c87..2f754f6160 100644 --- a/src/analyses/spec.ml +++ b/src/analyses/spec.ml @@ -488,7 +488,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/symbLocks.ml b/src/analyses/symbLocks.ml index 32be32f73d..f6fdd96c2e 100644 --- a/src/analyses/symbLocks.ml +++ b/src/analyses/symbLocks.ml @@ -30,7 +30,7 @@ struct let startstate v = D.top () let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () let branch ctx exp tv = ctx.local diff --git a/src/analyses/taintPartialContexts.ml b/src/analyses/taintPartialContexts.ml index b45ea54877..88cf532ab2 100644 --- a/src/analyses/taintPartialContexts.ml +++ b/src/analyses/taintPartialContexts.ml @@ -103,7 +103,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = match lval with | Some lv -> taint_lval ctx lv | None -> ctx.local diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index ff4b4d5c63..f51e9395db 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -91,7 +91,7 @@ struct ctx.sideg tid (true, TS.bot (), false)); [D.bot ()] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = let creator = ThreadId.get_current (Analyses.ask_of_ctx ctx) in let tid = ThreadId.get_current_unlift (Analyses.ask_of_ctx fctx) in let repeated = D.mem tid ctx.local in diff --git a/src/analyses/threadEscape.ml b/src/analyses/threadEscape.ml index 0948a3976d..21a8b69c93 100644 --- a/src/analyses/threadEscape.ml +++ b/src/analyses/threadEscape.ml @@ -153,7 +153,7 @@ struct let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = D.join ctx.local @@ match args with | [ptc_arg] -> diff --git a/src/analyses/threadFlag.ml b/src/analyses/threadFlag.ml index 81e05af679..6bd466caef 100644 --- a/src/analyses/threadFlag.ml +++ b/src/analyses/threadFlag.ml @@ -63,7 +63,7 @@ struct ctx.emit Events.EnterMultiThreaded; [create_tid f] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = if not (has_ever_been_multi (Analyses.ask_of_ctx ctx)) then ctx.emit Events.EnterMultiThreaded; D.join ctx.local (Flag.get_main ()) diff --git a/src/analyses/threadId.ml b/src/analyses/threadId.ml index a9f3fa35f7..900870a676 100644 --- a/src/analyses/threadId.ml +++ b/src/analyses/threadId.ml @@ -58,8 +58,8 @@ struct let create_tid ?(multiple=false) (_, current, (td, _)) ((node, index): Node.t * int option) v = match current with - | `Lifted current when not multiple -> - let+ tid = Thread.threadenter (current, td) node index v in + | `Lifted current -> + let+ tid = Thread.threadenter ~multiple (current, td) node index v in if GobConfig.get_bool "dbg.print_tids" then Hashtbl.replace !tids tid (); `Lifted tid @@ -138,10 +138,10 @@ struct let+ tid = create_tid ~multiple ctx.local (n, i) f in (`Lifted (f, n, i), tid, (TD.bot (), TD.bot ())) - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = let (current_n, current, (td,tdl)) = ctx.local in let v, n, i = match fctx.local with `Lifted vni, _, _ -> vni | _ -> failwith "ThreadId.threadspawn" in - (current_n, current, (Thread.threadspawn td n i v, Thread.threadspawn tdl n i v)) + (current_n, current, (Thread.threadspawn ~multiple td n i v, Thread.threadspawn ~multiple tdl n i v)) type marshal = (Thread.t,unit) Hashtbl.t (* TODO: don't use polymorphic Hashtbl *) let init (m:marshal option): unit = diff --git a/src/analyses/threadJoins.ml b/src/analyses/threadJoins.ml index f2cd36619f..862711073c 100644 --- a/src/analyses/threadJoins.ml +++ b/src/analyses/threadJoins.ml @@ -81,7 +81,7 @@ struct ) | _, _ -> ctx.local - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = if D.is_bot ctx.local then ( (* bot is All threads *) M.info ~category:Imprecise "Thread created while ALL threads must-joined, continuing with no threads joined."; D.top () (* top is no threads *) diff --git a/src/analyses/tmpSpecial.ml b/src/analyses/tmpSpecial.ml index 046345e627..9ed6da7c60 100644 --- a/src/analyses/tmpSpecial.ml +++ b/src/analyses/tmpSpecial.ml @@ -89,7 +89,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.bot ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.bot () end diff --git a/src/analyses/tutorials/taint.ml b/src/analyses/tutorials/taint.ml index 7fc3fd7343..a978d0faf4 100644 --- a/src/analyses/tutorials/taint.ml +++ b/src/analyses/tutorials/taint.ml @@ -130,7 +130,7 @@ struct (* You may leave these alone *) let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/tutorials/unitAnalysis.ml b/src/analyses/tutorials/unitAnalysis.ml index 3ecddc2bc0..dc377cdd97 100644 --- a/src/analyses/tutorials/unitAnalysis.ml +++ b/src/analyses/tutorials/unitAnalysis.ml @@ -40,7 +40,7 @@ struct let startstate v = D.bot () let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/analyses/uninit.ml b/src/analyses/uninit.ml index 2b388d1190..8693599a4d 100644 --- a/src/analyses/uninit.ml +++ b/src/analyses/uninit.ml @@ -26,7 +26,7 @@ struct let startstate v : D.t = D.empty () let threadenter ctx ~multiple lval f args = [D.empty ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v : D.t = D.empty () let access_address (ask: Queries.ask) write lv = diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 0c7a46c35f..683ddbdcc2 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -197,7 +197,7 @@ struct | _ -> state let threadenter ctx ~multiple lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let startstate v = D.bot () let exitstate v = D.top () diff --git a/src/analyses/varEq.ml b/src/analyses/varEq.ml index 3aaef95265..3f5a65516f 100644 --- a/src/analyses/varEq.ml +++ b/src/analyses/varEq.ml @@ -44,7 +44,7 @@ struct let startstate v = D.top () let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () let typ_equal = CilType.Typ.equal (* TODO: Used to have equality checking, which ignores attributes. Is that needed? *) diff --git a/src/cdomains/threadIdDomain.ml b/src/cdomains/threadIdDomain.ml index 7193552048..a9646cffd2 100644 --- a/src/cdomains/threadIdDomain.ml +++ b/src/cdomains/threadIdDomain.ml @@ -23,7 +23,7 @@ module type Stateless = sig include S - val threadenter: Node.t -> int option -> varinfo -> t + val threadenter: multiple:bool -> Node.t -> int option -> varinfo -> t end module type Stateful = @@ -32,8 +32,8 @@ sig module D: Lattice.S - val threadenter: t * D.t -> Node.t -> int option -> varinfo -> t list - val threadspawn: D.t -> Node.t -> int option -> varinfo -> D.t + val threadenter: multiple:bool -> t * D.t -> Node.t -> int option -> varinfo -> t list + val threadspawn: multiple:bool -> D.t -> Node.t -> int option -> varinfo -> D.t (** If it is possible to get a list of threads created thus far, get it *) val created: t -> D.t -> (t list) option @@ -71,9 +71,10 @@ struct let threadinit v ~multiple: t = (v, None) - let threadenter l i v: t = + let threadenter ~multiple l i v: t = if GobConfig.get_bool "ana.thread.include-node" then - (v, Some (l, i)) + let counter = Option.map (fun x -> if multiple then WrapperFunctionAnalysis0.ThreadCreateUniqueCount.top () else x) i in + (v, Some (l, counter)) else (v, None) @@ -93,8 +94,8 @@ struct module D = Lattice.Unit - let threadenter _ n i v = [threadenter n i v] - let threadspawn () _ _ _ = () + let threadenter ~multiple _ n i v = [threadenter ~multiple n i v] + let threadspawn ~multiple () _ _ _ = () let created _ _ = None end @@ -162,10 +163,10 @@ struct else ([base_tid], S.empty ()) - let threadenter ((p, _ ) as current, (cs,_)) (n: Node.t) i v = - let ni = Base.threadenter n i v in + let threadenter ~multiple ((p, _ ) as current, (cs,_)) (n: Node.t) i v = + let ni = Base.threadenter ~multiple n i v in let ((p', s') as composed) = compose current ni in - if is_unique composed && S.mem ni cs then + if is_unique composed && (S.mem ni cs || multiple) then [(p, S.singleton ni); composed] (* also respawn unique version of the thread to keep it reachable while thread ID sets refer to it *) else [composed] @@ -182,12 +183,12 @@ struct in Some (List.concat_map map_one els) - let threadspawn (cs,cms) l i v = - let e = Base.threadenter l i v in + let threadspawn ~multiple (cs,cms) l i v = + let e = Base.threadenter ~multiple l i v in if S.mem e cs then (cs, S.add e cms) else - (S.add e cs, cms) + (S.add e cs, if multiple then S.add e cms else cms) let is_main = function | ([fl], s) when S.is_empty s && Base.is_main fl -> true @@ -257,24 +258,24 @@ struct | (None, Some x'), `Top -> liftp x' (P.D.top ()) | _ -> None - let threadenter x n i v = + let threadenter ~multiple x n i v = match x with - | ((Some x', None), `Lifted1 d) -> H.threadenter (x',d) n i v |> List.map (fun t -> (Some t, None)) - | ((Some x', None), `Bot) -> H.threadenter (x',H.D.bot ()) n i v |> List.map (fun t -> (Some t, None)) - | ((Some x', None), `Top) -> H.threadenter (x',H.D.top ()) n i v |> List.map (fun t -> (Some t, None)) - | ((None, Some x'), `Lifted2 d) -> P.threadenter (x',d) n i v |> List.map (fun t -> (None, Some t)) - | ((None, Some x'), `Bot) -> P.threadenter (x',P.D.bot ()) n i v |> List.map (fun t -> (None, Some t)) - | ((None, Some x'), `Top) -> P.threadenter (x',P.D.top ()) n i v |> List.map (fun t -> (None, Some t)) + | ((Some x', None), `Lifted1 d) -> H.threadenter ~multiple (x',d) n i v |> List.map (fun t -> (Some t, None)) + | ((Some x', None), `Bot) -> H.threadenter ~multiple (x',H.D.bot ()) n i v |> List.map (fun t -> (Some t, None)) + | ((Some x', None), `Top) -> H.threadenter ~multiple (x',H.D.top ()) n i v |> List.map (fun t -> (Some t, None)) + | ((None, Some x'), `Lifted2 d) -> P.threadenter ~multiple (x',d) n i v |> List.map (fun t -> (None, Some t)) + | ((None, Some x'), `Bot) -> P.threadenter ~multiple (x',P.D.bot ()) n i v |> List.map (fun t -> (None, Some t)) + | ((None, Some x'), `Top) -> P.threadenter ~multiple (x',P.D.top ()) n i v |> List.map (fun t -> (None, Some t)) | _ -> failwith "FlagConfiguredTID received a value where not exactly one component is set" - let threadspawn x n i v = + let threadspawn ~multiple x n i v = match x with - | `Lifted1 x' -> `Lifted1 (H.threadspawn x' n i v) - | `Lifted2 x' -> `Lifted2 (P.threadspawn x' n i v) - | `Bot when history_enabled () -> `Lifted1 (H.threadspawn (H.D.bot ()) n i v) - | `Bot -> `Lifted2 (P.threadspawn (P.D.bot ()) n i v) - | `Top when history_enabled () -> `Lifted1 (H.threadspawn (H.D.top ()) n i v) - | `Top -> `Lifted2 (P.threadspawn (P.D.top ()) n i v) + | `Lifted1 x' -> `Lifted1 (H.threadspawn ~multiple x' n i v) + | `Lifted2 x' -> `Lifted2 (P.threadspawn ~multiple x' n i v) + | `Bot when history_enabled () -> `Lifted1 (H.threadspawn ~multiple (H.D.bot ()) n i v) + | `Bot -> `Lifted2 (P.threadspawn ~multiple (P.D.bot ()) n i v) + | `Top when history_enabled () -> `Lifted1 (H.threadspawn ~multiple (H.D.top ()) n i v) + | `Top -> `Lifted2 (P.threadspawn ~multiple (P.D.top ()) n i v) let name () = "FlagConfiguredTID: " ^ if history_enabled () then H.name () else P.name () end diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 3bb88a6ead..e1a4560003 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -447,7 +447,7 @@ sig val threadenter : (D.t, G.t, C.t, V.t) ctx -> multiple:bool -> lval option -> varinfo -> exp list -> D.t list (** Updates the local state of the creator thread using initial state of created thread. *) - val threadspawn : (D.t, G.t, C.t, V.t) ctx -> lval option -> varinfo -> exp list -> (D.t, G.t, C.t, V.t) ctx -> D.t + val threadspawn : (D.t, G.t, C.t, V.t) ctx -> multiple:bool -> lval option -> varinfo -> exp list -> (D.t, G.t, C.t, V.t) ctx -> D.t val event : (D.t, G.t, C.t, V.t) ctx -> Events.t -> (D.t, G.t, C.t, V.t) ctx -> D.t end @@ -697,7 +697,7 @@ struct ctx.local let threadenter ctx ~multiple lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ed492f4237..f474df6834 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -86,8 +86,8 @@ struct let threadenter ctx ~multiple lval f args = List.map D.lift @@ S.threadenter (conv ctx) ~multiple lval f args - let threadspawn ctx lval f args fctx = - D.lift @@ S.threadspawn (conv ctx) lval f args (conv fctx) + let threadspawn ctx ~multiple lval f args fctx = + D.lift @@ S.threadspawn (conv ctx) ~multiple lval f args (conv fctx) let paths_as_set ctx = List.map (fun x -> D.lift x) @@ S.paths_as_set (conv ctx) @@ -170,8 +170,8 @@ struct let threadenter ctx ~multiple lval f args = S.threadenter (conv ctx) ~multiple lval f args - let threadspawn ctx lval f args fctx = - S.threadspawn (conv ctx) lval f args (conv fctx) + let threadspawn ctx ~multiple lval f args fctx = + S.threadspawn (conv ctx) ~multiple lval f args (conv fctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let event ctx e octx = S.event (conv ctx) e (conv octx) @@ -250,7 +250,7 @@ struct let combine_assign' ctx r fe f args fc es f_ask = lift_fun ctx (lift ctx) S.combine_assign (fun p -> p r fe f args fc (fst es) f_ask) let threadenter ctx ~multiple lval f args = lift_fun ctx (List.map lift_start_level) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) - let threadspawn ctx lval f args fctx = lift_fun ctx (lift ctx) S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) + let threadspawn ctx ~multiple lval f args fctx = lift_fun ctx (lift ctx) (S.threadspawn ~multiple) ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let leq0 = function | `Top -> false @@ -395,7 +395,7 @@ struct let event ctx e octx = lift_fun ctx S.event ((|>) (conv octx) % (|>) e) let threadenter ctx ~multiple lval f args = S.threadenter (conv ctx) ~multiple lval f args |> List.map (fun d -> (d, snd ctx.local)) - let threadspawn ctx lval f args fctx = lift_fun ctx S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) + let threadspawn ctx ~multiple lval f args fctx = lift_fun ctx (S.threadspawn ~multiple) ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let enter ctx r f args = let m = snd ctx.local in @@ -486,7 +486,7 @@ struct let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx D.lift S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) `Bot let threadenter ctx ~multiple lval f args = lift_fun ctx (List.map D.lift) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval) [] - let threadspawn ctx lval f args fctx = lift_fun ctx D.lift S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) `Bot + let threadspawn ctx ~multiple lval f args fctx = lift_fun ctx D.lift (S.threadspawn ~multiple) ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) `Bot 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 @@ -563,7 +563,7 @@ struct if !AnalysisState.postsolving then sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c)) - let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t) list ref = + let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t * bool) list ref = let r = ref [] in let spawns = ref [] in (* now watch this ... *) @@ -586,7 +586,7 @@ struct (* TODO: don't repeat for all paths that spawn same *) let ds = S.threadenter ~multiple ctx lval f args in List.iter (fun d -> - spawns := (lval, f, args, d) :: !spawns; + spawns := (lval, f, args, d, multiple) :: !spawns; match Cilfacade.find_varinfo_fundec f with | fd -> let c = S.context fd d in @@ -618,14 +618,14 @@ struct } in (* TODO: don't forget path dependencies *) - let one_spawn (lval, f, args, fd) = + let one_spawn (lval, f, args, fd, multiple) = let rec fctx = { ctx with ask = (fun (type a) (q: a Queries.t) -> S.query fctx q) ; local = fd } in - S.threadspawn ctx' lval f args fctx + S.threadspawn ctx' ~multiple lval f args fctx in bigsqcup (List.map one_spawn spawns) @@ -1266,9 +1266,9 @@ struct let g xs ys = (List.map (fun y -> D.singleton y) ys) @ xs in fold' ctx (Spec.threadenter ~multiple) (fun h -> h lval f args) g [] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = let fd1 = D.choose fctx.local in - map ctx Spec.threadspawn (fun h -> h lval f args (conv fctx fd1)) + map ctx (Spec.threadspawn ~multiple) (fun h -> h lval f args (conv fctx fd1)) let sync ctx reason = map ctx Spec.sync (fun h -> h reason) @@ -1450,7 +1450,7 @@ struct let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let threadspawn ctx ~multiple lv f args fctx = S.threadspawn (conv ctx) ~multiple lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) let asm ctx = S.asm (conv ctx) @@ -1686,7 +1686,7 @@ struct S.D.bot () | _ -> S.special conv_ctx lv f args let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let threadspawn ctx ~multiple lv f args fctx = S.threadspawn (conv ctx) ~multiple lv f args (conv fctx) let sync ctx = S.sync (conv ctx) let skip ctx = S.skip (conv ctx) let asm ctx = S.asm (conv ctx) diff --git a/src/util/wideningTokens.ml b/src/util/wideningTokens.ml index 73c160e3bb..1816de90c7 100644 --- a/src/util/wideningTokens.ml +++ b/src/util/wideningTokens.ml @@ -180,6 +180,6 @@ struct let combine_assign ctx r fe f args fc es f_ask = lift_fun ctx lift' S.combine_assign (fun p -> p r fe f args fc (D.unlift es) f_ask) (* TODO: use tokens from es *) let threadenter ctx ~multiple lval f args = lift_fun ctx (fun l ts -> List.map (Fun.flip lift' ts) l) (S.threadenter ~multiple) ((|>) args % (|>) f % (|>) lval ) - let threadspawn ctx lval f args fctx = lift_fun ctx lift' S.threadspawn ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) + let threadspawn ctx ~multiple lval f args fctx = lift_fun ctx lift' (S.threadspawn ~multiple) ((|>) (conv fctx) % (|>) args % (|>) f % (|>) lval) let event ctx e octx = lift_fun ctx lift' S.event ((|>) (conv octx) % (|>) e) end diff --git a/src/witness/observerAnalysis.ml b/src/witness/observerAnalysis.ml index 45a547c471..e8daf56155 100644 --- a/src/witness/observerAnalysis.ml +++ b/src/witness/observerAnalysis.ml @@ -77,7 +77,7 @@ struct let startstate v = `Lifted Automaton.initial let threadenter ctx ~multiple lval f args = [D.top ()] - let threadspawn ctx lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = ctx.local let exitstate v = D.top () end diff --git a/src/witness/witnessConstraints.ml b/src/witness/witnessConstraints.ml index 1bf6294020..8dedf77a79 100644 --- a/src/witness/witnessConstraints.ml +++ b/src/witness/witnessConstraints.ml @@ -209,9 +209,9 @@ struct ys' @ xs in fold' ctx (Spec.threadenter ~multiple) (fun h -> h lval f args) g [] - let threadspawn ctx lval f args fctx = + let threadspawn ctx ~multiple lval f args fctx = let fd1 = Dom.choose_key (fst fctx.local) in - map ctx Spec.threadspawn (fun h -> h lval f args (conv fctx fd1)) + map ctx (Spec.threadspawn ~multiple) (fun h -> h lval f args (conv fctx fd1)) let sync ctx reason = fold'' ctx Spec.sync (fun h -> h reason) (fun (a, async) x r a' -> From 44ef0843efac4839f45f267f015ace6a27a88414 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 28 Sep 2023 13:54:36 +0200 Subject: [PATCH 295/628] Add example for race despite uniqueness counter --- .../40-threadid/11-multiple-unique-counter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/regression/40-threadid/11-multiple-unique-counter.c diff --git a/tests/regression/40-threadid/11-multiple-unique-counter.c b/tests/regression/40-threadid/11-multiple-unique-counter.c new file mode 100644 index 0000000000..37c08ae61a --- /dev/null +++ b/tests/regression/40-threadid/11-multiple-unique-counter.c @@ -0,0 +1,16 @@ +// PARAM: --set ana.thread.unique_thread_id_count 4 +#include +#include + +int myglobal; + +void *t_fun(void *arg) { + myglobal=40; //RACE + return NULL; +} + +int main(void) { + // This should spawn a non-unique thread + unknown(t_fun); + return 0; +} From b718e46241c0c4f9b926620060a8743c3c49b6d7 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 28 Sep 2023 14:04:49 +0200 Subject: [PATCH 296/628] Add check that only one mainfun is specified to privatizations --- src/analyses/basePriv.ml | 2 +- src/analyses/commonPriv.ml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/analyses/basePriv.ml b/src/analyses/basePriv.ml index 0154924a1c..3843dda300 100644 --- a/src/analyses/basePriv.ml +++ b/src/analyses/basePriv.ml @@ -893,7 +893,7 @@ end module MinePrivBase = struct include NoFinalize - include ConfCheck.RequireMutexPathSensInit + include ConfCheck.RequireMutexPathSensOneMainInit include MutexGlobals (* explicit not needed here because G is Prod anyway? *) let thread_join ?(force=false) ask get e st = st diff --git a/src/analyses/commonPriv.ml b/src/analyses/commonPriv.ml index 1b92cb320d..38a8dfe1b7 100644 --- a/src/analyses/commonPriv.ml +++ b/src/analyses/commonPriv.ml @@ -19,12 +19,14 @@ struct if not mutex_active then failwith "Privatization (to be useful) requires the 'mutex' analysis to be enabled (it is currently disabled)" end - module RequireMutexPathSensInit = + module RequireMutexPathSensOneMainInit = struct let init () = RequireMutexActivatedInit.init (); let mutex_path_sens = List.mem "mutex" (GobConfig.get_string_list "ana.path_sens") in if not mutex_path_sens then failwith "The activated privatization requires the 'mutex' analysis to be enabled & path sensitive (it is currently enabled, but not path sensitive)"; + let mainfuns = List.length @@ GobConfig.get_list "mainfun" in + if not (mainfuns = 1) then failwith "The activated privatization requires exactly one main function to be specified"; () end From dee2a60ba7855321f2d67513ca97be8cdbe3320d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 01:02:38 +0200 Subject: [PATCH 297/628] Set SV-COMP memory safety global flags at all necessary locations --- src/analyses/base.ml | 10 +++++--- src/analyses/memLeak.ml | 4 ++-- src/analyses/memOutOfBounds.ml | 42 +++++++++++++++++----------------- src/analyses/useAfterFree.ml | 6 +++-- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index d9cfba7b18..a624fd0b40 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2027,12 +2027,16 @@ struct in match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with | Address a -> - if AD.is_top a then + if AD.is_top a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname - else if has_non_heap_var a then + ) else if has_non_heap_var a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr - else if has_non_zero_offset a then + ) else if has_non_zero_offset a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr + ) | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 56cbbbff3d..eb38b97a1c 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -30,10 +30,10 @@ struct if not @@ D.is_empty state then match assert_exp_imprecise, exp with | true, Some exp -> - AnalysisStateUtil.set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemTrack; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state | _ -> - AnalysisStateUtil.set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemTrack; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 9ee022fe08..db86a63414 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -118,6 +118,7 @@ struct | x::xs -> List.fold_left VDQ.ID.join x xs end | _ -> + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; `Top @@ -172,7 +173,7 @@ struct | _ -> true in if may_contain_unknown_addr then begin - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior (Undefined Other)) "Pointer %a contains an unknown address. Invalid dereference may occur" d_exp ptr end @@ -201,15 +202,13 @@ struct | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a bot address offset. An invalid memory access may occur" d_exp ptr ) else if VDQ.AD.exists (function | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a top address offset. An invalid memory access may occur" d_exp ptr ); (* Offset should be the same for all elements in the points-to set *) @@ -224,7 +223,7 @@ struct ID.top_of @@ Cilfacade.ptrdiff_ikind () end | _ -> - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; ID.top_of @@ Cilfacade.ptrdiff_ikind () @@ -259,10 +258,10 @@ struct | Some t -> begin match ptr_size, addr_offs with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is top. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is bot. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Lifted ps, ao -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -270,11 +269,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_ao in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer is %a (in bytes). It is offset by %a (in bytes) due to pointer arithmetic. Memory out-of-bounds access must occur" ID.pretty casted_ps ID.pretty casted_ao | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of pointer (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_ps ID.pretty casted_ao end end @@ -334,16 +333,16 @@ struct in begin match ptr_size, offset_size_with_addr_size with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is top. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Top -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is top. Memory out-of-bounds access might occur" d_exp binopexp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is bottom. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Bot -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is bottom. Memory out-of-bounds access might occur" d_exp binopexp | `Lifted ps, `Lifted o -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -351,11 +350,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_o in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer in expression %a is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" d_exp binopexp ID.pretty casted_ps ID.pretty casted_o | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare pointer size (%a) with offset (%a). Memory out-of-bounds access may occur" ID.pretty casted_ps ID.pretty casted_o end end @@ -372,15 +371,16 @@ struct let addr_offs = get_addr_offs ctx dest in match dest_size, eval_n with | `Top, _ -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp dest fun_name | _, `Top -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is unknown. Memory out-of-bounds access might occur" fun_name | `Bot, _ -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp dest fun_name | _, `Bot -> + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is bottom" fun_name | `Lifted ds, `Lifted en -> let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in @@ -389,11 +389,11 @@ struct let dest_size_lt_count = ID.lt casted_ds (ID.add casted_en casted_ao) in begin match ID.to_bool dest_size_lt_count with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of dest (%a) with address offset (%a) count (%a) in function %s. Memory out-of-bounds access may occur" ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en fun_name end diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index dfbab87a29..2f4b54f000 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -76,7 +76,7 @@ struct M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Current thread is not unique and a %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var end else if HeapVars.mem heap_var (snd ctx.local) then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "%s might occur in current unique thread %a for heap variable %a" bug_name ThreadIdDomain.FlagConfiguredTID.pretty current CilType.Varinfo.pretty heap_var end end @@ -110,8 +110,10 @@ struct begin match ctx.ask (Queries.MayPointTo lval_to_query) with | ad when not (Queries.AD.is_top ad) -> let warn_for_heap_var v = - if HeapVars.mem v (snd state) then + if HeapVars.mem v (snd state) then begin + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior undefined_behavior) ~tags:[CWE cwe_number] "lval (%s) in \"%s\" points to a maybe freed memory region" v.vname transfer_fn_name + end in let pointed_to_heap_vars = Queries.AD.fold (fun addr vars -> From da45e40b56d3a049656cfb2993b462e6b797c5ac Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 01:05:18 +0200 Subject: [PATCH 298/628] Clean up UAF analysis a bit --- src/analyses/useAfterFree.ml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 2f4b54f000..a28591e273 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -15,7 +15,7 @@ module ThreadIdToJoinedThreadsMap = MapDomain.MapBot(ThreadIdDomain.ThreadLifted module Spec : Analyses.MCPSpec = struct - include Analyses.DefaultSpec + include Analyses.IdentitySpec let name () = "useAfterFree" @@ -24,7 +24,6 @@ struct module G = ThreadIdToJoinedThreadsMap module V = VarinfoV - (** TODO: Try out later in benchmarks to see how we perform with and without context-sensititivty *) let context _ _ = () @@ -176,9 +175,6 @@ struct warn_exp_might_contain_freed "branch" ctx exp; ctx.local - let body ctx (f:fundec) : D.t = - ctx.local - let return ctx (exp:exp option) (f:fundec) : D.t = Option.iter (fun x -> warn_exp_might_contain_freed "return" ctx x) exp; ctx.local @@ -248,9 +244,6 @@ struct end | _ -> state - let threadenter ctx lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = ctx.local - let startstate v = D.bot () let exitstate v = D.top () From 1335123d60b556e9759a4e4147d72095142a9452 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 09:45:49 +0200 Subject: [PATCH 299/628] Recognize mem-safety props in any order --- src/witness/svcompSpec.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index f066610953..fbe206dabb 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -32,7 +32,8 @@ let of_string s = let global1 = Str.matched_group 1 s in let global2 = Str.matched_group 2 s in let global3 = Str.matched_group 3 s in - if global1 = "valid-free" && global2 = "valid-deref" && global3 = "valid-memtrack" then + let mem_safety_props = ["valid-free"; "valid-deref"; "valid-memtrack";] in + if (global1 <> global2 && global1 <> global3 && global2 <> global3) && List.for_all (fun x -> List.mem x mem_safety_props) [global1; global2; global3] then MemorySafety (* if global = "valid-free" then ValidFree From 1384f733d812996399648b4a846389fcbac29afb Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 09:57:38 +0200 Subject: [PATCH 300/628] Add support for SV-COMP's valid-memcleanup property --- src/autoTune.ml | 1 + src/framework/analysisState.ml | 3 +++ src/util/analysisStateUtil.ml | 4 +++- src/witness/svcomp.ml | 1 + src/witness/svcompSpec.ml | 13 +++++++++++-- src/witness/witness.ml | 30 ++++++++++++++++++++++++++++++ 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 9e3508ccd2..ac7c150546 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -227,6 +227,7 @@ let focusOnSpecification () = | ValidDeref | ValidMemtrack -> () | MemorySafety -> () (* TODO: This is here for now just to complete the pattern match *) + | ValidMemcleanup -> () (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index ca619d4dfb..1416f99f69 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -16,6 +16,9 @@ let svcomp_may_invalid_deref = ref false (** Whether an invalid memtrack happened *) let svcomp_may_invalid_memtrack = ref false +(** Whether an invalid memcleanup happened *) +let svcomp_may_invalid_memcleanup = ref false + (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/util/analysisStateUtil.ml b/src/util/analysisStateUtil.ml index 25914f8c8e..a34be33f18 100644 --- a/src/util/analysisStateUtil.ml +++ b/src/util/analysisStateUtil.ml @@ -2,10 +2,12 @@ type mem_safety_violation = | InvalidFree | InvalidDeref | InvalidMemTrack + | InvalidMemcleanup let set_mem_safety_flag violation_type = if !AnalysisState.postsolving then match violation_type with | InvalidFree -> AnalysisState.svcomp_may_invalid_free := true | InvalidDeref -> AnalysisState.svcomp_may_invalid_deref := true - | InvalidMemTrack -> AnalysisState.svcomp_may_invalid_memtrack := true \ No newline at end of file + | InvalidMemTrack -> AnalysisState.svcomp_may_invalid_memtrack := true + | InvalidMemcleanup -> AnalysisState.svcomp_may_invalid_memcleanup := true \ No newline at end of file diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 15d41c0210..22543d48a9 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -56,6 +56,7 @@ struct | ValidDeref -> "valid-deref" | ValidMemtrack -> "valid-memtrack" | MemorySafety -> "memory-safety" (* TODO: Currently here only to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index fbe206dabb..25a9f522bc 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -10,10 +10,12 @@ type t = | ValidDeref | ValidMemtrack | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) + | ValidMemcleanup let of_string s = let s = String.strip s in - let regexp = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in @@ -28,7 +30,7 @@ let of_string s = UnreachCall f else failwith "Svcomp.Specification.of_string: unknown global not expression" - else if Str.string_match regexp s 0 then + else if Str.string_match regexp_multiple s 0 then let global1 = Str.matched_group 1 s in let global2 = Str.matched_group 2 s in let global3 = Str.matched_group 3 s in @@ -43,6 +45,12 @@ let of_string s = ValidMemtrack *) else failwith "Svcomp.Specification.of_string: unknown global expression" + else if Str.string_match regexp_single s 0 then + let global = Str.matched_group 1 s in + if global = "valid-memcleanup" then + ValidMemcleanup + else + failwith "Svcomp.Specification.of_string: unknown global expression" else failwith "Svcomp.Specification.of_string: unknown expression" @@ -72,5 +80,6 @@ let to_string spec = | ValidDeref -> "valid-deref", false | ValidMemtrack -> "valid-memtrack", false | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup", false in print_output spec_str is_neg diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 17dd14472e..35d932210d 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -625,6 +625,36 @@ struct in (module TaskResult:WitnessTaskResult) ) + | ValidMemcleanup -> + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + if not !AnalysisState.svcomp_may_invalid_memcleanup then ( + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) let write entrystates = From 4e70422c2c305de6408ef68177dddb1f3c9e9833 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 09:59:08 +0200 Subject: [PATCH 301/628] Set SV-COMP global flag for invalid-memcleanup --- src/analyses/memLeak.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index eb38b97a1c..dbaa2d69fc 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -22,6 +22,7 @@ struct let warn_for_multi_threaded ctx = if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" ) @@ -31,9 +32,11 @@ struct match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state | _ -> set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) From 00cc9b541ae6e6270906c16cbba94498692ab6f3 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 10:58:45 +0200 Subject: [PATCH 302/628] Enable memory safety analyses in autoTune --- src/autoTune.ml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index ac7c150546..f73a71ed40 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -223,11 +223,18 @@ let focusOnSpecification () = let uafAna = ["useAfterFree"] in print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; enableAnalyses uafAna - (* TODO: Finish these two below later *) - | ValidDeref - | ValidMemtrack -> () - | MemorySafety -> () (* TODO: This is here for now just to complete the pattern match *) - | ValidMemcleanup -> () + | ValidDeref -> (* Enable the memOutOfBounds analysis *) + let memOobAna = ["memOutOfBounds"] in + print_endline @@ "Specification: ValidDeref -> enabling memOutOfBounds analysis \"" ^ (String.concat ", " memOobAna) ^ "\""; + enableAnalyses memOobAna + | ValidMemtrack + | ValidMemcleanup -> (* Enable the memLeak analysis *) + let memLeakAna = ["memLeak"] in + print_endline @@ "Specification: ValidDeref and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; + enableAnalyses memLeakAna + | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) + let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in + enableAnalyses memSafetyAnas (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound From 2c8e927f4e5f88b0a4eb003da6fd24ac55a0e004 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Mon, 2 Oct 2023 10:59:36 +0200 Subject: [PATCH 303/628] Rename UAF tests from number 78 to 74 --- .../{78-use_after_free => 74-use_after_free}/01-simple-uaf.c | 0 .../{78-use_after_free => 74-use_after_free}/02-conditional-uaf.c | 0 .../{78-use_after_free => 74-use_after_free}/03-nested-ptr-uaf.c | 0 .../04-function-call-uaf.c | 0 .../05-uaf-free-in-wrapper-fun.c | 0 .../{78-use_after_free => 74-use_after_free}/06-uaf-struct.c | 0 .../{78-use_after_free => 74-use_after_free}/07-itc-double-free.c | 0 .../08-itc-no-double-free.c | 0 .../{78-use_after_free => 74-use_after_free}/09-juliet-uaf.c | 0 .../10-juliet-double-free.c | 0 .../11-wrapper-funs-uaf.c | 0 .../12-multi-threaded-uaf.c | 0 .../13-multi-threaded-uaf-with-joined-thread.c | 0 .../{78-use_after_free => 74-use_after_free}/14-alloca-uaf.c | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{78-use_after_free => 74-use_after_free}/01-simple-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/02-conditional-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/03-nested-ptr-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/04-function-call-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/05-uaf-free-in-wrapper-fun.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/06-uaf-struct.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/07-itc-double-free.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/08-itc-no-double-free.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/09-juliet-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/10-juliet-double-free.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/11-wrapper-funs-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/12-multi-threaded-uaf.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/13-multi-threaded-uaf-with-joined-thread.c (100%) rename tests/regression/{78-use_after_free => 74-use_after_free}/14-alloca-uaf.c (100%) diff --git a/tests/regression/78-use_after_free/01-simple-uaf.c b/tests/regression/74-use_after_free/01-simple-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/01-simple-uaf.c rename to tests/regression/74-use_after_free/01-simple-uaf.c diff --git a/tests/regression/78-use_after_free/02-conditional-uaf.c b/tests/regression/74-use_after_free/02-conditional-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/02-conditional-uaf.c rename to tests/regression/74-use_after_free/02-conditional-uaf.c diff --git a/tests/regression/78-use_after_free/03-nested-ptr-uaf.c b/tests/regression/74-use_after_free/03-nested-ptr-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/03-nested-ptr-uaf.c rename to tests/regression/74-use_after_free/03-nested-ptr-uaf.c diff --git a/tests/regression/78-use_after_free/04-function-call-uaf.c b/tests/regression/74-use_after_free/04-function-call-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/04-function-call-uaf.c rename to tests/regression/74-use_after_free/04-function-call-uaf.c diff --git a/tests/regression/78-use_after_free/05-uaf-free-in-wrapper-fun.c b/tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c similarity index 100% rename from tests/regression/78-use_after_free/05-uaf-free-in-wrapper-fun.c rename to tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c diff --git a/tests/regression/78-use_after_free/06-uaf-struct.c b/tests/regression/74-use_after_free/06-uaf-struct.c similarity index 100% rename from tests/regression/78-use_after_free/06-uaf-struct.c rename to tests/regression/74-use_after_free/06-uaf-struct.c diff --git a/tests/regression/78-use_after_free/07-itc-double-free.c b/tests/regression/74-use_after_free/07-itc-double-free.c similarity index 100% rename from tests/regression/78-use_after_free/07-itc-double-free.c rename to tests/regression/74-use_after_free/07-itc-double-free.c diff --git a/tests/regression/78-use_after_free/08-itc-no-double-free.c b/tests/regression/74-use_after_free/08-itc-no-double-free.c similarity index 100% rename from tests/regression/78-use_after_free/08-itc-no-double-free.c rename to tests/regression/74-use_after_free/08-itc-no-double-free.c diff --git a/tests/regression/78-use_after_free/09-juliet-uaf.c b/tests/regression/74-use_after_free/09-juliet-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/09-juliet-uaf.c rename to tests/regression/74-use_after_free/09-juliet-uaf.c diff --git a/tests/regression/78-use_after_free/10-juliet-double-free.c b/tests/regression/74-use_after_free/10-juliet-double-free.c similarity index 100% rename from tests/regression/78-use_after_free/10-juliet-double-free.c rename to tests/regression/74-use_after_free/10-juliet-double-free.c diff --git a/tests/regression/78-use_after_free/11-wrapper-funs-uaf.c b/tests/regression/74-use_after_free/11-wrapper-funs-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/11-wrapper-funs-uaf.c rename to tests/regression/74-use_after_free/11-wrapper-funs-uaf.c diff --git a/tests/regression/78-use_after_free/12-multi-threaded-uaf.c b/tests/regression/74-use_after_free/12-multi-threaded-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/12-multi-threaded-uaf.c rename to tests/regression/74-use_after_free/12-multi-threaded-uaf.c diff --git a/tests/regression/78-use_after_free/13-multi-threaded-uaf-with-joined-thread.c b/tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c similarity index 100% rename from tests/regression/78-use_after_free/13-multi-threaded-uaf-with-joined-thread.c rename to tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c diff --git a/tests/regression/78-use_after_free/14-alloca-uaf.c b/tests/regression/74-use_after_free/14-alloca-uaf.c similarity index 100% rename from tests/regression/78-use_after_free/14-alloca-uaf.c rename to tests/regression/74-use_after_free/14-alloca-uaf.c From f87285462b6cdcff1a2081b0d80b266ce248a358 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:57:44 +0300 Subject: [PATCH 304/628] Fix print for valid-memtrack and valid-memcleanup in `autoTune.ml` Co-authored-by: Michael Schwarz --- src/autoTune.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index f73a71ed40..e093c63f08 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -230,7 +230,7 @@ let focusOnSpecification () = | ValidMemtrack | ValidMemcleanup -> (* Enable the memLeak analysis *) let memLeakAna = ["memLeak"] in - print_endline @@ "Specification: ValidDeref and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; + print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in From edaef4230d6db75def47f41b4a748c9cbd5aa83d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:02:01 +0200 Subject: [PATCH 305/628] Set `ana.malloc.unique_address_count` to `1` when activating memLeak analysis --- src/autoTune.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index e093c63f08..0441fe0b4f 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -230,6 +230,8 @@ let focusOnSpecification () = | ValidMemtrack | ValidMemcleanup -> (* Enable the memLeak analysis *) let memLeakAna = ["memLeak"] in + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) From 7f0b43ccf1db2d6c3bec95ce1ea759dff84e4fba Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:09:00 +0200 Subject: [PATCH 306/628] Improve some `AnalysisState` global flag comments --- src/framework/analysisState.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index 1416f99f69..05a93741f8 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -13,10 +13,10 @@ let svcomp_may_invalid_free = ref false (** Whether an invalid pointer dereference happened *) let svcomp_may_invalid_deref = ref false -(** Whether an invalid memtrack happened *) +(** Whether a memory leak occurred and there's no reference to the leaked memory *) let svcomp_may_invalid_memtrack = ref false -(** Whether an invalid memcleanup happened *) +(** Whether a memory leak occurred *) let svcomp_may_invalid_memcleanup = ref false (** A hack to see if we are currently doing global inits *) From a975702f700511c3c1f0b71979502462192d9bc2 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:25:33 +0200 Subject: [PATCH 307/628] Clean up some commented out code --- src/witness/svcompSpec.ml | 6 --- src/witness/witness.ml | 93 ++------------------------------------- 2 files changed, 3 insertions(+), 96 deletions(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 25a9f522bc..4a3da23d9b 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -37,12 +37,6 @@ let of_string s = let mem_safety_props = ["valid-free"; "valid-deref"; "valid-memtrack";] in if (global1 <> global2 && global1 <> global3 && global2 <> global3) && List.for_all (fun x -> List.mem x mem_safety_props) [global1; global2; global3] then MemorySafety - (* if global = "valid-free" then - ValidFree - else if global = "valid-deref" then - ValidDeref - else if global = "valid-memtrack" then - ValidMemtrack *) else failwith "Svcomp.Specification.of_string: unknown global expression" else if Str.string_match regexp_single s 0 then diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 35d932210d..a28f69f76a 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -505,96 +505,9 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidFree (*->*) - (* let module TrivialArg = - struct - include Arg - let next _ = [] - end - in - if not !AnalysisState.svcomp_may_invalid_free then ( - let module TaskResult = - struct - module Arg = Arg - let result = Result.True - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) else ( - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) *) - | ValidDeref (*->*) - (* let module TrivialArg = - struct - include Arg - let next _ = [] - end - in - if not !AnalysisState.svcomp_may_invalid_deref then ( - let module TaskResult = - struct - module Arg = Arg - let result = Result.True - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) else ( - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) *) - | ValidMemtrack (*->*) - (* let module TrivialArg = - struct - include Arg - let next _ = [] - end - in - if not !AnalysisState.svcomp_may_invalid_memtrack then ( - let module TaskResult = - struct - module Arg = Arg - let result = Result.True - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) else ( - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) *) + | ValidFree + | ValidDeref + | ValidMemtrack | MemorySafety -> let module TrivialArg = struct From b26010ac042143b4cdeb806b2a35b67054db1d76 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:31:31 +0200 Subject: [PATCH 308/628] Set `ana.malloc.unique_address_count` to `1` only if it's not already set to a value >= 1 --- src/autoTune.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 0441fe0b4f..4912d645ce 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -230,8 +230,10 @@ let focusOnSpecification () = | ValidMemtrack | ValidMemcleanup -> (* Enable the memLeak analysis *) let memLeakAna = ["memLeak"] in - print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; - set_int "ana.malloc.unique_address_count" 1; + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) From 89d68af6d7c68a647e13dd77e876580dbc8e71b1 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 12:35:30 +0200 Subject: [PATCH 309/628] Add a valid-memcleanup.prp file --- tests/sv-comp/valid-memcleanup.prp | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/sv-comp/valid-memcleanup.prp diff --git a/tests/sv-comp/valid-memcleanup.prp b/tests/sv-comp/valid-memcleanup.prp new file mode 100644 index 0000000000..778c49e5dc --- /dev/null +++ b/tests/sv-comp/valid-memcleanup.prp @@ -0,0 +1,2 @@ +CHECK( init(main()), LTL(G valid-memcleanup) ) + From 171ba57b315044c20252fbff625a652c0f2d328f Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 15:13:00 +0200 Subject: [PATCH 310/628] Comment out reachability filter in useAfterFree's `enter` --- src/analyses/useAfterFree.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index a28591e273..805bf1792c 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -182,7 +182,8 @@ struct let enter ctx (lval:lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = let caller_state = ctx.local in List.iter (fun arg -> warn_exp_might_contain_freed "enter" ctx arg) args; - if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then + [(caller_state, caller_state)] + (* if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then [caller_state, caller_state] else ( let reachable_from_args = List.fold_left (fun ad arg -> Queries.AD.join ad (ctx.ask (ReachableFrom arg))) (Queries.AD.empty ()) args in @@ -192,7 +193,7 @@ struct let reachable_vars = Queries.AD.to_var_may reachable_from_args in let callee_state = (AllocaVars.empty (), HeapVars.filter (fun var -> List.mem var reachable_vars) (snd caller_state)) in (* TODO: use AD.mem directly *) [caller_state, callee_state] - ) + ) *) let combine_env ctx (lval:lval option) fexp (f:fundec) (args:exp list) fc (callee_local:D.t) (f_ask:Queries.ask) : D.t = let (caller_stack_state, caller_heap_state) = ctx.local in From 4a1c038b5bd32674b8dff3bd9499d4a6ddbb2f85 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 15:25:31 +0200 Subject: [PATCH 311/628] Fix wrong callee_state in enter --- src/analyses/useAfterFree.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 805bf1792c..521f17d97f 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -182,7 +182,7 @@ struct let enter ctx (lval:lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = let caller_state = ctx.local in List.iter (fun arg -> warn_exp_might_contain_freed "enter" ctx arg) args; - [(caller_state, caller_state)] + [caller_state, (AllocaVars.empty (), snd caller_state)] (* if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then [caller_state, caller_state] else ( From bb2091e5038a437c23db3c8711d38f19a301ef05 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 15:25:45 +0200 Subject: [PATCH 312/628] Add test case for UAF in callee through a global var --- .../15-juliet-uaf-global-var.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/regression/74-use_after_free/15-juliet-uaf-global-var.c diff --git a/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c b/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c new file mode 100644 index 0000000000..9cb3b2b29a --- /dev/null +++ b/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c @@ -0,0 +1,24 @@ +//PARAM: --set ana.activated[+] useAfterFree --set ana.activated[+] threadJoins +#include +#include +#include + +int *global; + +void other(void) +{ + int *data = global; + free((void *)data); + return; +} + +int main(int argc, char **argv) +{ + int *data = (int *)malloc(400UL); + free((void *)data); + + global = data; + other(); + + return 0; +} \ No newline at end of file From fb4ad24d4f71f93181c3b908398bc785c5c32dfe Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 16:32:48 +0200 Subject: [PATCH 313/628] Fix typo for warning about top address offsets --- src/analyses/memOutOfBounds.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index db86a63414..ca2cf82116 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -205,7 +205,7 @@ struct set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a bot address offset. An invalid memory access may occur" d_exp ptr ) else if VDQ.AD.exists (function - | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o + | Addr (_, o) -> ID.is_top_of (Cilfacade.ptrdiff_ikind ()) (offs_to_idx t o) | _ -> false ) a then ( set_mem_safety_flag InvalidDeref; From 9d64db11a69abf60b0c777ee591860416c49666d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 16:33:09 +0200 Subject: [PATCH 314/628] Add test case with invalid deref in complex loop --- .../regression/77-mem-oob/10-oob-two-loops.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/regression/77-mem-oob/10-oob-two-loops.c diff --git a/tests/regression/77-mem-oob/10-oob-two-loops.c b/tests/regression/77-mem-oob/10-oob-two-loops.c new file mode 100644 index 0000000000..2661f3dff7 --- /dev/null +++ b/tests/regression/77-mem-oob/10-oob-two-loops.c @@ -0,0 +1,20 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +int main() { + int *p = malloc(1048 * sizeof(int)); + + for (int i = 0; i < 1048; ++i) { + p[i] = __VERIFIER_nondet_int(); //NOWARN + } + + int *q = p; + + while (*q >= 0 && q < p + 1048 * sizeof(int)) { //WARN + if (__VERIFIER_nondet_int()) { + q++; + } else { + (*q)--; //WARN + } + } + free(p); + return 0; +} From 1afac024c34280a8c1b6bfbeae254654800d5919 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 16:39:30 +0200 Subject: [PATCH 315/628] Disable info messages which confuse `make test` in 77/10 --- tests/regression/77-mem-oob/10-oob-two-loops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/77-mem-oob/10-oob-two-loops.c b/tests/regression/77-mem-oob/10-oob-two-loops.c index 2661f3dff7..6737a212bf 100644 --- a/tests/regression/77-mem-oob/10-oob-two-loops.c +++ b/tests/regression/77-mem-oob/10-oob-two-loops.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info int main() { int *p = malloc(1048 * sizeof(int)); From f5c197e119e44fa997022daebaaae98d8e07ecf0 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 17:28:47 +0200 Subject: [PATCH 316/628] Add option for enabling the marking of variables as pulled out of scope --- src/util/cilfacade.ml | 4 +++- src/util/options.schema.json | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index eb7330aa19..32b6627319 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -51,7 +51,9 @@ let init () = (* lineDirectiveStyle := None; *) RmUnused.keepUnused := true; print_CIL_Input := true; - Cabs2cil.allowDuplication := false + Cabs2cil.allowDuplication := false; + if get_bool "cil.addNestedScopeAttr" then + Cabs2cil.addNestedScopeAttr := true let current_file = ref dummyFile diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 1b9c7d3fd5..400dde06dc 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -288,6 +288,12 @@ "type": "boolean", "description": "Indicates whether gnu89 semantic should be used for inline functions.", "default": false + }, + "addNestedScopeAttr": { + "title": "cil.addNestedScopeAttr", + "type": "boolean", + "description": "Indicates whether variables that CIL pulls out of their scope should be marked.", + "default": false } }, "additionalProperties": false From 003b8148f3cb5035f083ee8c8e3ab339b3d9538e Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 17:29:17 +0200 Subject: [PATCH 317/628] Warn for accesses to variables pulled out of scope --- src/analyses/memOutOfBounds.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index ca2cf82116..9db6e58e5f 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -228,6 +228,7 @@ struct ID.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = + check_lval_out_of_scope_access lval; (* If the lval does not contain a pointer or if it does contain a pointer, but only points to string addresses, then no need to WARN *) if (not @@ lval_contains_a_ptr lval) || ptr_only_has_str_addr ctx (Lval lval) then () else @@ -246,6 +247,15 @@ struct | _ -> check_exp_for_oob_access ctx ~is_implicitly_derefed e end + and check_lval_out_of_scope_access lval = + match lval with + | (Var v, _) -> + if hasAttribute "goblint_cil_nested" v.vattr then ( + set_mem_safety_flag InvalidDeref; + M.warn "Lvalue %a is potentially accessed out-of-scope. Invalid memory access may occur" d_lval lval + ) + | _ -> () + and check_no_binop_deref ctx lval_exp = check_unknown_addr_deref ctx lval_exp; let behavior = Undefined MemoryOutOfBoundsAccess in From ac7dd717c0dc8f353130c1395dc0f7910aaf8f24 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 17:29:44 +0200 Subject: [PATCH 318/628] Automatically set `cil.addNestedScopeAttr` in autoTune when running `memOutOfBounds` --- src/autoTune.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index 4912d645ce..4e0080d0bd 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -225,6 +225,8 @@ let focusOnSpecification () = enableAnalyses uafAna | ValidDeref -> (* Enable the memOutOfBounds analysis *) let memOobAna = ["memOutOfBounds"] in + print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; print_endline @@ "Specification: ValidDeref -> enabling memOutOfBounds analysis \"" ^ (String.concat ", " memOobAna) ^ "\""; enableAnalyses memOobAna | ValidMemtrack From c95a846617c7a73c86d5a2e4655b5e0f16d4f32e Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 17:59:18 +0200 Subject: [PATCH 319/628] Bump goblint-cil --- goblint.opam | 6 +++--- goblint.opam.locked | 3 +++ goblint.opam.template | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/goblint.opam b/goblint.opam index 661222805b..88289820c1 100644 --- a/goblint.opam +++ b/goblint.opam @@ -74,12 +74,12 @@ dev-repo: "git+https://github.com/goblint/analyzer.git" # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -# pin-depends: [ +pin-depends: [ # published goblint-cil 2.0.2 is currently up-to-date, so no pin needed - # [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#98598d94f796a63751e5a9d39c6b3a9fe1f32330" ] + [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -# ] +] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] diff --git a/goblint.opam.locked b/goblint.opam.locked index bb59c41dd1..31acfdd4ea 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -122,6 +122,9 @@ build: [ ] dev-repo: "git+https://github.com/goblint/analyzer.git" available: os-distribution != "alpine" & arch != "arm64" +pin-depends: [ + [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] +] conflicts: [ "result" {< "1.5"} ] diff --git a/goblint.opam.template b/goblint.opam.template index 6259c4d498..3476f5befe 100644 --- a/goblint.opam.template +++ b/goblint.opam.template @@ -1,12 +1,12 @@ # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -# pin-depends: [ +pin-depends: [ # published goblint-cil 2.0.2 is currently up-to-date, so no pin needed - # [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#98598d94f796a63751e5a9d39c6b3a9fe1f32330" ] + [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -# ] +] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] From c9a846b6a74f1dd37f53d15d9909adb291ec82da Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 3 Oct 2023 18:48:01 +0200 Subject: [PATCH 320/628] set also for meta property --- src/autoTune.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 4e0080d0bd..10c9570d46 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -239,8 +239,10 @@ let focusOnSpecification () = print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) - let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in - enableAnalyses memSafetyAnas + (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; + let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in + enableAnalyses memSafetyAnas) (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound From 9efae6f8bef52e96d99052443f6a6a31a50f4dca Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 23:50:32 +0200 Subject: [PATCH 321/628] Fix address offset calculation in `memOutOfBounds` --- src/analyses/memOutOfBounds.ml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 9db6e58e5f..aadf433a6e 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -211,11 +211,16 @@ struct set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a top address offset. An invalid memory access may occur" d_exp ptr ); - (* Offset should be the same for all elements in the points-to set *) - (* Hence, we can just pick one element and obtain its offset *) - begin match VDQ.AD.choose a with - | Addr (_, o) -> offs_to_idx t o - | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + (* Get the address offsets of all points-to set elements *) + let addr_offsets = + VDQ.AD.filter (function Addr (v, o) -> true | _ -> false) a + |> VDQ.AD.to_mval + |> List.map (fun (_, o) -> offs_to_idx t o) + in + begin match addr_offsets with + | [] -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + | [x] -> x + | x::xs -> List.fold_left ID.join x xs end end | None -> From dcc3d5c3c608414092171f55fda99ebcd18d29c4 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 23:53:12 +0200 Subject: [PATCH 322/628] Adapt 77/10 test case to correctly account for address offsets --- tests/regression/77-mem-oob/10-oob-two-loops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/77-mem-oob/10-oob-two-loops.c b/tests/regression/77-mem-oob/10-oob-two-loops.c index 6737a212bf..5208da5a0b 100644 --- a/tests/regression/77-mem-oob/10-oob-two-loops.c +++ b/tests/regression/77-mem-oob/10-oob-two-loops.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none int main() { int *p = malloc(1048 * sizeof(int)); From a64e9c37e0b12eaa767e5f43f28b952c41ffa318 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 23:53:36 +0200 Subject: [PATCH 323/628] Add further test case to check address offset calculation in `memOutOfBounds` --- .../77-mem-oob/11-address-offset-oob.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/regression/77-mem-oob/11-address-offset-oob.c diff --git a/tests/regression/77-mem-oob/11-address-offset-oob.c b/tests/regression/77-mem-oob/11-address-offset-oob.c new file mode 100644 index 0000000000..ba01a12873 --- /dev/null +++ b/tests/regression/77-mem-oob/11-address-offset-oob.c @@ -0,0 +1,16 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +int main() { + int *p = malloc(2 * sizeof(int)); + int *q = p; + int x; + + if (x) { + q++; + q++; + q++; + x = *q; //WARN + } + + x = *q; //WARN + return 0; +} From 44476ce76e283c8adbdcb445c1799186cc1c3320 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 3 Oct 2023 23:56:46 +0200 Subject: [PATCH 324/628] Set `ana.malloc.unique_address_count` for `MemorySafety` as well --- src/autoTune.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index 10c9570d46..822195b1f6 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -241,6 +241,10 @@ let focusOnSpecification () = | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; set_bool "cil.addNestedScopeAttr" true; + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in enableAnalyses memSafetyAnas) From 80b3b72df749337a3b68435f45b3ff90a2a74dac Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 4 Oct 2023 11:49:49 +0300 Subject: [PATCH 325/628] Add ldv_kzalloc to svcomp malloc wrappers --- conf/svcomp.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 913d43784b..d6c07387a8 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -52,7 +52,8 @@ "ldv_xmalloc", "ldv_xzalloc", - "ldv_calloc" + "ldv_calloc", + "ldv_kzalloc" ] }, "base": { From 35f6d0000f61e2565e9e9ab86bf2279fd8ebce7a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 4 Oct 2023 11:54:54 +0300 Subject: [PATCH 326/628] Disable free races in svcomp They should be considered MemSafety issues instead. --- conf/svcomp.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/svcomp.json b/conf/svcomp.json index d6c07387a8..16c4ef338e 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -61,6 +61,9 @@ "domain": "partitioned" } }, + "race": { + "free": false + }, "autotune": { "enabled": true, "activated": [ From b6dfb14231e30c869e9c3a139b6ce7b609960a38 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 4 Oct 2023 11:55:39 +0300 Subject: [PATCH 327/628] Make threadid path sensitive in svcomp This is required for some ldv-races/ no-data-race tasks. --- conf/svcomp.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/conf/svcomp.json b/conf/svcomp.json index 16c4ef338e..f51c7a52ee 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -32,6 +32,14 @@ "thread", "threadJoins" ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "threadid" + ], "context": { "widen": false }, From e052544e9d225c6292ecce05a0468f3dad7b5f31 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 11:14:50 +0200 Subject: [PATCH 328/628] Move `cil.addNestedScopeAttr` setting to `init_options` --- src/util/cilfacade.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 8eaef280c6..6ca9023324 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -40,7 +40,9 @@ let is_first_field x = match x.fcomp.cfields with let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); - Cil.gnu89inline := get_bool "cil.gnu89inline" + Cil.gnu89inline := get_bool "cil.gnu89inline"; + if get_bool "cil.addNestedScopeAttr" = true then + Cabs2cil.addNestedScopeAttr := true let init () = initCIL (); @@ -51,9 +53,7 @@ let init () = (* lineDirectiveStyle := None; *) RmUnused.keepUnused := true; print_CIL_Input := true; - Cabs2cil.allowDuplication := false; - if get_bool "cil.addNestedScopeAttr" then - Cabs2cil.addNestedScopeAttr := true + Cabs2cil.allowDuplication := false let current_file = ref dummyFile From 11164fd7c7d709206c2e6483edd79492450af3c5 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 4 Oct 2023 12:15:54 +0300 Subject: [PATCH 329/628] Use exp.architecture for SV-COMP preprocessing Avoids a large number or CIL warnings about mismatching types. --- src/maingoblint.ml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 155faa0e76..ef548fb83a 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -252,6 +252,15 @@ let preprocess_files () = (* Preprocessor flags *) let cppflags = ref (get_string_list "pre.cppflags") in + if get_bool "ana.sv-comp.enabled" then ( + let architecture_flag = match get_string "exp.architecture" with + | "32bit" -> "-m32" + | "64bit" -> "-m64" + | _ -> assert false + in + cppflags := architecture_flag :: !cppflags + ); + (* the base include directory *) (* TODO: any better way? dune executable promotion doesn't add _build sites *) let source_lib_dirs = From 33414703562868d35f974bc2201238733959874c Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 11:36:10 +0200 Subject: [PATCH 330/628] Try with `cil.addNestedScopeAttr` always set to `true` --- src/util/cilfacade.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 6ca9023324..7009512adf 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -41,8 +41,8 @@ let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); Cil.gnu89inline := get_bool "cil.gnu89inline"; - if get_bool "cil.addNestedScopeAttr" = true then - Cabs2cil.addNestedScopeAttr := true + (* if get_bool "cil.addNestedScopeAttr" = true then *) + Cabs2cil.addNestedScopeAttr := true let init () = initCIL (); From 1211a9fe95fb881e8d53a7ab474498c31d675b7e Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 12:25:10 +0200 Subject: [PATCH 331/628] Use rand() in 77/10 --- tests/regression/77-mem-oob/10-oob-two-loops.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/regression/77-mem-oob/10-oob-two-loops.c b/tests/regression/77-mem-oob/10-oob-two-loops.c index 5208da5a0b..303aac242e 100644 --- a/tests/regression/77-mem-oob/10-oob-two-loops.c +++ b/tests/regression/77-mem-oob/10-oob-two-loops.c @@ -1,15 +1,17 @@ // PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +#include + int main() { int *p = malloc(1048 * sizeof(int)); for (int i = 0; i < 1048; ++i) { - p[i] = __VERIFIER_nondet_int(); //NOWARN + p[i] = rand(); //NOWARN } int *q = p; while (*q >= 0 && q < p + 1048 * sizeof(int)) { //WARN - if (__VERIFIER_nondet_int()) { + if (rand()) { q++; } else { (*q)--; //WARN From 20396754a27385fdc788557ef30704da339ae8cc Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 12:45:14 +0200 Subject: [PATCH 332/628] Activate `cil.addNestedScopeAttr` in cilfacade only conditionally --- src/util/cilfacade.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 7009512adf..7ac3e29ee0 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -41,8 +41,8 @@ let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); Cil.gnu89inline := get_bool "cil.gnu89inline"; - (* if get_bool "cil.addNestedScopeAttr" = true then *) - Cabs2cil.addNestedScopeAttr := true + if get_bool "cil.addNestedScopeAttr" then + Cabs2cil.addNestedScopeAttr := true let init () = initCIL (); From fb4979b567d4664c9012d3d98a9a32ba2f0b39d9 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 12:46:11 +0200 Subject: [PATCH 333/628] Activate SV-COMP memory-safety-related options before CIL has completely parsed the program --- src/autoTune.ml | 21 +++++++++++++-------- src/goblint.ml | 2 ++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 822195b1f6..186d930189 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -210,15 +210,8 @@ let activateLongjmpAnalysesWhenRequired () = enableAnalyses longjmpAnalyses; ) -let focusOnSpecification () = +let focusOnMemSafetySpecification () = match Svcomp.Specification.of_option () with - | UnreachCall s -> () - | NoDataRace -> (*enable all thread analyses*) - print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; - enableAnalyses notNeccessaryThreadAnalyses; - | NoOverflow -> (*We focus on integer analysis*) - set_bool "ana.int.def_exc" true; - set_bool "ana.int.interval" true | ValidFree -> (* Enable the useAfterFree analysis *) let uafAna = ["useAfterFree"] in print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; @@ -247,6 +240,18 @@ let focusOnSpecification () = ); let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in enableAnalyses memSafetyAnas) + | _ -> () + +let focusOnSpecification () = + match Svcomp.Specification.of_option () with + | UnreachCall s -> () + | NoDataRace -> (*enable all thread analyses*) + print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; + enableAnalyses notNeccessaryThreadAnalyses; + | NoOverflow -> (*We focus on integer analysis*) + set_bool "ana.int.def_exc" true; + set_bool "ana.int.interval" true + | _ -> () (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound diff --git a/src/goblint.ml b/src/goblint.ml index 4ea3a3d242..45dae3a4c6 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -56,6 +56,8 @@ let main () = else None in + if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then + AutoTune.focusOnMemSafetySpecification (); (* This is run independant of the autotuner being enabled or not be sound for programs with longjmp *) AutoTune.activateLongjmpAnalysesWhenRequired (); if get_bool "ana.autotune.enabled" then AutoTune.chooseConfig file; From 1eb7309b472c1392b1812fecf4adb1b2b756bb05 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 13:59:05 +0200 Subject: [PATCH 334/628] Fix again scoping check --- src/analyses/memOutOfBounds.ml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index aadf433a6e..655ed7d3f1 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -89,6 +89,10 @@ struct let pts_elems_to_sizes (addr: Queries.AD.elt) = begin match addr with | Addr (v, _) -> + if hasAttribute "goblint_cil_nested" v.vattr then ( + set_mem_safety_flag InvalidDeref; + M.warn "Var %a is potentially accessed out-of-scope. Invalid memory access may occur" CilType.Varinfo.pretty v + ); begin match v.vtype with | TArray (item_typ, _, _) -> let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in @@ -233,7 +237,6 @@ struct ID.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = - check_lval_out_of_scope_access lval; (* If the lval does not contain a pointer or if it does contain a pointer, but only points to string addresses, then no need to WARN *) if (not @@ lval_contains_a_ptr lval) || ptr_only_has_str_addr ctx (Lval lval) then () else @@ -252,15 +255,6 @@ struct | _ -> check_exp_for_oob_access ctx ~is_implicitly_derefed e end - and check_lval_out_of_scope_access lval = - match lval with - | (Var v, _) -> - if hasAttribute "goblint_cil_nested" v.vattr then ( - set_mem_safety_flag InvalidDeref; - M.warn "Lvalue %a is potentially accessed out-of-scope. Invalid memory access may occur" d_lval lval - ) - | _ -> () - and check_no_binop_deref ctx lval_exp = check_unknown_addr_deref ctx lval_exp; let behavior = Undefined MemoryOutOfBoundsAccess in From a840e412a7eedcd3cd6a2c8b3166e80acb4b8f2b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 4 Oct 2023 16:40:37 +0300 Subject: [PATCH 335/628] Extract most library extensions to std dune library --- src/dune | 19 ++++++++++--------- src/goblint_lib.ml | 17 +++-------------- src/util/std/dune | 17 +++++++++++++++++ src/util/{ => std}/gobFpath.ml | 0 src/util/{ => std}/gobGc.ml | 0 src/util/{ => std}/gobHashtbl.ml | 0 src/util/{ => std}/gobList.ml | 0 src/util/{ => std}/gobOption.ml | 0 src/util/{ => std}/gobPretty.ml | 0 src/util/{ => std}/gobRef.ml | 0 src/util/{ => std}/gobResult.ml | 0 src/util/{ => std}/gobSys.ml | 0 src/util/{ => std}/gobUnix.ml | 0 src/util/{ => std}/gobYaml.ml | 0 src/util/{ => std}/gobYojson.ml | 0 src/util/{ => std}/gobZ.ml | 0 src/util/std/goblint_std.ml | 24 ++++++++++++++++++++++++ 17 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 src/util/std/dune rename src/util/{ => std}/gobFpath.ml (100%) rename src/util/{ => std}/gobGc.ml (100%) rename src/util/{ => std}/gobHashtbl.ml (100%) rename src/util/{ => std}/gobList.ml (100%) rename src/util/{ => std}/gobOption.ml (100%) rename src/util/{ => std}/gobPretty.ml (100%) rename src/util/{ => std}/gobRef.ml (100%) rename src/util/{ => std}/gobResult.ml (100%) rename src/util/{ => std}/gobSys.ml (100%) rename src/util/{ => std}/gobUnix.ml (100%) rename src/util/{ => std}/gobYaml.ml (100%) rename src/util/{ => std}/gobYojson.ml (100%) rename src/util/{ => std}/gobZ.ml (100%) create mode 100644 src/util/std/goblint_std.ml diff --git a/src/dune b/src/dune index 85944375ea..a8cda818b1 100644 --- a/src/dune +++ b/src/dune @@ -7,7 +7,7 @@ (name goblint_lib) (public_name goblint.lib) (modules :standard \ goblint mainspec privPrecCompare apronPrecCompare messagesCompare) - (libraries goblint.sites goblint.build-info goblint-cil.all-features batteries.unthreaded qcheck-core.runner sha json-data-encoding jsonrpc cpu arg-complete fpath yaml yaml.unix uuidm goblint_timing catapult goblint_backtrace fileutils + (libraries goblint.sites goblint.build-info goblint-cil.all-features batteries.unthreaded qcheck-core.runner sha json-data-encoding jsonrpc cpu arg-complete fpath yaml yaml.unix uuidm goblint_timing catapult goblint_backtrace fileutils goblint_std ; Conditionally compile based on whether apron optional dependency is installed or not. ; Alternative dependencies seem like the only way to optionally depend on optional dependencies. ; See: https://dune.readthedocs.io/en/stable/concepts.html#alternative-dependencies. @@ -56,6 +56,7 @@ (-> violationZ3.no-z3.ml) ) ) + (flags :standard -open Goblint_std) (foreign_stubs (language c) (names stubs)) (ocamlopt_flags :standard -no-float-const-prop) (preprocess @@ -77,33 +78,33 @@ (public_names goblint -) (modes byte native) ; https://dune.readthedocs.io/en/stable/dune-files.html#linking-modes (modules goblint mainspec) - (libraries goblint.lib goblint.sites.dune goblint.build-info.dune) + (libraries goblint.lib goblint.sites.dune goblint.build-info.dune goblint_std) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson)) - (flags :standard -linkall) + (flags :standard -linkall -open Goblint_std) ) (executable (name privPrecCompare) (modules privPrecCompare) - (libraries goblint.lib goblint.sites.dune goblint.build-info.dune) + (libraries goblint.lib goblint.sites.dune goblint.build-info.dune goblint_std) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson)) - (flags :standard -linkall) + (flags :standard -linkall -open Goblint_std) ) (executable (name apronPrecCompare) (modules apronPrecCompare) - (libraries goblint.lib goblint.sites.dune goblint.build-info.dune) + (libraries goblint.lib goblint.sites.dune goblint.build-info.dune goblint_std) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson)) - (flags :standard -linkall) + (flags :standard -linkall -open Goblint_std) ) (executable (name messagesCompare) (modules messagesCompare) - (libraries goblint.lib goblint.sites.dune goblint.build-info.dune) + (libraries goblint.lib goblint.sites.dune goblint.build-info.dune goblint_std) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson)) - (flags :standard -linkall) + (flags :standard -linkall -open Goblint_std) ) (rule diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 6e700485dd..816a69faff 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -469,29 +469,18 @@ module ConfigVersion = ConfigVersion (** {1 Library extensions} - OCaml library extensions which are completely independent of Goblint. *) + OCaml library extensions which are completely independent of Goblint. + + See {!Goblint_std}. *) (** {2 Standard library} OCaml standard library extensions which are not provided by {!Batteries}. *) module GobFormat = GobFormat -module GobGc = GobGc -module GobHashtbl = GobHashtbl -module GobList = GobList -module GobRef = GobRef -module GobResult = GobResult -module GobOption = GobOption -module GobSys = GobSys -module GobUnix = GobUnix (** {2 Other libraries} External library extensions. *) -module GobFpath = GobFpath -module GobPretty = GobPretty -module GobYaml = GobYaml -module GobYojson = GobYojson -module GobZ = GobZ module MyCheck = MyCheck diff --git a/src/util/std/dune b/src/util/std/dune new file mode 100644 index 0000000000..c85710a8d6 --- /dev/null +++ b/src/util/std/dune @@ -0,0 +1,17 @@ +(include_subdirs no) + +(library + (name goblint_std) + (public_name goblint.std) + (libraries + batteries + zarith + goblint-cil + fpath + yojson + yaml) + (preprocess + (pps + ppx_deriving.std + ppx_deriving_hash + ppx_deriving_yojson))) diff --git a/src/util/gobFpath.ml b/src/util/std/gobFpath.ml similarity index 100% rename from src/util/gobFpath.ml rename to src/util/std/gobFpath.ml diff --git a/src/util/gobGc.ml b/src/util/std/gobGc.ml similarity index 100% rename from src/util/gobGc.ml rename to src/util/std/gobGc.ml diff --git a/src/util/gobHashtbl.ml b/src/util/std/gobHashtbl.ml similarity index 100% rename from src/util/gobHashtbl.ml rename to src/util/std/gobHashtbl.ml diff --git a/src/util/gobList.ml b/src/util/std/gobList.ml similarity index 100% rename from src/util/gobList.ml rename to src/util/std/gobList.ml diff --git a/src/util/gobOption.ml b/src/util/std/gobOption.ml similarity index 100% rename from src/util/gobOption.ml rename to src/util/std/gobOption.ml diff --git a/src/util/gobPretty.ml b/src/util/std/gobPretty.ml similarity index 100% rename from src/util/gobPretty.ml rename to src/util/std/gobPretty.ml diff --git a/src/util/gobRef.ml b/src/util/std/gobRef.ml similarity index 100% rename from src/util/gobRef.ml rename to src/util/std/gobRef.ml diff --git a/src/util/gobResult.ml b/src/util/std/gobResult.ml similarity index 100% rename from src/util/gobResult.ml rename to src/util/std/gobResult.ml diff --git a/src/util/gobSys.ml b/src/util/std/gobSys.ml similarity index 100% rename from src/util/gobSys.ml rename to src/util/std/gobSys.ml diff --git a/src/util/gobUnix.ml b/src/util/std/gobUnix.ml similarity index 100% rename from src/util/gobUnix.ml rename to src/util/std/gobUnix.ml diff --git a/src/util/gobYaml.ml b/src/util/std/gobYaml.ml similarity index 100% rename from src/util/gobYaml.ml rename to src/util/std/gobYaml.ml diff --git a/src/util/gobYojson.ml b/src/util/std/gobYojson.ml similarity index 100% rename from src/util/gobYojson.ml rename to src/util/std/gobYojson.ml diff --git a/src/util/gobZ.ml b/src/util/std/gobZ.ml similarity index 100% rename from src/util/gobZ.ml rename to src/util/std/gobZ.ml diff --git a/src/util/std/goblint_std.ml b/src/util/std/goblint_std.ml new file mode 100644 index 0000000000..e716d1df5b --- /dev/null +++ b/src/util/std/goblint_std.ml @@ -0,0 +1,24 @@ +(** OCaml library extensions which are completely independent of Goblint. *) + +(** {1 Standard library} + + OCaml standard library extensions which are not provided by {!Batteries}. *) + +module GobGc = GobGc +module GobHashtbl = GobHashtbl +module GobList = GobList +module GobRef = GobRef +module GobResult = GobResult +module GobOption = GobOption +module GobSys = GobSys +module GobUnix = GobUnix + +(** {1 Other libraries} + + External library extensions. *) + +module GobFpath = GobFpath +module GobPretty = GobPretty +module GobYaml = GobYaml +module GobYojson = GobYojson +module GobZ = GobZ From 4a4b6abc6edd18d1487084131a4f3bc038fe526f Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 19:48:48 +0200 Subject: [PATCH 336/628] Fix conditional enabling of `cil.addNestedScopeAttr` --- src/goblint.ml | 2 -- src/maingoblint.ml | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/goblint.ml b/src/goblint.ml index 45dae3a4c6..4ea3a3d242 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -56,8 +56,6 @@ let main () = else None in - if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then - AutoTune.focusOnMemSafetySpecification (); (* This is run independant of the autotuner being enabled or not be sound for programs with longjmp *) AutoTune.activateLongjmpAnalysesWhenRequired (); if get_bool "ana.autotune.enabled" then AutoTune.chooseConfig file; diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 155faa0e76..0f061a3507 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -185,6 +185,8 @@ let handle_options () = check_arguments (); AfterConfig.run (); Sys.set_signal (GobSys.signal_of_string (get_string "dbg.solver-signal")) Signal_ignore; (* Ignore solver-signal before solving (e.g. MyCFG), otherwise exceptions self-signal the default, which crashes instead of printing backtrace. *) + if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then + AutoTune.focusOnMemSafetySpecification (); Cilfacade.init_options (); handle_flags () From 395c30db266591bc2e20b663274628278bb3b6f0 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 20:39:15 +0200 Subject: [PATCH 337/628] Warn for invalid deallocation when encountering invalid addresses --- src/analyses/base.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 81bd29f8d0..a9457ca41b 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2039,7 +2039,9 @@ struct AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr ) - | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname + | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidFree; + M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname let special ctx (lv:lval option) (f: varinfo) (args: exp list) = From 055d9cc01b2fa8332c00e9011183d18cd2bf2fc6 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 20:39:39 +0200 Subject: [PATCH 338/628] Add invalid address test case for invalid deallocation --- .../10-invalid-dealloc-union.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c diff --git a/tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c b/tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c new file mode 100644 index 0000000000..be1eaa056d --- /dev/null +++ b/tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c @@ -0,0 +1,42 @@ +extern void abort(void); +#include + +extern int __VERIFIER_nondet_int(void); + +int main() +{ + union { + void *p0; + + struct { + char c[2]; + int p1; + int p2; + } str; + + } data; + + // alloc 37B on heap + data.p0 = malloc(37U); + + // avoid introducing a memleak + void *ptr = data.p0; + + // this should be fine + if(__VERIFIER_nondet_int()) { + data.str.p2 = 20; + } else { + data.str.p2 = 30; + } + + if(25 > data.str.p2) { + // avoids memleak + data.str.c[1] = sizeof data.str.p1; + } + + // invalid free() + free(data.p0);//WARN + + free(ptr);//NOWARN + return 0; +} From 2c883eb32cc67f17a48bb4ff7aca73f5811a056b Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 21:58:30 +0200 Subject: [PATCH 339/628] Warn if lval contains an address with a non-local var --- src/analyses/base.ml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index a9457ca41b..a323e5f270 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1051,7 +1051,18 @@ struct else if AD.may_be_null adr then ( AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" - ) + ); + (* Warn if any of the addresses contains a non-local variable *) + AD.iter (function + | AD.Addr.Addr (v,o) -> + if not @@ CPA.mem v st.cpa then ( + (* TODO: Not the smartest move to set the global flag within an iter *) + (* TODO: We can resort to using AD.exists instead *) + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn "lval %a points to non-local variable %a. Invalid pointer dereference may occur" d_lval lval CilType.Varinfo.pretty v + ) + | _ -> () + ) adr ); AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr | _ -> From 5cb10f61925e55932475e859569d496a630fee6a Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 22:09:51 +0200 Subject: [PATCH 340/628] Don't warn for non-local vars in address set if they're globals --- src/analyses/base.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index a323e5f270..a5b60e8cca 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1055,7 +1055,7 @@ struct (* Warn if any of the addresses contains a non-local variable *) AD.iter (function | AD.Addr.Addr (v,o) -> - if not @@ CPA.mem v st.cpa then ( + if not (CPA.mem v st.cpa) && not (is_global a v) then ( (* TODO: Not the smartest move to set the global flag within an iter *) (* TODO: We can resort to using AD.exists instead *) AnalysisStateUtil.set_mem_safety_flag InvalidDeref; From ea4410d8d0939d93f5effa56fd51c9549c717641 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 22:10:11 +0200 Subject: [PATCH 341/628] Add test cases for invalid deref due to scoping --- .../01-scopes-no-static.c | 22 ++++++++ .../02-scopes-global-var.c | 29 +++++++++++ .../03-scopes-static.c | 52 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c create mode 100644 tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c create mode 100644 tests/regression/78-invalid-deref-scopes/03-scopes-static.c diff --git a/tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c b/tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c new file mode 100644 index 0000000000..e0c4b47b73 --- /dev/null +++ b/tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c @@ -0,0 +1,22 @@ +// PARAM: --set ana.activated[+] memOutOfBounds +// TODO: I haven't checked why, but we need memOutOfBounds for this case +extern int printf ( const char * format, ... ); + +int *foo2(void) +{ + int arr[1024]; + arr[194] = 13; + return arr + 1; +} + +int *foo(void) +{ + int arr[123]; + return foo2(); +} + +int main(void) { + int *a = foo(); + printf("%d\n", *a);//WARN + return 0; +} diff --git a/tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c b/tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c new file mode 100644 index 0000000000..9491e1c574 --- /dev/null +++ b/tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c @@ -0,0 +1,29 @@ +int array[10]; + +// function returns array of numbers +int* getNumbers(void) { + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2(void) { + int* numbers = getNumbers(); + // numbers2 is local + int numbers2[10]; + + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + + return numbers2; +} + +int main(void) { + int *numbers = getNumbers2(); + numbers[0] = 100;//WARN + + return 0; +} diff --git a/tests/regression/78-invalid-deref-scopes/03-scopes-static.c b/tests/regression/78-invalid-deref-scopes/03-scopes-static.c new file mode 100644 index 0000000000..c13b665c84 --- /dev/null +++ b/tests/regression/78-invalid-deref-scopes/03-scopes-static.c @@ -0,0 +1,52 @@ +extern int printf (const char* format, ...); + +// function returns array of numbers +int* getNumbers() { + + static int array[10]; + + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2() { + int* numbers = getNumbers(); + static int numbers2[10]; + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + return numbers2; +} + +int* getNumbers3() { + int* numbers = getNumbers2(); + int numbers3[10]; + for (int i = 0; i < 10; ++i) { + numbers3[i] = numbers[i];//NOWARN + } + + return numbers3; +} + +int* getNumbers4() { + int* numbers = getNumbers3(); + static int numbers4[10]; + for (int i = 0; i < 10; ++i) { + numbers4[i] = numbers[i];//WARN + } + return numbers4; +} + +int main (void) { + + int *numbers = getNumbers4(); + + for (int i = 0; i < 10; i++ ) { + printf( "%d\n", *(numbers + i));//NOWARN + } + + return 0; +} From 6745d799de882a056df9dd0c695668592a5f31eb Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 22:49:37 +0200 Subject: [PATCH 342/628] Slightly refactor `check_count` and check for `src`'s size in `memcpy` --- src/analyses/memOutOfBounds.ml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 655ed7d3f1..8a2ca12467 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -372,22 +372,22 @@ struct | _ -> () (* For memset() and memcpy() *) - let check_count ctx fun_name dest n = + let check_count ctx fun_name ptr n = let (behavior:MessageCategory.behavior) = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in - let dest_size = get_size_of_ptr_target ctx dest in + let ptr_size = get_size_of_ptr_target ctx ptr in let eval_n = ctx.ask (Queries.EvalInt n) in - let addr_offs = get_addr_offs ctx dest in - match dest_size, eval_n with + let addr_offs = get_addr_offs ctx ptr in + match ptr_size, eval_n with | `Top, _ -> set_mem_safety_flag InvalidDeref; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp dest fun_name + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Top -> set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is unknown. Memory out-of-bounds access might occur" fun_name | `Bot, _ -> set_mem_safety_flag InvalidDeref; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp dest fun_name + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Bot -> set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is bottom" fun_name @@ -399,7 +399,7 @@ struct begin match ID.to_bool dest_size_lt_count with | Some true -> set_mem_safety_flag InvalidDeref; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of %a in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" d_exp ptr fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en | Some false -> () | None -> set_mem_safety_flag InvalidDeref; @@ -436,7 +436,9 @@ struct (* Check calls to memset and memcpy for out-of-bounds-accesses *) match desc.special arglist with | Memset { dest; ch; count; } -> check_count ctx f.vname dest count; - | Memcpy { dest; src; n = count; } -> check_count ctx f.vname dest count; + | Memcpy { dest; src; n = count; } -> + check_count ctx f.vname src count; + check_count ctx f.vname dest count; | _ -> (); ctx.local From 136bec0232107c61a42a3ed369a03aee90fbf2b8 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 22:50:41 +0200 Subject: [PATCH 343/628] Add test case with wrong src size for memcpy --- .../regression/77-mem-oob/12-memcpy-oob-src.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/regression/77-mem-oob/12-memcpy-oob-src.c diff --git a/tests/regression/77-mem-oob/12-memcpy-oob-src.c b/tests/regression/77-mem-oob/12-memcpy-oob-src.c new file mode 100644 index 0000000000..0f3a609fbe --- /dev/null +++ b/tests/regression/77-mem-oob/12-memcpy-oob-src.c @@ -0,0 +1,43 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info +// TODO: The "--disable warn.info" part is a temporary fix and needs to be removed once the MacOS CI job is fixed +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d:5; + unsigned char e; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(5); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + // It's an OOB error, because sizeof(d) == 4 + memcpy(p, &d, 5); //WARN + if (p->a != 1) { + free(p); + } + if (p->b != 2) { + free(p); + } + if (p->c != 3) { + free(p); + } + if (p->d != 4) { + free(p); + } + if (p->e != 5) { + free(p); + } + free(p); +} + From 3a2fe3f09278fc80fe8e6b68c3697f6996bf7030 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 4 Oct 2023 22:53:50 +0200 Subject: [PATCH 344/628] Correct test 77/07 to warn for src OOB access in memcpy as well --- tests/regression/77-mem-oob/07-memcpy-oob.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/77-mem-oob/07-memcpy-oob.c b/tests/regression/77-mem-oob/07-memcpy-oob.c index 012f92996e..5605404a87 100644 --- a/tests/regression/77-mem-oob/07-memcpy-oob.c +++ b/tests/regression/77-mem-oob/07-memcpy-oob.c @@ -31,13 +31,13 @@ int main(int argc, char const *argv[]) { memcpy(a, b, 40); //WARN memcpy(a, b, sizeof(a)); //WARN - memcpy(b, a, 60); //NOWARN + memcpy(b, a, 60); //WARN b += 1; memcpy(b, a, 60); //WARN s *s_ptr = malloc(sizeof(s)); - memcpy(s_ptr, a, sizeof(s)); //NOWARN + memcpy(s_ptr, a, sizeof(s)); //WARN memcpy(s_ptr->a, 0, sizeof(s)); //WARN memcpy(s_ptr->b, 0, sizeof(s)); //WARN From 0776dbe5423c38aa74acfbdc1cdd88c148e2051d Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 5 Oct 2023 12:02:14 +0300 Subject: [PATCH 345/628] Add __builtin_clzll to library functions --- src/analyses/libraryFunctions.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 9ee9dc8c9d..7695844dd0 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -374,6 +374,8 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__builtin_ctzl", unknown [drop "x" []]); ("__builtin_ctzll", unknown [drop "x" []]); ("__builtin_clz", unknown [drop "x" []]); + ("__builtin_clzl", unknown [drop "x" []]); + ("__builtin_clzll", unknown [drop "x" []]); ("__builtin_object_size", unknown [drop "ptr" [r]; drop' []]); ("__builtin_prefetch", unknown (drop "addr" [] :: VarArgs (drop' []))); ("__builtin_expect", special [__ "exp" []; drop' []] @@ fun exp -> Identity exp); (* Identity, because just compiler optimization annotation. *) From 7b76751a6cc2100f7c303c481fe28c0b7a4737a4 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 5 Oct 2023 12:37:54 +0300 Subject: [PATCH 346/628] Move config modules to build_info dune library --- src/build-info/.gitignore | 1 + ...blint_build_info.ml => dune_build_info.ml} | 0 ...blint_build_info.ml => dune_build_info.ml} | 0 src/build-info/dune | 20 ++++++++++- ...int_build_info.mli => dune_build_info.mli} | 0 src/build-info/goblint_build_info.ml | 34 +++++++++++++++++++ src/dune | 16 --------- src/framework/control.ml | 2 +- src/goblint_lib.ml | 15 -------- src/maingoblint.ml | 6 ++-- src/util/sarif.ml | 2 +- src/util/tracing.ml | 2 +- src/version.ml | 16 --------- src/witness/witness.ml | 2 +- src/witness/yamlWitness.ml | 2 +- 15 files changed, 62 insertions(+), 56 deletions(-) create mode 100644 src/build-info/.gitignore rename src/build-info/build_info_dune/{goblint_build_info.ml => dune_build_info.ml} (100%) rename src/build-info/build_info_js/{goblint_build_info.ml => dune_build_info.ml} (100%) rename src/build-info/{goblint_build_info.mli => dune_build_info.mli} (100%) create mode 100644 src/build-info/goblint_build_info.ml delete mode 100644 src/version.ml diff --git a/src/build-info/.gitignore b/src/build-info/.gitignore new file mode 100644 index 0000000000..8afff91d71 --- /dev/null +++ b/src/build-info/.gitignore @@ -0,0 +1 @@ +config*.ml diff --git a/src/build-info/build_info_dune/goblint_build_info.ml b/src/build-info/build_info_dune/dune_build_info.ml similarity index 100% rename from src/build-info/build_info_dune/goblint_build_info.ml rename to src/build-info/build_info_dune/dune_build_info.ml diff --git a/src/build-info/build_info_js/goblint_build_info.ml b/src/build-info/build_info_js/dune_build_info.ml similarity index 100% rename from src/build-info/build_info_js/goblint_build_info.ml rename to src/build-info/build_info_js/dune_build_info.ml diff --git a/src/build-info/dune b/src/build-info/dune index 89ae841778..c1de250263 100644 --- a/src/build-info/dune +++ b/src/build-info/dune @@ -8,4 +8,22 @@ (library (name goblint_build_info) (public_name goblint.build-info) - (virtual_modules goblint_build_info)) + (libraries batteries.unthreaded) + (virtual_modules dune_build_info)) + +(rule + (target configVersion.ml) + (mode (promote (until-clean) (only configVersion.ml))) ; replace existing file in source tree, even if releasing (only overrides) + (deps (universe)) ; do not cache, always regenerate + (action (pipe-stdout (bash "git describe --all --long --dirty || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet version = \"%s\"'"))))) + +(rule + (target configProfile.ml) + (mode (promote (until-clean) (only configProfile.ml))) ; replace existing file in source tree, even if releasing (only overrides) + (action (write-file %{target} "(* Automatically regenerated, changes do not persist! *)\nlet profile = \"%{profile}\""))) + +(rule + (target configOcaml.ml) + (mode (promote (until-clean) (only configOcaml.ml))) ; replace existing file in source tree, even if releasing (only overrides) + (action (write-file %{target} "(* Automatically regenerated, changes do not persist! *)\nlet flambda = \"%{ocaml-config:flambda}\""))) + diff --git a/src/build-info/goblint_build_info.mli b/src/build-info/dune_build_info.mli similarity index 100% rename from src/build-info/goblint_build_info.mli rename to src/build-info/dune_build_info.mli diff --git a/src/build-info/goblint_build_info.ml b/src/build-info/goblint_build_info.ml new file mode 100644 index 0000000000..cf5165d51c --- /dev/null +++ b/src/build-info/goblint_build_info.ml @@ -0,0 +1,34 @@ +(** Goblint build info. *) + +(** OCaml compiler flambda status. *) +let ocaml_flambda = ConfigOcaml.flambda + +(** Dune profile. *) +let dune_profile = ConfigProfile.profile + +(** Goblint version from git. *) +let git_version = ConfigVersion.version + +(** Goblint version from release archive. *) +let release_version = "%%VERSION_NUM%%" + +(** Goblint git commit from release archive. *) +let release_commit = "%%VCS_COMMIT_ID%%" + +(** Goblint version. *) +let version = + let commit = ConfigVersion.version in + if BatString.starts_with release_version "%" then + commit + else ( + let commit = + if commit = "n/a" then (* released archive has no .git *) + release_commit + else + commit + in + Format.sprintf "%s (%s)" release_version commit + ) + +(** Statically linked libraries with versions. *) +let statically_linked_libraries = Dune_build_info.statically_linked_libraries diff --git a/src/dune b/src/dune index a8cda818b1..5fdf58a5b2 100644 --- a/src/dune +++ b/src/dune @@ -107,22 +107,6 @@ (flags :standard -linkall -open Goblint_std) ) -(rule - (target configVersion.ml) - (mode (promote (until-clean) (only configVersion.ml))) ; replace existing file in source tree, even if releasing (only overrides) - (deps (universe)) ; do not cache, always regenerate - (action (pipe-stdout (bash "git describe --all --long --dirty || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet version = \"%s\"'"))))) - -(rule - (target configProfile.ml) - (mode (promote (until-clean) (only configProfile.ml))) ; replace existing file in source tree, even if releasing (only overrides) - (action (write-file %{target} "(* Automatically regenerated, changes do not persist! *)\nlet profile = \"%{profile}\""))) - -(rule - (target configOcaml.ml) - (mode (promote (until-clean) (only configOcaml.ml))) ; replace existing file in source tree, even if releasing (only overrides) - (action (write-file %{target} "(* Automatically regenerated, changes do not persist! *)\nlet flambda = \"%{ocaml-config:flambda}\""))) - (rule (alias runtest) (deps ../goblint ../scripts/update_suite.rb ../Makefile ../make.sh (source_tree ../tests/regression) (source_tree ../includes) (source_tree ../linux-headers)) diff --git a/src/framework/control.ml b/src/framework/control.ml index 5cefc1a7de..9baa2dd1ca 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -529,7 +529,7 @@ struct 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 = Version.goblint; timestamp = Unix.time (); localtime = GobUnix.localtime () } + 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; *) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 816a69faff..e009ecf86b 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -452,21 +452,6 @@ module PrivPrecCompareUtil = PrivPrecCompareUtil module RelationPrecCompareUtil = RelationPrecCompareUtil module ApronPrecCompareUtil = ApronPrecCompareUtil -(** {2 Build info} *) - -(** OCaml compiler info. *) -module ConfigOcaml = ConfigOcaml - -(** Dune profile info. *) -module ConfigProfile = ConfigProfile - -(** Goblint version info. *) -module Version = Version - -(** Goblint git version info. *) -module ConfigVersion = ConfigVersion - - (** {1 Library extensions} OCaml library extensions which are completely independent of Goblint. diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 7808cbcd3f..98363233a2 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -9,11 +9,11 @@ let writeconffile = ref None (** Print version and bail. *) let print_version ch = - printf "Goblint version: %s\n" Version.goblint; + printf "Goblint version: %s\n" Goblint_build_info.version; printf "Cil version: %s\n" Cil.cilVersion; - printf "Dune profile: %s\n" ConfigProfile.profile; + printf "Dune profile: %s\n" Goblint_build_info.dune_profile; printf "OCaml version: %s\n" Sys.ocaml_version; - printf "OCaml flambda: %s\n" ConfigOcaml.flambda; + printf "OCaml flambda: %s\n" Goblint_build_info.ocaml_flambda; if get_bool "dbg.verbose" then ( printf "Library versions:\n"; List.iter (fun (name, version) -> diff --git a/src/util/sarif.ml b/src/util/sarif.ml index 4374da46d7..7620384cc4 100644 --- a/src/util/sarif.ml +++ b/src/util/sarif.ml @@ -26,7 +26,7 @@ let goblintTool: Tool.t = { fullName = "Goblint static analyser"; informationUri = "https://goblint.in.tum.de/home"; organization = "TUM - i2 and UTartu - SWS"; - version = Version.goblint; + version = Goblint_build_info.version; rules = List.map transformToReportingDescriptor (List.map (fun rule -> rule.name) rules) }; } diff --git a/src/util/tracing.ml b/src/util/tracing.ml index f9dff2c2cf..ad8892c396 100644 --- a/src/util/tracing.ml +++ b/src/util/tracing.ml @@ -10,7 +10,7 @@ open Pretty module Strs = Set.Make (String) -let tracing = ConfigProfile.profile = "trace" +let tracing = Goblint_build_info.dune_profile = "trace" let current_loc = ref locUnknown let next_loc = ref locUnknown diff --git a/src/version.ml b/src/version.ml deleted file mode 100644 index cbe2874608..0000000000 --- a/src/version.ml +++ /dev/null @@ -1,16 +0,0 @@ -let release = "%%VERSION_NUM%%" -let release_commit = "%%VCS_COMMIT_ID%%" - -let goblint = - let commit = ConfigVersion.version in - if BatString.starts_with release "%" then - commit - else ( - let commit = - if commit = "n/a" then (* released archive has no .git *) - release_commit - else - commit - in - Format.sprintf "%s (%s)" release commit - ) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 0e237716fd..fb1604f03e 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -118,7 +118,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Result.Unknown -> "unknown_witness" ); GML.write_metadata g "sourcecodelang" "C"; - GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Version.goblint); + GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Goblint_build_info.version); GML.write_metadata g "specification" (Svcomp.Specification.to_string Task.specification); let programfile = (Node.location (N.cfgnode main_entry)).file in GML.write_metadata g "programfile" programfile; diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index c7106a57b5..72ff21f6bd 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -17,7 +17,7 @@ struct (* let yaml_conf: Yaml.value = Json_repr.convert (module Json_repr.Yojson) (module Json_repr.Ezjsonm) (!GobConfig.json_conf) in *) let producer: Producer.t = { name = "Goblint"; - version = Version.goblint; + version = Goblint_build_info.version; command_line = Some GobSys.command_line; } From 9b728d352169f0eea1e4a21609233413f2ae1c79 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 5 Oct 2023 13:59:19 +0200 Subject: [PATCH 347/628] Set `dest` in `memcpy` to top if `n` doesn't match its size --- src/analyses/base.ml | 85 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index a5b60e8cca..2d779b8d85 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2054,6 +2054,64 @@ struct AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname + let points_to_heap_only ctx ptr = + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a)-> + Queries.AD.for_all (function + | Addr (v, o) -> ctx.ask (Queries.IsHeapVar v) + | _ -> false + ) a + | _ -> false + + let get_size_of_ptr_target ctx ptr = + let intdom_of_int x = + ID.of_int (Cilfacade.ptrdiff_ikind ()) (Z.of_int x) + in + let size_of_type_in_bytes typ = + let typ_size_in_bytes = (bitsSizeOf typ) / 8 in + intdom_of_int typ_size_in_bytes + in + if points_to_heap_only ctx ptr then + (* Ask for BlobSize from the base address (the second component being set to true) in order to avoid BlobSize giving us bot *) + ctx.ask (Queries.BlobSize {exp = ptr; base_address = true}) + else + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a) -> + let pts_list = Queries.AD.elements a in + let pts_elems_to_sizes (addr: Queries.AD.elt) = + begin match addr with + | Addr (v, _) -> + begin match v.vtype with + | TArray (item_typ, _, _) -> + let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in + begin match ctx.ask (Queries.EvalLength ptr) with + | `Lifted arr_len -> + let arr_len_casted = ID.cast_to (Cilfacade.ptrdiff_ikind ()) arr_len in + begin + try `Lifted (ID.mul item_typ_size_in_bytes arr_len_casted) + with IntDomain.ArithmeticOnIntegerBot _ -> `Bot + end + | `Bot -> `Bot + | `Top -> `Top + end + | _ -> + let type_size_in_bytes = size_of_type_in_bytes v.vtype in + `Lifted type_size_in_bytes + end + | _ -> `Top + end + in + (* Map each points-to-set element to its size *) + let pts_sizes = List.map pts_elems_to_sizes pts_list in + (* Take the smallest of all sizes that ptr's contents may have *) + begin match pts_sizes with + | [] -> `Bot + | [x] -> x + | x::xs -> List.fold_left ValueDomainQueries.ID.join x xs + end + | _ -> + (M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let special ctx (lv:lval option) (f: varinfo) (args: exp list) = let invalidate_ret_lv st = match lv with @@ -2073,13 +2131,32 @@ struct let st: store = ctx.local in let gs = ctx.global in let desc = LF.find f in - let memory_copying dst src = + let memory_copying dst src n = + let dest_size = get_size_of_ptr_target ctx dst in + let n_intdom = match n with + | Some exp -> ctx.ask (Queries.EvalInt exp) + | None -> `Bot + in + let dest_size_equal_n = + match dest_size, n_intdom with + | `Top, `Top -> true + | `Bot, `Bot -> true + | `Lifted ds, `Lifted n -> + let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in + let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in + let ds_eq_n = ID.eq casted_ds casted_n in + begin match ID.to_bool ds_eq_n with + | Some b -> b + | None -> false + end + | _, _ -> false + in let dest_a, dest_typ = addr_type_of_exp dst in let src_lval = mkMem ~addr:(Cil.stripCasts src) ~off:NoOffset in let src_typ = eval_lv (Analyses.ask_of_ctx ctx) gs st src_lval |> AD.type_of in (* when src and destination type coincide, take value from the source, otherwise use top *) - let value = if typeSig dest_typ = typeSig src_typ then + let value = if (typeSig dest_typ = typeSig src_typ) && dest_size_equal_n then let src_cast_lval = mkMem ~addr:(Cilfacade.mkCast ~e:src ~newt:(TPtr (dest_typ, []))) ~off:NoOffset in eval_rv (Analyses.ask_of_ctx ctx) gs st (Lval src_cast_lval) else @@ -2140,13 +2217,13 @@ struct let value = VD.zero_init_value dest_typ in set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value | Memcpy { dest = dst; src; n; }, _ -> (* TODO: use n *) - memory_copying dst src + memory_copying dst src (Some n) (* strcpy(dest, src); *) | Strcpy { dest = dst; src; n = None }, _ -> let dest_a, dest_typ = addr_type_of_exp dst in (* when dest surely isn't a string literal, try copying src to dest *) if AD.string_writing_defined dest_a then - memory_copying dst src + memory_copying dst src None else (* else return top (after a warning was issued) *) set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) From 48f2cfedda0a61517a69e012dfc07a08fe3646cb Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 5 Oct 2023 14:00:18 +0200 Subject: [PATCH 348/628] Add test case for UAF due to bad memcpy --- .../74-use_after_free/16-uaf-packed-struct.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/regression/74-use_after_free/16-uaf-packed-struct.c diff --git a/tests/regression/74-use_after_free/16-uaf-packed-struct.c b/tests/regression/74-use_after_free/16-uaf-packed-struct.c new file mode 100644 index 0000000000..e10aa28486 --- /dev/null +++ b/tests/regression/74-use_after_free/16-uaf-packed-struct.c @@ -0,0 +1,40 @@ +// PARAM: --set ana.activated[+] useAfterFree +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char pad1[2]; + unsigned int d; + unsigned char e; + unsigned char pad2[3]; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(12); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + memcpy(p, &d, 4); + if (p->a != 1) { + free(p); + } + if (p->b != 2) {//WARN + free(p);//WARN + } + if (p->c != 3) {//WARN + free(p);//WARN + } + if (p->d != 4) { //WARN + free(p);//WARN + } + free(p);//WARN +} + From 753b5c1661009bbfa6542fd64ca3d6de62231a34 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 5 Oct 2023 14:02:33 +0200 Subject: [PATCH 349/628] Check offsets of dereferenced lvalues as well --- src/analyses/memOutOfBounds.ml | 65 +++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 8a2ca12467..d555db968d 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -122,9 +122,9 @@ struct | x::xs -> List.fold_left VDQ.ID.join x xs end | _ -> - set_mem_safety_flag InvalidDeref; - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; - `Top + (set_mem_safety_flag InvalidDeref; + M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let get_ptr_deref_type ptr_typ = match ptr_typ with @@ -165,6 +165,32 @@ struct with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () end + let rec cil_offs_to_idx ctx typ offs = + match offs with + | NoOffset -> intdom_of_int 0 + | Field (field, o) -> + let field_as_offset = Field (field, NoOffset) in + let bits_offset, _size = GoblintCil.bitsOffset (TComp (field.fcomp, [])) field_as_offset in + let bytes_offset = intdom_of_int (bits_offset / 8) in + let remaining_offset = cil_offs_to_idx ctx field.ftype o in + begin + try ID.add bytes_offset remaining_offset + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + | Index (x, o) -> + begin try + begin match ctx.ask (Queries.EvalInt x) with + | `Top -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + | `Bot -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + | `Lifted eval_x -> + let typ_size_in_bytes = size_of_type_in_bytes typ in + let bytes_offset = ID.mul typ_size_in_bytes eval_x in + let remaining_offset = cil_offs_to_idx ctx typ o in + ID.add bytes_offset remaining_offset + end + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + let check_unknown_addr_deref ctx ptr = let may_contain_unknown_addr = match ctx.ask (Queries.EvalValue ptr) with @@ -245,7 +271,38 @@ struct match lval, is_implicitly_derefed with | (Var _, _), false -> () | (Var v, _), true -> check_no_binop_deref ctx (Lval lval) - | (Mem e, _), _ -> + | (Mem e, o), _ -> + let ptr_deref_type = get_ptr_deref_type @@ typeOf e in + let offs_intdom = begin match ptr_deref_type with + | Some t -> cil_offs_to_idx ctx t o + | None -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end in + let e_size = get_size_of_ptr_target ctx e in + let () = begin match e_size with + | `Top -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is top. Out-of-bounds memory access may occur" d_exp e) + | `Bot -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is bot. Out-of-bounds memory access may occur" d_exp e) + | `Lifted es -> + let casted_es = ID.cast_to (Cilfacade.ptrdiff_ikind ()) es in + let one = intdom_of_int 1 in + let casted_es = ID.sub casted_es one in + let casted_offs = ID.cast_to (Cilfacade.ptrdiff_ikind ()) offs_intdom in + let ptr_size_lt_offs = ID.lt casted_es casted_offs in + let behavior = Undefined MemoryOutOfBoundsAccess in + let cwe_number = 823 in + begin match ID.to_bool ptr_size_lt_offs with + | Some true -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of lval dereference expression is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" ID.pretty casted_es ID.pretty casted_offs) + | Some false -> () + | None -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of lval dereference expression (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_es ID.pretty casted_offs) + end + end in begin match e with | Lval (Var v, _) as lval_exp -> check_no_binop_deref ctx lval_exp | BinOp (binop, e1, e2, t) when binop = PlusPI || binop = MinusPI || binop = IndexPI -> From d68328163e07f228f44f50c0b9b27200ea631284 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 5 Oct 2023 14:02:51 +0200 Subject: [PATCH 350/628] Add regr. test case for OOB due to too large lval offset --- .../77-mem-oob/13-mem-oob-packed-struct.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/regression/77-mem-oob/13-mem-oob-packed-struct.c diff --git a/tests/regression/77-mem-oob/13-mem-oob-packed-struct.c b/tests/regression/77-mem-oob/13-mem-oob-packed-struct.c new file mode 100644 index 0000000000..552cd1bb0b --- /dev/null +++ b/tests/regression/77-mem-oob/13-mem-oob-packed-struct.c @@ -0,0 +1,33 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d; +} __attribute__((packed)); + +int main(void) +{ + struct A *p; + p = malloc(2); + p->a = 1; + if (p->a != 1) { + free(p); + } + p->b = 2; + if (p->b != 2) { + free(p); + } + p->c = 3; + if (p->c != 3) { + free(p); + } + p->d = 4; //WARN + if (p->d != 4) {//WARN + free(p); + } + free(p); +} + From d723fdef0bf9e17625c141ed44a0e9d271e0609d Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 5 Oct 2023 15:48:41 +0300 Subject: [PATCH 351/628] Extract widely used modules to common dune library --- src/{util => common}/afterConfig.ml | 0 src/{framework => common}/analysisState.ml | 0 src/{cdomains => common}/basetype.ml | 0 src/{util => common}/cilType.ml | 0 src/{util => common}/cilfacade.ml | 0 src/{util => common}/cilfacade0.ml | 0 src/{framework => common}/controlSpecC.ml | 0 src/{framework => common}/controlSpecC.mli | 0 src/common/dune | 28 ++++++++++++++++++++++ src/{framework => common}/edge.ml | 0 src/{util => common}/gobConfig.ml | 0 src/{util => common}/gobFormat.ml | 0 src/{util => common}/jsonSchema.ml | 0 src/{domains => common}/lattice.ml | 0 src/{util => common}/lazyEval.ml | 0 src/{util => common}/messageCategory.ml | 0 src/{util => common}/messageUtil.ml | 0 src/{util => common}/messages.ml | 0 src/{framework => common}/myCFG.ml | 0 src/{domains => common}/myCheck.ml | 0 src/{framework => common}/node.ml | 0 src/{framework => common}/node0.ml | 0 src/{util => common}/options.ml | 0 src/{util => common}/options.schema.json | 0 src/{domains => common}/printable.ml | 0 src/{util => common}/resettableLazy.ml | 0 src/{util => common}/resettableLazy.mli | 0 src/{util => common}/richVarinfo.ml | 0 src/{util => common}/richVarinfo.mli | 0 src/{util => common}/timing.ml | 0 src/{util => common}/tracing.ml | 0 src/{incremental => common}/updateCil0.ml | 0 src/{util => common}/xmlUtil.ml | 0 src/dune | 3 +-- 34 files changed, 29 insertions(+), 2 deletions(-) rename src/{util => common}/afterConfig.ml (100%) rename src/{framework => common}/analysisState.ml (100%) rename src/{cdomains => common}/basetype.ml (100%) rename src/{util => common}/cilType.ml (100%) rename src/{util => common}/cilfacade.ml (100%) rename src/{util => common}/cilfacade0.ml (100%) rename src/{framework => common}/controlSpecC.ml (100%) rename src/{framework => common}/controlSpecC.mli (100%) create mode 100644 src/common/dune rename src/{framework => common}/edge.ml (100%) rename src/{util => common}/gobConfig.ml (100%) rename src/{util => common}/gobFormat.ml (100%) rename src/{util => common}/jsonSchema.ml (100%) rename src/{domains => common}/lattice.ml (100%) rename src/{util => common}/lazyEval.ml (100%) rename src/{util => common}/messageCategory.ml (100%) rename src/{util => common}/messageUtil.ml (100%) rename src/{util => common}/messages.ml (100%) rename src/{framework => common}/myCFG.ml (100%) rename src/{domains => common}/myCheck.ml (100%) rename src/{framework => common}/node.ml (100%) rename src/{framework => common}/node0.ml (100%) rename src/{util => common}/options.ml (100%) rename src/{util => common}/options.schema.json (100%) rename src/{domains => common}/printable.ml (100%) rename src/{util => common}/resettableLazy.ml (100%) rename src/{util => common}/resettableLazy.mli (100%) rename src/{util => common}/richVarinfo.ml (100%) rename src/{util => common}/richVarinfo.mli (100%) rename src/{util => common}/timing.ml (100%) rename src/{util => common}/tracing.ml (100%) rename src/{incremental => common}/updateCil0.ml (100%) rename src/{util => common}/xmlUtil.ml (100%) diff --git a/src/util/afterConfig.ml b/src/common/afterConfig.ml similarity index 100% rename from src/util/afterConfig.ml rename to src/common/afterConfig.ml diff --git a/src/framework/analysisState.ml b/src/common/analysisState.ml similarity index 100% rename from src/framework/analysisState.ml rename to src/common/analysisState.ml diff --git a/src/cdomains/basetype.ml b/src/common/basetype.ml similarity index 100% rename from src/cdomains/basetype.ml rename to src/common/basetype.ml diff --git a/src/util/cilType.ml b/src/common/cilType.ml similarity index 100% rename from src/util/cilType.ml rename to src/common/cilType.ml diff --git a/src/util/cilfacade.ml b/src/common/cilfacade.ml similarity index 100% rename from src/util/cilfacade.ml rename to src/common/cilfacade.ml diff --git a/src/util/cilfacade0.ml b/src/common/cilfacade0.ml similarity index 100% rename from src/util/cilfacade0.ml rename to src/common/cilfacade0.ml diff --git a/src/framework/controlSpecC.ml b/src/common/controlSpecC.ml similarity index 100% rename from src/framework/controlSpecC.ml rename to src/common/controlSpecC.ml diff --git a/src/framework/controlSpecC.mli b/src/common/controlSpecC.mli similarity index 100% rename from src/framework/controlSpecC.mli rename to src/common/controlSpecC.mli diff --git a/src/common/dune b/src/common/dune new file mode 100644 index 0000000000..03a93a3030 --- /dev/null +++ b/src/common/dune @@ -0,0 +1,28 @@ +(include_subdirs no) + +(library + (name goblint_common) + (public_name goblint.common) + (wrapped false) ; TODO: wrap + (libraries + batteries + zarith + goblint_std + goblint-cil + fpath + yojson + json-data-encoding + cpu + goblint_timing + goblint_build_info + goblint.sites + qcheck-core.runner) + (flags :standard -open Goblint_std) + (preprocess + (pps + ppx_deriving.std + ppx_deriving_hash + ppx_deriving_yojson + ppx_blob)) + (preprocessor_deps (file options.schema.json))) + diff --git a/src/framework/edge.ml b/src/common/edge.ml similarity index 100% rename from src/framework/edge.ml rename to src/common/edge.ml diff --git a/src/util/gobConfig.ml b/src/common/gobConfig.ml similarity index 100% rename from src/util/gobConfig.ml rename to src/common/gobConfig.ml diff --git a/src/util/gobFormat.ml b/src/common/gobFormat.ml similarity index 100% rename from src/util/gobFormat.ml rename to src/common/gobFormat.ml diff --git a/src/util/jsonSchema.ml b/src/common/jsonSchema.ml similarity index 100% rename from src/util/jsonSchema.ml rename to src/common/jsonSchema.ml diff --git a/src/domains/lattice.ml b/src/common/lattice.ml similarity index 100% rename from src/domains/lattice.ml rename to src/common/lattice.ml diff --git a/src/util/lazyEval.ml b/src/common/lazyEval.ml similarity index 100% rename from src/util/lazyEval.ml rename to src/common/lazyEval.ml diff --git a/src/util/messageCategory.ml b/src/common/messageCategory.ml similarity index 100% rename from src/util/messageCategory.ml rename to src/common/messageCategory.ml diff --git a/src/util/messageUtil.ml b/src/common/messageUtil.ml similarity index 100% rename from src/util/messageUtil.ml rename to src/common/messageUtil.ml diff --git a/src/util/messages.ml b/src/common/messages.ml similarity index 100% rename from src/util/messages.ml rename to src/common/messages.ml diff --git a/src/framework/myCFG.ml b/src/common/myCFG.ml similarity index 100% rename from src/framework/myCFG.ml rename to src/common/myCFG.ml diff --git a/src/domains/myCheck.ml b/src/common/myCheck.ml similarity index 100% rename from src/domains/myCheck.ml rename to src/common/myCheck.ml diff --git a/src/framework/node.ml b/src/common/node.ml similarity index 100% rename from src/framework/node.ml rename to src/common/node.ml diff --git a/src/framework/node0.ml b/src/common/node0.ml similarity index 100% rename from src/framework/node0.ml rename to src/common/node0.ml diff --git a/src/util/options.ml b/src/common/options.ml similarity index 100% rename from src/util/options.ml rename to src/common/options.ml diff --git a/src/util/options.schema.json b/src/common/options.schema.json similarity index 100% rename from src/util/options.schema.json rename to src/common/options.schema.json diff --git a/src/domains/printable.ml b/src/common/printable.ml similarity index 100% rename from src/domains/printable.ml rename to src/common/printable.ml diff --git a/src/util/resettableLazy.ml b/src/common/resettableLazy.ml similarity index 100% rename from src/util/resettableLazy.ml rename to src/common/resettableLazy.ml diff --git a/src/util/resettableLazy.mli b/src/common/resettableLazy.mli similarity index 100% rename from src/util/resettableLazy.mli rename to src/common/resettableLazy.mli diff --git a/src/util/richVarinfo.ml b/src/common/richVarinfo.ml similarity index 100% rename from src/util/richVarinfo.ml rename to src/common/richVarinfo.ml diff --git a/src/util/richVarinfo.mli b/src/common/richVarinfo.mli similarity index 100% rename from src/util/richVarinfo.mli rename to src/common/richVarinfo.mli diff --git a/src/util/timing.ml b/src/common/timing.ml similarity index 100% rename from src/util/timing.ml rename to src/common/timing.ml diff --git a/src/util/tracing.ml b/src/common/tracing.ml similarity index 100% rename from src/util/tracing.ml rename to src/common/tracing.ml diff --git a/src/incremental/updateCil0.ml b/src/common/updateCil0.ml similarity index 100% rename from src/incremental/updateCil0.ml rename to src/common/updateCil0.ml diff --git a/src/util/xmlUtil.ml b/src/common/xmlUtil.ml similarity index 100% rename from src/util/xmlUtil.ml rename to src/common/xmlUtil.ml diff --git a/src/dune b/src/dune index 5fdf58a5b2..df19f85340 100644 --- a/src/dune +++ b/src/dune @@ -7,7 +7,7 @@ (name goblint_lib) (public_name goblint.lib) (modules :standard \ goblint mainspec privPrecCompare apronPrecCompare messagesCompare) - (libraries goblint.sites goblint.build-info goblint-cil.all-features batteries.unthreaded qcheck-core.runner sha json-data-encoding jsonrpc cpu arg-complete fpath yaml yaml.unix uuidm goblint_timing catapult goblint_backtrace fileutils goblint_std + (libraries goblint.sites goblint.build-info goblint-cil.all-features batteries.unthreaded qcheck-core.runner sha json-data-encoding jsonrpc cpu arg-complete fpath yaml yaml.unix uuidm goblint_timing catapult goblint_backtrace fileutils goblint_std goblint_common ; Conditionally compile based on whether apron optional dependency is installed or not. ; Alternative dependencies seem like the only way to optionally depend on optional dependencies. ; See: https://dune.readthedocs.io/en/stable/concepts.html#alternative-dependencies. @@ -61,7 +61,6 @@ (ocamlopt_flags :standard -no-float-const-prop) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson ppx_blob)) - (preprocessor_deps (file util/options.schema.json)) (instrumentation (backend bisect_ppx)) ) From 22e4df53b11aa16dc676a690f131321f2112523b Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 5 Oct 2023 15:24:47 +0200 Subject: [PATCH 352/628] Fix exceptions due to ID ops --- src/analyses/base.ml | 6 +++++- src/analyses/memOutOfBounds.ml | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 2d779b8d85..b6cc5c29cf 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2144,7 +2144,11 @@ struct | `Lifted ds, `Lifted n -> let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in - let ds_eq_n = ID.eq casted_ds casted_n in + let ds_eq_n = + begin try ID.eq casted_ds casted_n + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + in begin match ID.to_bool ds_eq_n with | Some b -> b | None -> false diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index d555db968d..68dae1d89a 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -184,7 +184,8 @@ struct | `Bot -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () | `Lifted eval_x -> let typ_size_in_bytes = size_of_type_in_bytes typ in - let bytes_offset = ID.mul typ_size_in_bytes eval_x in + let casted_eval_x = ID.cast_to (Cilfacade.ptrdiff_ikind ()) eval_x in + let bytes_offset = ID.mul typ_size_in_bytes casted_eval_x in let remaining_offset = cil_offs_to_idx ctx typ o in ID.add bytes_offset remaining_offset end @@ -290,7 +291,11 @@ struct let one = intdom_of_int 1 in let casted_es = ID.sub casted_es one in let casted_offs = ID.cast_to (Cilfacade.ptrdiff_ikind ()) offs_intdom in - let ptr_size_lt_offs = ID.lt casted_es casted_offs in + let ptr_size_lt_offs = + begin try ID.lt casted_es casted_offs + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + in let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in begin match ID.to_bool ptr_size_lt_offs with From 94307d03c47d63621ade9b833c0be35bb23bee89 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 5 Oct 2023 17:27:55 +0300 Subject: [PATCH 353/628] Add option ana.race.call --- conf/svcomp.json | 3 ++- src/domains/access.ml | 2 ++ src/util/options.schema.json | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index f51c7a52ee..df624e4b83 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -70,7 +70,8 @@ } }, "race": { - "free": false + "free": false, + "call": false }, "autotune": { "enabled": true, diff --git a/src/domains/access.ml b/src/domains/access.ml index 8907ccbc32..f243b85bda 100644 --- a/src/domains/access.ml +++ b/src/domains/access.ml @@ -444,6 +444,8 @@ let may_race A.{kind; acc; _} A.{kind=kind2; acc=acc2; _} = false (* two read/read accesses do not race *) else if not (get_bool "ana.race.free") && (kind = Free || kind2 = Free) then false + else if not (get_bool "ana.race.call") && (kind = Call || kind2 = Call) then + false else if not (MCPAccess.A.may_race acc acc2) then false (* analysis-specific information excludes race *) else diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 1b9c7d3fd5..33de069b38 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -1002,6 +1002,12 @@ "type": "boolean", "default": true }, + "call": { + "title": "ana.race.call", + "description": "Report races for thread-unsafe function calls.", + "type": "boolean", + "default": true + }, "direct-arithmetic": { "title": "ana.race.direct-arithmetic", "description": "Collect and distribute direct (i.e. not in a field) accesses to arithmetic types.", From b9c213441f2ef03ce02173fa323650ebe234c080 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:54:55 +0300 Subject: [PATCH 354/628] Fix size check in `memory_copying` Co-authored-by: Michael Schwarz --- src/analyses/base.ml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index b6cc5c29cf..6aaf25944e 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2139,21 +2139,16 @@ struct in let dest_size_equal_n = match dest_size, n_intdom with - | `Top, `Top -> true - | `Bot, `Bot -> true | `Lifted ds, `Lifted n -> let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in let ds_eq_n = begin try ID.eq casted_ds casted_n - with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + with IntDomain.ArithmeticOnIntegerBot _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () end in - begin match ID.to_bool ds_eq_n with - | Some b -> b - | None -> false - end - | _, _ -> false + Option.value ~default:false ID.to_bool ds_eq_n + | _ -> false in let dest_a, dest_typ = addr_type_of_exp dst in let src_lval = mkMem ~addr:(Cil.stripCasts src) ~off:NoOffset in From 625e90b308159da7407f0fef01cd863bfc662d36 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:56:11 +0300 Subject: [PATCH 355/628] Use `Option.map_default` instead of `match` Co-authored-by: Michael Schwarz --- src/analyses/base.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 6aaf25944e..cc5ddc9c9d 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2133,10 +2133,7 @@ struct let desc = LF.find f in let memory_copying dst src n = let dest_size = get_size_of_ptr_target ctx dst in - let n_intdom = match n with - | Some exp -> ctx.ask (Queries.EvalInt exp) - | None -> `Bot - in + let n_intdom = Option.map_default (fun exp -> ctx.ask (Queries.EvalInt exp)) `Bot n in let dest_size_equal_n = match dest_size, n_intdom with | `Lifted ds, `Lifted n -> From fbab25ec49ecee2727f9675e36e5b3116b4c1d91 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:56:59 +0300 Subject: [PATCH 356/628] Use `_` in place of unused offset in lambda Co-authored-by: Michael Schwarz --- src/analyses/base.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index cc5ddc9c9d..df67d1afe4 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2058,7 +2058,7 @@ struct match ctx.ask (Queries.MayPointTo ptr) with | a when not (Queries.AD.is_top a)-> Queries.AD.for_all (function - | Addr (v, o) -> ctx.ask (Queries.IsHeapVar v) + | Addr (v, _) -> ctx.ask (Queries.IsHeapVar v) | _ -> false ) a | _ -> false From 91aeee732f1f97afdb406e189176f22c46049ff1 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:57:46 +0300 Subject: [PATCH 357/628] Set `Cabs2cil.addNestedScopeAttr` based on the Goblint config option Co-authored-by: Michael Schwarz --- src/util/cilfacade.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 432b623464..3b00365abf 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -41,8 +41,7 @@ let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); Cil.gnu89inline := get_bool "cil.gnu89inline"; - if get_bool "cil.addNestedScopeAttr" then - Cabs2cil.addNestedScopeAttr := true + Cabs2cil.addNestedScopeAttr := get_bool "cil.addNestedScopeAttr"; let init () = initCIL (); From 992e5c0b183326d8a3acc102fd40c99e110c140d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:04:44 +0200 Subject: [PATCH 358/628] Remove extra semicolon --- src/util/cilfacade.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 3b00365abf..ba57074e5a 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -41,7 +41,7 @@ let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); Cil.gnu89inline := get_bool "cil.gnu89inline"; - Cabs2cil.addNestedScopeAttr := get_bool "cil.addNestedScopeAttr"; + Cabs2cil.addNestedScopeAttr := get_bool "cil.addNestedScopeAttr" let init () = initCIL (); From cc351e04e745b11aaab409a60b7d2dc7a7c32eab Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:05:00 +0200 Subject: [PATCH 359/628] Use `Option.default` in place of `Option.value` --- src/analyses/base.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index df67d1afe4..f5da725226 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2144,7 +2144,7 @@ struct with IntDomain.ArithmeticOnIntegerBot _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () end in - Option.value ~default:false ID.to_bool ds_eq_n + Option.default false (ID.to_bool ds_eq_n) | _ -> false in let dest_a, dest_typ = addr_type_of_exp dst in From de0220baf762f69ba6f0da19299ce568b243bed4 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Fri, 6 Oct 2023 23:09:46 +0200 Subject: [PATCH 360/628] Use `AD.exists` to warn about non-local vars in address set instead of using `AD.iter` --- src/analyses/base.ml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index f5da725226..908dc88401 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1052,17 +1052,14 @@ struct AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" ); - (* Warn if any of the addresses contains a non-local variable *) - AD.iter (function - | AD.Addr.Addr (v,o) -> - if not (CPA.mem v st.cpa) && not (is_global a v) then ( - (* TODO: Not the smartest move to set the global flag within an iter *) - (* TODO: We can resort to using AD.exists instead *) - AnalysisStateUtil.set_mem_safety_flag InvalidDeref; - M.warn "lval %a points to non-local variable %a. Invalid pointer dereference may occur" d_lval lval CilType.Varinfo.pretty v - ) - | _ -> () - ) adr + (* Warn if any of the addresses contains a non-local and non-global variable *) + if AD.exists (function + | AD.Addr.Addr (v, _) -> not (CPA.mem v st.cpa) && not (is_global a v) + | _ -> false + ) adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval + ) ); AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr | _ -> From fd5237a6dfdd68f1cd6791030dd43227e9ed77fc Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 11:40:54 +0300 Subject: [PATCH 361/628] Add 68-longjmp/56-longjmp-top extracted from concrat --- tests/regression/68-longjmp/56-longjmp-top.c | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/regression/68-longjmp/56-longjmp-top.c diff --git a/tests/regression/68-longjmp/56-longjmp-top.c b/tests/regression/68-longjmp/56-longjmp-top.c new file mode 100644 index 0000000000..4a12a43792 --- /dev/null +++ b/tests/regression/68-longjmp/56-longjmp-top.c @@ -0,0 +1,21 @@ +// Extracted from concrat/pigz. +#include +#include +#include + +pthread_key_t buf_key; + +int main() { + jmp_buf buf; + pthread_setspecific(buf_key, &buf); + + if (!setjmp(buf)) { + jmp_buf *buf_ptr; + buf_ptr = pthread_getspecific(buf_key); + longjmp(*buf_ptr, 1); // TODO NO CRASH: problem?! + } + else { + __goblint_check(1); // reachable + } + return 0; +} From 2224e86ce5e770cedd4558cfff6379471424e743 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 11:46:24 +0300 Subject: [PATCH 362/628] Fix longjmp crash on Uninitialized --- src/analyses/base.ml | 11 +++++++++-- tests/regression/68-longjmp/56-longjmp-top.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 7b87d3ff51..2fda2540e8 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1217,9 +1217,16 @@ struct if copied then M.warn ~category:(Behavior (Undefined Other)) "The jump buffer %a contains values that were copied here instead of being set by setjmp. This is Undefined Behavior." d_exp e; x - | y -> failwith (GobPretty.sprintf "problem?! is %a %a:\n state is %a" CilType.Exp.pretty e VD.pretty y D.pretty ctx.local) + | Top + | Bot -> + JmpBufDomain.JmpBufSet.top () + | y -> + M.debug ~category:Imprecise "EvalJmpBuf %a is %a, not JmpBuf." CilType.Exp.pretty e VD.pretty y; + JmpBufDomain.JmpBufSet.top () end - | _ -> failwith "problem?!" + | _ -> + M.debug ~category:Imprecise "EvalJmpBuf is not Address"; + JmpBufDomain.JmpBufSet.top () end | Q.EvalInt e -> query_evalint (Analyses.ask_of_ctx ctx) ctx.global ctx.local e diff --git a/tests/regression/68-longjmp/56-longjmp-top.c b/tests/regression/68-longjmp/56-longjmp-top.c index 4a12a43792..4d57b42fd3 100644 --- a/tests/regression/68-longjmp/56-longjmp-top.c +++ b/tests/regression/68-longjmp/56-longjmp-top.c @@ -12,7 +12,7 @@ int main() { if (!setjmp(buf)) { jmp_buf *buf_ptr; buf_ptr = pthread_getspecific(buf_key); - longjmp(*buf_ptr, 1); // TODO NO CRASH: problem?! + longjmp(*buf_ptr, 1); // NO CRASH: problem?! } else { __goblint_check(1); // reachable From 8468a5a676fae48a82e0284ea13170d0cefa935c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 12:12:58 +0300 Subject: [PATCH 363/628] Fix too broad try block in BaseInvariant Caused Invalid_argument("Cilfacade.get_fkind: non-float type int ") before, even though integer case is checked first, but something else in it raises. --- src/analyses/baseInvariant.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 70c6ed9101..72e00efbb1 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -805,15 +805,15 @@ struct | BinOp ((Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr), _, _, _) -> true | _ -> false in - try - let ik = Cilfacade.get_ikind_exp exp in + match Cilfacade.get_ikind_exp exp with + | ik -> let itv = if not tv || is_cmp exp then (* false is 0, but true can be anything that is not 0, except for comparisons which yield 1 *) ID.of_bool ik tv (* this will give 1 for true which is only ok for comparisons *) else ID.of_excl_list ik [BI.zero] (* Lvals, Casts, arithmetic operations etc. should work with true = non_zero *) in inv_exp (Int itv) exp st - with Invalid_argument _ -> + | exception Invalid_argument _ -> let fk = Cilfacade.get_fkind_exp exp in let ftv = if not tv then (* false is 0, but true can be anything that is not 0, except for comparisons which yield 1 *) FD.of_const fk 0. From 56cf37e347039f9a2f12cfd360f0dece5e583c5a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 12:50:22 +0300 Subject: [PATCH 364/628] Add missing library functions for concrat/dnspod-sr --- src/analyses/libraryFunctions.ml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 1c509e7660..8566cd6b0c 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -265,6 +265,9 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("access", unknown [drop "pathname" [r]; drop "mode" []]); ("ttyname", unknown ~attrs:[ThreadUnsafe] [drop "fd" []]); ("shm_open", unknown [drop "name" [r]; drop "oflag" []; drop "mode" []]); + ("shmget", unknown [drop "key" []; drop "size" []; drop "shmflag" []]); + ("shmat", unknown [drop "shmid" []; drop "shmaddr" []; drop "shmflag" []]) (* TODO: shmaddr? *); + ("shmdt", unknown [drop "shmaddr" []]) (* TODO: shmaddr? *); ("sched_get_priority_max", unknown [drop "policy" []]); ("mprotect", unknown [drop "addr" []; drop "len" []; drop "prot" []]); ("ftime", unknown [drop "tp" [w]]); @@ -364,6 +367,9 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("sigdelset", unknown [drop "set" [r; w]; drop "signum" []]); ("sigismember", unknown [drop "set" [r]; drop "signum" []]); ("sigprocmask", unknown [drop "how" []; drop "set" [r]; drop "oldset" [w]]); + ("sigwait", unknown [drop "set" [r]; drop "sig" [w]]); + ("sigwaitinfo", unknown [drop "set" [r]; drop "info" [w]]); + ("sigtimedwait", unknown [drop "set" [r]; drop "info" [w]; drop "timeout" [r]]); ("fork", unknown []); ("dlopen", unknown [drop "filename" [r]; drop "flag" []]); ("dlerror", unknown ~attrs:[ThreadUnsafe] []); @@ -566,6 +572,7 @@ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atoq", unknown [drop "nptr" [r]]); ("strchrnul", unknown [drop "s" [r]; drop "c" []]); ("getdtablesize", unknown []); + ("daemon", unknown [drop "nochdir" []; drop "noclose" []]); ] let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ @@ -1135,7 +1142,6 @@ let invalidate_actions = [ "umount", readsAll;(*safe*) "scandir", writes [1;3;4];(*keep [1;3;4]*) "unlink", readsAll;(*safe*) - "sigwait", writesAllButFirst 1 readsAll;(*drop 1*) "bindtextdomain", readsAll;(*safe*) "textdomain", readsAll;(*safe*) "dcgettext", readsAll;(*safe*) From a13e2b921268d7b4f894494a32424ed952c4b145 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 12:54:12 +0300 Subject: [PATCH 365/628] Add mremap library function for concrat/kona --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 8566cd6b0c..87534e97bb 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -589,6 +589,7 @@ let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__xpg_basename", unknown [drop "path" [r]]); ("ptrace", unknown (drop "request" [] :: VarArgs (drop' [r_deep; w_deep]))); (* man page has 4 arguments, but header has varargs and real-world programs may call with <4 *) ("madvise", unknown [drop "addr" []; drop "length" []; drop "advice" []]); + ("mremap", unknown (drop "old_address" [] :: drop "old_size" [] :: drop "new_size" [] :: drop "flags" [] :: VarArgs (drop "new_address" []))); ("inotify_init1", unknown [drop "flags" []]); ("inotify_add_watch", unknown [drop "fd" []; drop "pathname" [r]; drop "mask" []]); ("inotify_rm_watch", unknown [drop "fd" []; drop "wd" []]); From 530781376bfc10281fd0a3451e7bb683d3e28141 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:03:11 +0300 Subject: [PATCH 366/628] Add missing library functions for concrat/lmdb --- src/analyses/libraryFunctions.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 87534e97bb..a1a79f5f5c 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -246,6 +246,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("mkfifo", unknown [drop "pathname" [r]; drop "mode" []]); ("ntohs", unknown [drop "netshort" []]); ("alarm", unknown [drop "seconds" []]); + ("pread", unknown [drop "fd" []; drop "buf" [w]; drop "count" []; drop "offset" []]); ("pwrite", unknown [drop "fd" []; drop "buf" [r]; drop "count" []; drop "offset" []]); ("hstrerror", unknown [drop "err" []]); ("inet_ntoa", unknown ~attrs:[ThreadUnsafe] [drop "in" []]); @@ -379,6 +380,8 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("uname", unknown [drop "buf" [w_deep]]); ("strcasecmp", unknown [drop "s1" [r]; drop "s2" [r]]); ("strncasecmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); + ("fsync", unknown [drop "fd" []]); + ("fdatasync", unknown [drop "fd" []]); ] (** Pthread functions. *) @@ -443,6 +446,10 @@ let pthread_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("pthread_attr_setschedpolicy", unknown [drop "attr" [r; w]; drop "policy" []]); ("pthread_condattr_init", unknown [drop "attr" [w]]); ("pthread_condattr_setclock", unknown [drop "attr" [w]; drop "clock_id" []]); + ("pthread_mutexattr_getpshared", unknown [drop "attr" [r]; drop "pshared" [w]]); + ("pthread_mutexattr_setpshared", unknown [drop "attr" [w]; drop "pshared" []]); + ("pthread_mutexattr_getrobust", unknown [drop "attr" [r]; drop "pshared" [w]]); + ("pthread_mutexattr_setrobust", unknown [drop "attr" [w]; drop "pshared" []]); ("pthread_mutexattr_destroy", unknown [drop "attr" [f]]); ("pthread_attr_setschedparam", unknown [drop "attr" [r; w]; drop "param" [r]]); ("pthread_setaffinity_np", unknown [drop "thread" []; drop "cpusetsize" []; drop "cpuset" [r]]); @@ -590,12 +597,15 @@ let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("ptrace", unknown (drop "request" [] :: VarArgs (drop' [r_deep; w_deep]))); (* man page has 4 arguments, but header has varargs and real-world programs may call with <4 *) ("madvise", unknown [drop "addr" []; drop "length" []; drop "advice" []]); ("mremap", unknown (drop "old_address" [] :: drop "old_size" [] :: drop "new_size" [] :: drop "flags" [] :: VarArgs (drop "new_address" []))); + ("msync", unknown [drop "addr" []; drop "len" []; drop "flags" []]); ("inotify_init1", unknown [drop "flags" []]); ("inotify_add_watch", unknown [drop "fd" []; drop "pathname" [r]; drop "mask" []]); ("inotify_rm_watch", unknown [drop "fd" []; drop "wd" []]); ("fts_open", unknown [drop "path_argv" [r_deep]; drop "options" []; drop "compar" [s]]); (* TODO: use Call instead of Spawn *) ("fts_read", unknown [drop "ftsp" [r_deep; w_deep]]); ("fts_close", unknown [drop "ftsp" [f_deep]]); + ("statfs", unknown [drop "path" [r]; drop "buf" [w]]); + ("fstatfs", unknown [drop "fd" []; drop "buf" [w]]); ] let big_kernel_lock = AddrOf (Cil.var (Cilfacade.create_var (makeGlobalVar "[big kernel lock]" intType))) @@ -1134,7 +1144,6 @@ let invalidate_actions = [ "lstat__extinline", writesAllButFirst 1 readsAll;(*drop 1*) "umount2", readsAll;(*safe*) "waitpid", readsAll;(*safe*) - "statfs", writes [1;3;4];(*keep [1;3;4]*) "mount", readsAll;(*safe*) "__open_alias", readsAll;(*safe*) "__open_2", readsAll;(*safe*) From 25ef4ce6f33be1406b9af3e0c8ca1ed3a20e0474 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:12:07 +0300 Subject: [PATCH 367/628] Add missing library functions for concrat/minimap2 --- src/analyses/libraryFunctions.ml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index a1a79f5f5c..af96e10c06 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -42,6 +42,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("getc", unknown [drop "stream" [r_deep; w_deep]]); ("fgets", unknown [drop "str" [w]; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fopen", unknown [drop "pathname" [r]; drop "mode" [r]]); + ("freopen", unknown [drop "pathname" [r]; drop "mode" [r]; drop "stream" [r_deep; w_deep]]); ("printf", unknown (drop "format" [r] :: VarArgs (drop' [r]))); ("fprintf", unknown (drop "stream" [r_deep; w_deep] :: drop "format" [r] :: VarArgs (drop' [r]))); ("sprintf", unknown (drop "buffer" [w] :: drop "format" [r] :: VarArgs (drop' [r]))); @@ -382,6 +383,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("strncasecmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); ("fsync", unknown [drop "fd" []]); ("fdatasync", unknown [drop "fd" []]); + ("getrusage", unknown [drop "who" []; drop "usage" [w]]); ] (** Pthread functions. *) @@ -987,6 +989,10 @@ let zlib_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("inflateInit2", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []]); ("inflateInit2_", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []; drop "version" [r]; drop "stream_size" []]); ("inflateEnd", unknown [drop "strm" [f_deep]]); + ("gzopen", unknown [drop "path" [r]; drop "mode" [r]]); + ("gzdopen", unknown [drop "fd" []; drop "mode" [r]]); + ("gzread", unknown [drop "file" [r_deep; w_deep]; drop "buf" [w]; drop "len" []]); + ("gzclose", unknown [drop "file" [f_deep]]); ] let liblzma_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ From 9f614ebbd474a0c8b9696a39cbd63620e24e3ae4 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:21:03 +0300 Subject: [PATCH 368/628] Add missing library functions for concrat/phpspy --- src/analyses/libraryFunctions.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index af96e10c06..c795c04084 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -111,6 +111,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("vprintf", unknown [drop "format" [r]; drop "vlist" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) ("vfprintf", unknown [drop "stream" [r_deep; w_deep]; drop "format" [r]; drop "vlist" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) ("vsprintf", unknown [drop "buffer" [w]; drop "format" [r]; drop "vlist" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) + ("asprintf", unknown (drop "strp" [w] :: drop "format" [r] :: VarArgs (drop' [r_deep]))); (* TODO: glibc section? *) ("vasprintf", unknown [drop "strp" [w]; drop "format" [r]; drop "ap" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) ("vsnprintf", unknown [drop "str" [w]; drop "size" []; drop "format" [r]; drop "ap" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) ("mktime", unknown [drop "tm" [r;w]]); @@ -339,6 +340,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("execl", unknown (drop "path" [r] :: drop "arg" [r] :: VarArgs (drop' [r]))); ("statvfs", unknown [drop "path" [r]; drop "buf" [w]]); ("readlink", unknown [drop "path" [r]; drop "buf" [w]; drop "bufsz" []]); + ("wcwidth", unknown [drop "c" []]); ("wcswidth", unknown [drop "s" [r]; drop "n" []]); ("link", unknown [drop "oldpath" [r]; drop "newpath" [r]]); ("renameat", unknown [drop "olddirfd" []; drop "oldpath" [r]; drop "newdirfd" []; drop "newpath" [r]]); @@ -518,6 +520,12 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__atomic_clear", unknown [drop "ptr" [w]; drop "memorder" []]); ("__atomic_compare_exchange_n", unknown [drop "ptr" [r; w]; drop "expected" [r; w]; drop "desired" []; drop "weak" []; drop "success_memorder" []; drop "failure_memorder" []]); ("__atomic_compare_exchange", unknown [drop "ptr" [r; w]; drop "expected" [r; w]; drop "desired" [r]; drop "weak" []; drop "success_memorder" []; drop "failure_memorder" []]); + ("__atomic_add_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); + ("__atomic_sub_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); + ("__atomic_and_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); + ("__atomic_xor_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); + ("__atomic_or_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); + ("__atomic_nand_fetch", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); ("__atomic_fetch_add", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); ("__atomic_fetch_sub", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); ("__atomic_fetch_and", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); @@ -608,6 +616,8 @@ let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fts_close", unknown [drop "ftsp" [f_deep]]); ("statfs", unknown [drop "path" [r]; drop "buf" [w]]); ("fstatfs", unknown [drop "fd" []; drop "buf" [w]]); + ("cfmakeraw", unknown [drop "termios" [r; w]]); + ("process_vm_readv", unknown [drop "pid" []; drop "local_iov" [w_deep]; drop "liovcnt" []; drop "remote_iov" []; drop "riovcnt" []; drop "flags" []]); ] let big_kernel_lock = AddrOf (Cil.var (Cilfacade.create_var (makeGlobalVar "[big kernel lock]" intType))) From c22250889672d27f11aa99a33593218a70502bad Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:22:49 +0300 Subject: [PATCH 369/628] Add alphasort library function for concrat/ProcDump-for-Linux --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index c795c04084..2ea99cdcaa 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -386,6 +386,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fsync", unknown [drop "fd" []]); ("fdatasync", unknown [drop "fd" []]); ("getrusage", unknown [drop "who" []; drop "usage" [w]]); + ("alphasort", unknown [drop "a" [r]; drop "b" [r]]); ] (** Pthread functions. *) From 969d3156b879ba6a22f3d752945d320364e917e6 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:43:02 +0300 Subject: [PATCH 370/628] Add missing library functions for concrat/Remotery --- src/analyses/libraryFunctions.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 2ea99cdcaa..1247a66497 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -395,6 +395,7 @@ let pthread_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("pthread_exit", special [__ "retval" []] @@ fun retval -> ThreadExit { ret_val = retval }); (* Doesn't dereference the void* itself, but just passes to pthread_join. *) ("pthread_join", special [__ "thread" []; __ "retval" [w]] @@ fun thread retval -> ThreadJoin {thread; ret_var = retval}); ("pthread_kill", unknown [drop "thread" []; drop "sig" []]); + ("pthread_equal", unknown [drop "t1" []; drop "t2" []]); ("pthread_cond_init", unknown [drop "cond" [w]; drop "attr" [r]]); ("__pthread_cond_init", unknown [drop "cond" [w]; drop "attr" [r]]); ("pthread_cond_signal", special [__ "cond" []] @@ fun cond -> Signal cond); @@ -535,6 +536,7 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__atomic_fetch_nand", unknown [drop "ptr" [r; w]; drop "val" []; drop "memorder" []]); ("__atomic_test_and_set", unknown [drop "ptr" [r; w]; drop "memorder" []]); ("__atomic_thread_fence", unknown [drop "memorder" []]); + ("__sync_bool_compare_and_swap", unknown [drop "ptr" [r; w]; drop "oldval" []; drop "newval" []]); ("__sync_fetch_and_add", unknown (drop "ptr" [r; w] :: drop "value" [] :: VarArgs (drop' []))); ("__sync_fetch_and_sub", unknown (drop "ptr" [r; w] :: drop "value" [] :: VarArgs (drop' []))); ("__builtin_va_copy", unknown [drop "dest" [w]; drop "src" [r]]); From 012282132c4fc362ee111e2fe91e90da4752610a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:56:58 +0300 Subject: [PATCH 371/628] Add missing library functions for concrat/siege --- src/analyses/libraryFunctions.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 1247a66497..7bc373e3cc 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -387,6 +387,8 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fdatasync", unknown [drop "fd" []]); ("getrusage", unknown [drop "who" []; drop "usage" [w]]); ("alphasort", unknown [drop "a" [r]; drop "b" [r]]); + ("gmtime_r", unknown [drop "timer" [r]; drop "result" [w]]); + ("rand_r", special [drop "seedp" [r; w]] Rand); ] (** Pthread functions. *) @@ -447,6 +449,8 @@ let pthread_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("pthread_key_create", unknown [drop "key" [w]; drop "destructor" [s]]); ("pthread_key_delete", unknown [drop "key" [f]]); ("pthread_cancel", unknown [drop "thread" []]); + ("pthread_testcancel", unknown []); + ("pthread_setcancelstate", unknown [drop "state" []; drop "oldstate" [w]]); ("pthread_setcanceltype", unknown [drop "type" []; drop "oldtype" [w]]); ("pthread_detach", unknown [drop "thread" []]); ("pthread_attr_setschedpolicy", unknown [drop "attr" [r; w]; drop "policy" []]); From c630a3926f71b740e002ae4ff6e6bdf515142cf4 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 13:57:09 +0300 Subject: [PATCH 372/628] Add warn library function for concrat/the_silver_searcher --- src/analyses/libraryFunctions.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 7bc373e3cc..62dbe2aa7c 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -551,7 +551,8 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fputs_unlocked", unknown [drop "s" [r]; drop "stream" [w]]); ("futimesat", unknown [drop "dirfd" []; drop "pathname" [r]; drop "times" [r]]); - ("error", unknown ((drop "status" []):: (drop "errnum" []) :: (drop "format" [r]) :: (VarArgs (drop' [r])))); + ("error", unknown ((drop "status" []) :: (drop "errnum" []) :: (drop "format" [r]) :: (VarArgs (drop' [r])))); + ("warn", unknown (drop "format" [r] :: VarArgs (drop' [r]))); ("gettext", unknown [drop "msgid" [r]]); ("euidaccess", unknown [drop "pathname" [r]; drop "mode" []]); ("rpmatch", unknown [drop "response" [r]]); From 0af8ba71bac405e1e7ade51607cee49f91dd2f3a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 14:39:47 +0300 Subject: [PATCH 373/628] Add zError library function for concrat/the_silver_searcher --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 62dbe2aa7c..03a984fede 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -1007,6 +1007,7 @@ let zlib_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("inflateInit2", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []]); ("inflateInit2_", unknown [drop "strm" [r_deep; w_deep]; drop "windowBits" []; drop "version" [r]; drop "stream_size" []]); ("inflateEnd", unknown [drop "strm" [f_deep]]); + ("zError", unknown [drop "err" []]); ("gzopen", unknown [drop "path" [r]; drop "mode" [r]]); ("gzdopen", unknown [drop "fd" []; drop "mode" [r]]); ("gzread", unknown [drop "file" [r_deep; w_deep]; drop "buf" [w]; drop "len" []]); From c6f7180617d67f5e00845cfc80b2a6f7e78e9dda Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 15:37:37 +0300 Subject: [PATCH 374/628] Add more duplicate library function checks --- src/analyses/libraryFunctions.ml | 40 ++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 1c509e7660..f30f40cbdf 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -994,11 +994,43 @@ let libraries = Hashtbl.of_list [ ("liblzma", liblzma_descs_list); ] +let libraries = + Hashtbl.map (fun library descs_list -> + let descs_tbl = Hashtbl.create 113 in + List.iter (fun (name, desc) -> + Hashtbl.modify_opt name (function + | None -> Some desc + | Some _ -> failwith (Format.sprintf "Library function %s specified multiple times in library %s" name library) + ) descs_tbl + ) descs_list; + descs_tbl + ) libraries + +let all_library_descs: (string, LibraryDesc.t) Hashtbl.t = + Hashtbl.fold (fun _ descs_tbl acc -> + Hashtbl.merge (fun name desc1 desc2 -> + match desc1, desc2 with + | Some _, Some _ -> failwith (Format.sprintf "Library function %s specified in multiple libraries" name) + | (Some _ as desc), None + | None, (Some _ as desc) -> desc + | None, None -> assert false + ) acc descs_tbl + ) libraries (Hashtbl.create 0) + let activated_library_descs: (string, LibraryDesc.t) Hashtbl.t ResettableLazy.t = + let union = + Hashtbl.merge (fun _ desc1 desc2 -> + match desc1, desc2 with + | (Some _ as desc), None + | None, (Some _ as desc) -> desc + | _, _ -> assert false + ) + in ResettableLazy.from_fun (fun () -> - let activated = List.unique (GobConfig.get_string_list "lib.activated") in - let desc_list = List.concat_map (Hashtbl.find libraries) activated in - Hashtbl.of_list desc_list + GobConfig.get_string_list "lib.activated" + |> List.unique + |> List.map (Hashtbl.find libraries) + |> List.fold_left union (Hashtbl.create 0) ) let reset_lazy () = @@ -1201,7 +1233,7 @@ let invalidate_actions = [ ] let () = List.iter (fun (x, _) -> - if Hashtbl.exists (fun _ b -> List.mem_assoc x b) libraries then + if Hashtbl.mem all_library_descs x then failwith ("You have added a function to invalidate_actions that already exists in libraries. Please undo this for function: " ^ x); ) invalidate_actions From 44e01f563bc6cf74399af4e4251456c54325a34e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 15:43:04 +0300 Subject: [PATCH 375/628] Remove duplicate library functions --- src/analyses/libraryFunctions.ml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index f30f40cbdf..0360617171 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -244,7 +244,6 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("symlink" , unknown [drop "oldpath" [r]; drop "newpath" [r];]); ("ftruncate", unknown [drop "fd" []; drop "length" []]); ("mkfifo", unknown [drop "pathname" [r]; drop "mode" []]); - ("ntohs", unknown [drop "netshort" []]); ("alarm", unknown [drop "seconds" []]); ("pwrite", unknown [drop "fd" []; drop "buf" [r]; drop "count" []; drop "offset" []]); ("hstrerror", unknown [drop "err" []]); @@ -275,7 +274,6 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("lstat", unknown [drop "pathname" [r]; drop "statbuf" [w]]); ("fstat", unknown [drop "fd" []; drop "buf" [w]]); ("fstatat", unknown [drop "dirfd" []; drop "pathname" [r]; drop "buf" [w]; drop "flags" []]); - ("getpwnam", unknown [drop "name" [r]]); ("chdir", unknown [drop "path" [r]]); ("closedir", unknown [drop "dirp" [r]]); ("mkdir", unknown [drop "pathname" [r]; drop "mode" []]); @@ -295,7 +293,6 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("freeaddrinfo", unknown [drop "res" [f_deep]]); ("getgid", unknown []); ("pselect", unknown [drop "nfds" []; drop "readdfs" [r]; drop "writedfs" [r]; drop "exceptfds" [r]; drop "timeout" [r]; drop "sigmask" [r]]); - ("strncasecmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); ("getnameinfo", unknown [drop "addr" [r_deep]; drop "addrlen" []; drop "host" [w]; drop "hostlen" []; drop "serv" [w]; drop "servlen" []; drop "flags" []]); ("strtok_r", unknown [drop "str" [r; w]; drop "delim" [r]; drop "saveptr" [r_deep; w_deep]]); (* deep accesses through saveptr if str is NULL: https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/string/strtok_r.c#L31-L40 *) ("kill", unknown [drop "pid" []; drop "sig" []]); @@ -437,7 +434,6 @@ let pthread_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("pthread_attr_setschedpolicy", unknown [drop "attr" [r; w]; drop "policy" []]); ("pthread_condattr_init", unknown [drop "attr" [w]]); ("pthread_condattr_setclock", unknown [drop "attr" [w]; drop "clock_id" []]); - ("pthread_mutexattr_destroy", unknown [drop "attr" [f]]); ("pthread_attr_setschedparam", unknown [drop "attr" [r; w]; drop "param" [r]]); ("pthread_setaffinity_np", unknown [drop "thread" []; drop "cpusetsize" []; drop "cpuset" [r]]); ("pthread_getaffinity_np", unknown [drop "thread" []; drop "cpusetsize" []; drop "cpuset" [w]]); From 599bbb5ed55a7a8ab509271193e4c2df05dadbbe Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 15:53:34 +0300 Subject: [PATCH 376/628] Refactor invalidate actions table --- src/analyses/libraryFunctions.ml | 38 +++++++++----------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 0360617171..aa279ff324 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -1228,32 +1228,16 @@ let invalidate_actions = [ "__goblint_assume_join", readsAll; ] -let () = List.iter (fun (x, _) -> - if Hashtbl.mem all_library_descs x then - failwith ("You have added a function to invalidate_actions that already exists in libraries. Please undo this for function: " ^ x); - ) invalidate_actions - -(* used by get_invalidate_action to make sure - * that hash of invalidates is built only once - * - * Hashtable from strings to functions of type (exp list -> exp list) -*) -let processed_table = ref None - -let get_invalidate_action name = - let tbl = match !processed_table with - | None -> begin - let hash = Hashtbl.create 113 in - let f (k, v) = Hashtbl.add hash k v in - List.iter f invalidate_actions; - processed_table := (Some hash); - hash - end - | Some x -> x - in - if Hashtbl.mem tbl name - then Some (Hashtbl.find tbl name) - else None +let invalidate_actions = + let tbl = Hashtbl.create 113 in + List.iter (fun (name, old_accesses) -> + Hashtbl.modify_opt name (function + | None when Hashtbl.mem all_library_descs name -> failwith (Format.sprintf "Library function %s specified both in libraries and invalidate actions" name) + | None -> Some old_accesses + | Some _ -> failwith (Format.sprintf "Library function %s specified multiple times in invalidate actions" name) + ) tbl + ) invalidate_actions; + tbl let lib_funs = ref (Set.String.of_list ["__raw_read_unlock"; "__raw_write_unlock"; "spin_trylock"]) @@ -1297,7 +1281,7 @@ let find f = match Hashtbl.find_option (ResettableLazy.force activated_library_descs) name with | Some desc -> desc | None -> - match get_invalidate_action name with + match Hashtbl.find_option invalidate_actions name with | Some old_accesses -> LibraryDesc.of_old old_accesses | None -> From 6fd299852648e1dde28eeb0b70e5684b9f471dab Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 16:09:39 +0300 Subject: [PATCH 377/628] Fix references to options.schema.json --- .github/workflows/options.yml | 6 +++--- .readthedocs.yaml | 2 +- docs/user-guide/configuring.md | 2 +- src/common/options.ml | 2 +- src/goblint_lib.ml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/options.yml b/.github/workflows/options.yml index b5f690a700..84906d4949 100644 --- a/.github/workflows/options.yml +++ b/.github/workflows/options.yml @@ -26,10 +26,10 @@ jobs: run: npm install -g ajv-cli - name: Migrate schema # https://github.com/ajv-validator/ajv-cli/issues/199 - run: ajv migrate -s src/util/options.schema.json + run: ajv migrate -s src/common/options.schema.json - name: Validate conf - run: ajv validate -s src/util/options.schema.json -d "conf/**/*.json" + run: ajv validate -s src/common/options.schema.json -d "conf/**/*.json" - name: Validate incremental tests - run: ajv validate -s src/util/options.schema.json -d "tests/incremental/*/*.json" + run: ajv validate -s src/common/options.schema.json -d "tests/incremental/*/*.json" diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c9b41df49d..4827b825ef 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,4 +20,4 @@ build: - pip install json-schema-for-humans post_build: - mkdir _readthedocs/html/jsfh/ - - generate-schema-doc --config-file jsfh.yml src/util/options.schema.json _readthedocs/html/jsfh/ + - generate-schema-doc --config-file jsfh.yml src/common/options.schema.json _readthedocs/html/jsfh/ diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index 82e92f6fe7..348e15dac4 100644 --- a/docs/user-guide/configuring.md +++ b/docs/user-guide/configuring.md @@ -24,7 +24,7 @@ In `.vscode/settings.json` add the following: "/conf/*.json", "/tests/incremental/*/*.json" ], - "url": "/src/util/options.schema.json" + "url": "/src/common/options.schema.json" } ] } diff --git a/src/common/options.ml b/src/common/options.ml index d352c86465..c9bd41038f 100644 --- a/src/common/options.ml +++ b/src/common/options.ml @@ -1,4 +1,4 @@ -(** [src/util/options.schema.json] low-level access. *) +(** [src/common/options.schema.json] low-level access. *) open Json_schema diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index e009ecf86b..a108058291 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -49,7 +49,7 @@ module VarQuery = VarQuery (** {2 Configuration} Runtime configuration is represented as JSON. - Options are specified and documented by the JSON schema [src/util/options.schema.json]. *) + Options are specified and documented by the JSON schema [src/common/options.schema.json]. *) module GobConfig = GobConfig module AfterConfig = AfterConfig From 809f84b905a4b85f6e56d7fc74a5d252dfe90a5e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 9 Oct 2023 16:12:52 +0300 Subject: [PATCH 378/628] Update Gobview for goblint.common --- gobview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gobview b/gobview index b373d06174..41be36b548 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit b373d06174667537b671f3122daf4ebd4b195aea +Subproject commit 41be36b54837b24e6de83740c34e810d3d1afdfb From 5aa420441c248a582b4484df170666b75fee5377 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Mon, 9 Oct 2023 16:20:50 +0200 Subject: [PATCH 379/628] Some ~15 more library functions (#1203) * More socket * `recvfrom` * `writev` / `readv` * `popen` * `stat` / `fstat` * `statfs` * `mount` / `umount` * Fix `select` Co-authored-by: Simmo Saan * Rm duplicate `fstat` Co-authored-by: Simmo Saan * Rm duplicates --------- Co-authored-by: Simmo Saan --- src/analyses/libraryFunctions.ml | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 1c509e7660..c4d1acf76a 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -285,7 +285,9 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("read", unknown [drop "fd" []; drop "buf" [w]; drop "count" []]); ("write", unknown [drop "fd" []; drop "buf" [r]; drop "count" []]); ("recv", unknown [drop "sockfd" []; drop "buf" [w]; drop "len" []; drop "flags" []]); + ("recvfrom", unknown [drop "sockfd" []; drop "buf" [w]; drop "len" []; drop "flags" []; drop "src_addr" [w_deep]; drop "addrlen" [r; w]]); ("send", unknown [drop "sockfd" []; drop "buf" [r]; drop "len" []; drop "flags" []]); + ("sendto", unknown [drop "sockfd" []; drop "buf" [r]; drop "len" []; drop "flags" []; drop "dest_addr" [r_deep]; drop "addrlen" []]); ("strdup", unknown [drop "s" [r]]); ("strndup", unknown [drop "s" [r]; drop "n" []]); ("syscall", unknown (drop "number" [] :: VarArgs (drop' [r; w]))); @@ -373,6 +375,18 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("uname", unknown [drop "buf" [w_deep]]); ("strcasecmp", unknown [drop "s1" [r]; drop "s2" [r]]); ("strncasecmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); + ("connect", unknown [drop "sockfd" []; drop "sockaddr" [r_deep]; drop "addrlen" []]); + ("bind", unknown [drop "sockfd" []; drop "sockaddr" [r_deep]; drop "addrlen" []]); + ("listen", unknown [drop "sockfd" []; drop "backlog" []]); + ("select", unknown [drop "nfds" []; drop "readfds" [r; w]; drop "writefds" [r; w]; drop "exceptfds" [r; w]; drop "timeout" [r; w]]); + ("accept", unknown [drop "sockfd" []; drop "addr" [w_deep]; drop "addrlen" [r; w]]); + ("close", unknown [drop "fd" []]); + ("writev", unknown [drop "fd" []; drop "iov" [r_deep]; drop "iovcnt" []]); + ("readv", unknown [drop "fd" []; drop "iov" [w_deep]; drop "iovcnt" []]); + ("unlink", unknown [drop "pathname" [r]]); + ("popen", unknown [drop "command" [r]; drop "type" [r]]); + ("stat", unknown [drop "pathname" [r]; drop "statbuf" [w]]); + ("statfs", unknown [drop "path" [r]; drop "buf" [w]]); ] (** Pthread functions. *) @@ -588,6 +602,9 @@ let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fts_open", unknown [drop "path_argv" [r_deep]; drop "options" []; drop "compar" [s]]); (* TODO: use Call instead of Spawn *) ("fts_read", unknown [drop "ftsp" [r_deep; w_deep]]); ("fts_close", unknown [drop "ftsp" [f_deep]]); + ("mount", unknown [drop "source" [r]; drop "target" [r]; drop "filesystemtype" [r]; drop "mountflags" []; drop "data" [r]]); + ("umount", unknown [drop "target" [r]]); + ("umount2", unknown [drop "target" [r]; drop "flags" []]); ] let big_kernel_lock = AddrOf (Cil.var (Cilfacade.create_var (makeGlobalVar "[big kernel lock]" intType))) @@ -1100,7 +1117,6 @@ open Invalidate * We assume that no known functions that are reachable are executed/spawned. For that we use ThreadCreate above. *) (* WTF: why are argument numbers 1-indexed (in partition)? *) let invalidate_actions = [ - "connect", readsAll; (*safe*) "__printf_chk", readsAll;(*safe*) "printk", readsAll;(*safe*) "__mutex_init", readsAll;(*safe*) @@ -1118,23 +1134,17 @@ let invalidate_actions = [ "atoi__extinline", readsAll;(*safe*) "_IO_getc", writesAll;(*unsafe*) "pipe", writesAll;(*unsafe*) - "close", writesAll;(*unsafe*) "strerror_r", writesAll;(*unsafe*) "raise", writesAll;(*unsafe*) "_strlen", readsAll;(*safe*) "stat__extinline", writesAllButFirst 1 readsAll;(*drop 1*) "lstat__extinline", writesAllButFirst 1 readsAll;(*drop 1*) - "umount2", readsAll;(*safe*) "waitpid", readsAll;(*safe*) - "statfs", writes [1;3;4];(*keep [1;3;4]*) - "mount", readsAll;(*safe*) "__open_alias", readsAll;(*safe*) "__open_2", readsAll;(*safe*) "ioctl", writesAll;(*unsafe*) "fstat__extinline", writesAll;(*unsafe*) - "umount", readsAll;(*safe*) "scandir", writes [1;3;4];(*keep [1;3;4]*) - "unlink", readsAll;(*safe*) "sigwait", writesAllButFirst 1 readsAll;(*drop 1*) "bindtextdomain", readsAll;(*safe*) "textdomain", readsAll;(*safe*) @@ -1149,11 +1159,9 @@ let invalidate_actions = [ "svctcp_create", readsAll;(*safe*) "clntudp_bufcreate", writesAll;(*unsafe*) "authunix_create_default", readsAll;(*safe*) - "writev", readsAll;(*safe*) "clnt_broadcast", writesAll;(*unsafe*) "clnt_sperrno", readsAll;(*safe*) "pmap_unset", writesAll;(*unsafe*) - "bind", readsAll;(*safe*) "svcudp_create", readsAll;(*safe*) "svc_register", writesAll;(*unsafe*) "svc_run", writesAll;(*unsafe*) @@ -1162,18 +1170,13 @@ let invalidate_actions = [ "__builtin___vsnprintf_chk", writesAllButFirst 3 readsAll; (*drop 3*) "__error", readsAll; (*safe*) "__maskrune", writesAll; (*unsafe*) - "listen", readsAll; (*safe*) - "select", writes [1;5]; (*keep [1;5]*) - "accept", writesAll; (*keep [1]*) "times", writesAll; (*unsafe*) "timespec_get", writes [1]; "__tolower", readsAll; (*safe*) "signal", writesAll; (*unsafe*) - "popen", readsAll; (*safe*) "BF_cfb64_encrypt", writes [1;3;4;5]; (*keep [1;3;4,5]*) "BZ2_bzBuffToBuffDecompress", writes [3;4]; (*keep [3;4]*) "uncompress", writes [3;4]; (*keep [3;4]*) - "stat", writes [2]; (*keep [1]*) "__xstat", writes [3]; (*keep [1]*) "__lxstat", writes [3]; (*keep [1]*) "remove", readsAll; @@ -1181,8 +1184,6 @@ let invalidate_actions = [ "compress2", writes [3]; (*keep [3]*) "__toupper", readsAll; (*safe*) "BF_set_key", writes [3]; (*keep [3]*) - "sendto", writes [2;4]; (*keep [2;4]*) - "recvfrom", writes [4;5]; (*keep [4;5]*) "PL_NewHashTable", readsAll; (*safe*) "assert_failed", readsAll; (*safe*) "munmap", readsAll;(*safe*) From 85ce4b252b47aebc19574938f0db01635c93114c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 10 Oct 2023 14:52:23 +0300 Subject: [PATCH 380/628] Add some missing library functions for concrat/sysbench --- src/analyses/libraryFunctions.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 03a984fede..b84ddc5ac5 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -389,6 +389,9 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("alphasort", unknown [drop "a" [r]; drop "b" [r]]); ("gmtime_r", unknown [drop "timer" [r]; drop "result" [w]]); ("rand_r", special [drop "seedp" [r; w]] Rand); + ("srandom", unknown [drop "seed" []]); + ("random", special [] Rand); + ("posix_memalign", unknown [drop "memptr" [w]; drop "alignment" []; drop "size" []]); (* TODO: Malloc *) ] (** Pthread functions. *) From b96c010fb5c86b5b238b91668feeb0156f2cba8c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 10 Oct 2023 17:36:58 +0300 Subject: [PATCH 381/628] Fix memOutOfBounds indentation --- src/analyses/memOutOfBounds.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 7015e6f143..c715a1d2e7 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -397,8 +397,7 @@ struct match desc.special arglist with | Memset { dest; ch; count; } -> check_count ctx f.vname dest count; | Memcpy { dest; src; n = count; } -> check_count ctx f.vname dest count; - | _ -> (); - ctx.local + | _ -> ctx.local let enter ctx (lval: lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = List.iter (fun arg -> check_exp_for_oob_access ctx arg) args; From 5cc481148d4e079327e6f395c02e28e99cdaa414 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 10 Oct 2023 17:47:36 +0300 Subject: [PATCH 382/628] Fix library function duplicate check indentation (PR #1213) --- src/analyses/libraryFunctions.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index dd9360d7b7..0f9c34f957 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -1047,11 +1047,11 @@ let all_library_descs: (string, LibraryDesc.t) Hashtbl.t = let activated_library_descs: (string, LibraryDesc.t) Hashtbl.t ResettableLazy.t = let union = Hashtbl.merge (fun _ desc1 desc2 -> - match desc1, desc2 with - | (Some _ as desc), None - | None, (Some _ as desc) -> desc - | _, _ -> assert false - ) + match desc1, desc2 with + | (Some _ as desc), None + | None, (Some _ as desc) -> desc + | _, _ -> assert false + ) in ResettableLazy.from_fun (fun () -> GobConfig.get_string_list "lib.activated" From e98911df182e6725bed56113613e30e7cd9f7fa1 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 11 Oct 2023 11:53:06 +0300 Subject: [PATCH 383/628] Remove unnecessary pin Co-authored-by: Simmo Saan --- goblint.opam.locked | 3 --- 1 file changed, 3 deletions(-) diff --git a/goblint.opam.locked b/goblint.opam.locked index d5af6ea348..2744d2fe92 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -122,9 +122,6 @@ build: [ ] dev-repo: "git+https://github.com/goblint/analyzer.git" available: os-distribution != "alpine" & arch != "arm64" -pin-depends: [ - [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] -] conflicts: [ "result" {< "1.5"} ] From 072f99d701ddf09a97c9a7ab0b754be4c63ee138 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 11 Oct 2023 10:57:37 +0200 Subject: [PATCH 384/628] Remove commented out code from `enter` in UAF analysis Add TODOs for future improvement there --- src/analyses/useAfterFree.ml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 521f17d97f..ef63ab3e91 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -182,18 +182,10 @@ struct let enter ctx (lval:lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = let caller_state = ctx.local in List.iter (fun arg -> warn_exp_might_contain_freed "enter" ctx arg) args; + (* TODO: The 2nd component of the callee state needs to contain only the heap vars from the caller state which are reachable from: *) + (* * Global program variables *) + (* * The callee arguments *) [caller_state, (AllocaVars.empty (), snd caller_state)] - (* if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then - [caller_state, caller_state] - else ( - let reachable_from_args = List.fold_left (fun ad arg -> Queries.AD.join ad (ctx.ask (ReachableFrom arg))) (Queries.AD.empty ()) args in - if Queries.AD.is_top reachable_from_args || D.is_top caller_state then - [caller_state, caller_state] - else - let reachable_vars = Queries.AD.to_var_may reachable_from_args in - let callee_state = (AllocaVars.empty (), HeapVars.filter (fun var -> List.mem var reachable_vars) (snd caller_state)) in (* TODO: use AD.mem directly *) - [caller_state, callee_state] - ) *) let combine_env ctx (lval:lval option) fexp (f:fundec) (args:exp list) fc (callee_local:D.t) (f_ask:Queries.ask) : D.t = let (caller_stack_state, caller_heap_state) = ctx.local in From e339ed17c88a154785a0d70ab4ad1c1c0aa31730 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 11 Oct 2023 11:59:50 +0300 Subject: [PATCH 385/628] Remove unnecessary stuff from test case `74/15` Co-authored-by: Simmo Saan --- tests/regression/74-use_after_free/15-juliet-uaf-global-var.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c b/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c index 9cb3b2b29a..cc9819950f 100644 --- a/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c +++ b/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c @@ -1,7 +1,5 @@ -//PARAM: --set ana.activated[+] useAfterFree --set ana.activated[+] threadJoins +//PARAM: --set ana.activated[+] useAfterFree #include -#include -#include int *global; From f018ea37bc1e2cfb66237283b44a8400fc5cf161 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 11 Oct 2023 11:36:01 +0200 Subject: [PATCH 386/628] Reduce duplication --- src/analyses/memOutOfBounds.ml | 45 ++++++++++++++-------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index 68dae1d89a..d52bb1109a 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -165,32 +165,23 @@ struct with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () end - let rec cil_offs_to_idx ctx typ offs = - match offs with - | NoOffset -> intdom_of_int 0 - | Field (field, o) -> - let field_as_offset = Field (field, NoOffset) in - let bits_offset, _size = GoblintCil.bitsOffset (TComp (field.fcomp, [])) field_as_offset in - let bytes_offset = intdom_of_int (bits_offset / 8) in - let remaining_offset = cil_offs_to_idx ctx field.ftype o in - begin - try ID.add bytes_offset remaining_offset - with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () - end - | Index (x, o) -> - begin try - begin match ctx.ask (Queries.EvalInt x) with - | `Top -> ID.top_of @@ Cilfacade.ptrdiff_ikind () - | `Bot -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () - | `Lifted eval_x -> - let typ_size_in_bytes = size_of_type_in_bytes typ in - let casted_eval_x = ID.cast_to (Cilfacade.ptrdiff_ikind ()) eval_x in - let bytes_offset = ID.mul typ_size_in_bytes casted_eval_x in - let remaining_offset = cil_offs_to_idx ctx typ o in - ID.add bytes_offset remaining_offset - end - with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () - end + let cil_offs_to_idx ctx typ offs = + (* TODO: Some duplication with convert_offset in base.ml, unclear how to immediately get more reuse *) + let rec convert_offset (ofs: offset) = + match ofs with + | NoOffset -> `NoOffset + | Field (fld, ofs) -> `Field (fld, convert_offset ofs) + | Index (exp, ofs) when CilType.Exp.equal exp Offset.Index.Exp.any -> (* special offset added by convertToQueryLval *) + `Index (ID.top (), convert_offset ofs) + | Index (exp, ofs) -> + let i = match ctx.ask (Queries.EvalInt exp) with + | `Lifted x -> x + | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + in + `Index (i, convert_offset ofs) + in + PreValueDomain.Offs.to_index (convert_offset offs) + let check_unknown_addr_deref ctx ptr = let may_contain_unknown_addr = @@ -517,4 +508,4 @@ struct end let _ = - MCP.register_analysis (module Spec : MCPSpec) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) From 7ddd47167395781152fe85efa66f57ca74caa477 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 14:12:21 +0300 Subject: [PATCH 387/628] Improve MCP.D pretty --- src/analyses/mCPRegistry.ml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/analyses/mCPRegistry.ml b/src/analyses/mCPRegistry.ml index d1311e0427..8560e5122d 100644 --- a/src/analyses/mCPRegistry.ml +++ b/src/analyses/mCPRegistry.ml @@ -149,20 +149,21 @@ struct let unop_map f x = List.rev @@ unop_fold (fun a n s d -> (n, f s d) :: a) [] x - let pretty () x = - let f a n (module S : Printable.S) x = Pretty.dprintf "%s:%a" (S.name ()) S.pretty (obj x) :: a in - let xs = unop_fold f [] x in - match xs with - | [] -> text "[]" - | x :: [] -> x - | x :: y -> - let rest = List.fold_left (fun p n->p ++ text "," ++ break ++ n) nil y in - text "[" ++ align ++ x ++ rest ++ unalign ++ text "]" + let pretty () xs = + let pretty_one a n (module S: Printable.S) x = + let doc = Pretty.dprintf "%s:%a" (find_spec_name n) S.pretty (obj x) in + match a with + | None -> Some doc + | Some a -> Some (a ++ text "," ++ line ++ doc) + in + let doc = Option.default Pretty.nil (unop_fold pretty_one None xs) in + Pretty.dprintf "[@[%a@]]" Pretty.insert doc let show x = let xs = unop_fold (fun a n (module S : Printable.S) x -> let analysis_name = find_spec_name n in - (analysis_name ^ ":(" ^ S.show (obj x) ^ ")") :: a) [] x + (analysis_name ^ ":(" ^ S.show (obj x) ^ ")") :: a + ) [] x in IO.to_string (List.print ~first:"[" ~last:"]" ~sep:", " String.print) (rev xs) From e2a585999e3f46642f4474aa339cd6567e429448 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 14:12:45 +0300 Subject: [PATCH 388/628] Improve MCP.D pretty_diff --- src/analyses/mCPRegistry.ml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/analyses/mCPRegistry.ml b/src/analyses/mCPRegistry.ml index 8560e5122d..32847bb3ed 100644 --- a/src/analyses/mCPRegistry.ml +++ b/src/analyses/mCPRegistry.ml @@ -370,12 +370,19 @@ struct let top () = map (fun (n,(module S : Lattice.S)) -> (n,repr @@ S.top ())) @@ domain_list () let bot () = map (fun (n,(module S : Lattice.S)) -> (n,repr @@ S.bot ())) @@ domain_list () - let pretty_diff () (x,y) = - let f a n (module S : Lattice.S) x y = - if S.leq (obj x) (obj y) then a - else a ++ S.pretty_diff () (obj x, obj y) ++ text ". " + let pretty_diff () (xs, ys) = + let pretty_one a n (module S: Lattice.S) x y = + if S.leq (obj x) (obj y) then + a + else ( + let doc = Pretty.dprintf "%s:%a" (find_spec_name n) S.pretty_diff (obj x, obj y) in + match a with + | None -> Some doc + | Some a -> Some (a ++ text "," ++ line ++ doc) + ) in - binop_fold f nil x y + let doc = Option.default Pretty.nil (binop_fold pretty_one None xs ys) in + Pretty.dprintf "[@[%a@]]" Pretty.insert doc end module DomVariantLattice0 (DLSpec : DomainListLatticeSpec) From 44f775942ce6d82736fe2150ff7af219dc0c1532 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 14:35:44 +0300 Subject: [PATCH 389/628] Improve empty MapDomain pretty --- src/domains/mapDomain.ml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/domains/mapDomain.ml b/src/domains/mapDomain.ml index 6c40ab9792..76dec6f0d2 100644 --- a/src/domains/mapDomain.ml +++ b/src/domains/mapDomain.ml @@ -68,11 +68,14 @@ end module Print (D: Printable.S) (R: Printable.S) (M: Bindings with type key = D.t and type value = R.t) = struct let pretty () map = - let pretty_bindings () = M.fold (fun k v acc -> - acc ++ dprintf "%a ->@? @[%a@]\n" D.pretty k R.pretty v + let doc = M.fold (fun k v acc -> + acc ++ dprintf "%a ->@?@[%a@]\n" D.pretty k R.pretty v ) map nil in - dprintf "@[{\n @[%t@]}@]" pretty_bindings + if doc = Pretty.nil then + text "{}" + else + dprintf "@[{\n @[%a@]}@]" Pretty.insert doc let show map = GobPretty.sprint pretty map From 00b7e623a7a2ddaa36a91cfd21546de33008e10e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:00:49 +0300 Subject: [PATCH 390/628] Add module names to Prod and Prod3 --- src/domains/printable.ml | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/domains/printable.ml b/src/domains/printable.ml index 1207d35db2..b0755fb730 100644 --- a/src/domains/printable.ml +++ b/src/domains/printable.ml @@ -366,9 +366,17 @@ struct let pretty () (x,y) = if expand_fst || expand_snd then text "(" + ++ text (Base1.name ()) + ++ text ":" + ++ align ++ (if expand_fst then Base1.pretty () x else text (Base1.show x)) + ++ unalign ++ text ", " + ++ text (Base2.name ()) + ++ text ":" + ++ align ++ (if expand_snd then Base2.pretty () y else text (Base2.show y)) + ++ unalign ++ text ")" else text (show (x,y)) @@ -403,12 +411,24 @@ struct "(" ^ !first ^ ", " ^ !second ^ ", " ^ !third ^ ")" let pretty () (x,y,z) = - text "(" ++ - Base1.pretty () x - ++ text ", " ++ - Base2.pretty () y - ++ text ", " ++ - Base3.pretty () z + text "(" + ++ text (Base1.name ()) + ++ text ":" + ++ align + ++ Base1.pretty () x + ++ unalign + ++ text ", " + ++ text (Base2.name ()) + ++ text ":" + ++ align + ++ Base2.pretty () y + ++ unalign + ++ text ", " + ++ text (Base3.name ()) + ++ text ":" + ++ align + ++ Base3.pretty () z + ++ unalign ++ text ")" let printXml f (x,y,z) = From 83fef2cd47fb15d937192392684c4e39d9d136bb Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:01:03 +0300 Subject: [PATCH 391/628] Add names to mutex analysis domains --- src/analyses/mutexAnalysis.ml | 2 ++ src/cdomains/lockDomain.ml | 1 + 2 files changed, 3 insertions(+) diff --git a/src/analyses/mutexAnalysis.ml b/src/analyses/mutexAnalysis.ml index 5a61976ef5..ee050f55ca 100644 --- a/src/analyses/mutexAnalysis.ml +++ b/src/analyses/mutexAnalysis.ml @@ -30,6 +30,8 @@ struct include MapDomain.MapTop_LiftBot (ValueDomain.Addr) (Count) + let name () = "multiplicity" + let increment v x = let current = find v x in if current = max_count () then diff --git a/src/cdomains/lockDomain.ml b/src/cdomains/lockDomain.ml index 4bc97b34ab..107c1c0692 100644 --- a/src/cdomains/lockDomain.ml +++ b/src/cdomains/lockDomain.ml @@ -37,6 +37,7 @@ struct end include SetDomain.Reverse(SetDomain.ToppedSet (Lock) (struct let topname = "All mutexes" end)) + let name () = "lockset" let may_be_same_offset of1 of2 = (* Only reached with definite of2 and indefinite of1. *) From 151ccb15068bb262a0134ec818fe7ad307615379 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:01:17 +0300 Subject: [PATCH 392/628] Add names to mallocWrapper analysis domains --- src/analyses/wrapperFunctionAnalysis.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/analyses/wrapperFunctionAnalysis.ml b/src/analyses/wrapperFunctionAnalysis.ml index 5c0176df48..e98597a66a 100644 --- a/src/analyses/wrapperFunctionAnalysis.ml +++ b/src/analyses/wrapperFunctionAnalysis.ml @@ -33,11 +33,20 @@ struct Introduce a function for this to keep things consistent. *) let node_for_ctx ctx = ctx.prev_node + module NodeFlatLattice = + struct + include NodeFlatLattice + let name () = "wrapper call" + end + module UniqueCount = UniqueCount (* Map for counting function call node visits up to n (of the current thread). *) module UniqueCallCounter = - MapDomain.MapBot_LiftTop(NodeFlatLattice)(UniqueCount) + struct + include MapDomain.MapBot_LiftTop(NodeFlatLattice)(UniqueCount) + let name () = "unique calls" + end (* Increase counter for given node. If it does not exist yet, create it. *) let add_unique_call counter node = From b0ce3691ec8525711f57889ddb29b44670090d76 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:01:24 +0300 Subject: [PATCH 393/628] Add names to threadid analysis domains --- src/analyses/threadId.ml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/analyses/threadId.ml b/src/analyses/threadId.ml index 4acf88a7ef..8144aea507 100644 --- a/src/analyses/threadId.ml +++ b/src/analyses/threadId.ml @@ -29,11 +29,30 @@ module Spec = struct include Analyses.IdentitySpec - module N = Lattice.Flat (VNI) (struct let bot_name = "unknown node" let top_name = "unknown node" end) + module N = + struct + include Lattice.Flat (VNI) (struct let bot_name = "unknown node" let top_name = "unknown node" end) + let name () = "wrapper call" + end module TD = Thread.D + module Created = + struct + module Current = + struct + include TD + let name () = "current function" + end + module Callees = + struct + include TD + let name () = "callees" + end + include Lattice.Prod (Current) (Callees) + let name () = "created" + end (** Uniqueness Counter * TID * (All thread creates of current thread * All thread creates of the current function and its callees) *) - module D = Lattice.Prod3 (N) (ThreadLifted) (Lattice.Prod(TD)(TD)) + module D = Lattice.Prod3 (N) (ThreadLifted) (Created) module C = D module P = IdentityP (D) From 0f70e17d5d13404b83d1caed8b4219471c32776f Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:09:09 +0300 Subject: [PATCH 394/628] Fix MCP module names --- src/analyses/mCPRegistry.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/mCPRegistry.ml b/src/analyses/mCPRegistry.ml index 32847bb3ed..810da827ff 100644 --- a/src/analyses/mCPRegistry.ml +++ b/src/analyses/mCPRegistry.ml @@ -318,6 +318,7 @@ struct open Obj include DomListPrintable (PrintableOfRepresentativeSpec (DLSpec)) + let name () = "MCP.P" type elt = (int * unknown) list @@ -344,6 +345,7 @@ struct open Obj include DomListPrintable (PrintableOfLatticeSpec (DLSpec)) + let name () = "MCP.D" let binop_fold f a (x:t) (y:t) = GobList.fold_left3 (fun a (n,d) (n',d') (n'',s) -> assert (n = n' && n = n''); f a n s d d') a x y (domain_list ()) From d9afd55a63514ff47f163c34ff07a41ffd48a30c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 15:09:17 +0300 Subject: [PATCH 395/628] Add names to region analysis domains --- src/cdomains/regionDomain.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cdomains/regionDomain.ml b/src/cdomains/regionDomain.ml index 143ba086a6..b577e3499f 100644 --- a/src/cdomains/regionDomain.ml +++ b/src/cdomains/regionDomain.ml @@ -9,6 +9,15 @@ module B = Printable.UnitConf (struct let name = "•" end) module VFB = struct include Printable.Either (VF) (B) + let name () = "region" + + let pretty () = function + | `Right () -> Pretty.text "•" + | `Left x -> VF.pretty () x + + let show = function + | `Right () -> "•" + | `Left x -> VF.show x let printXml f = function | `Right () -> @@ -51,6 +60,7 @@ end module RS = struct include PartitionDomain.Set (VFB) + let name () = "regions" let single_vf vf = singleton (VFB.of_vf vf) let single_bullet = singleton (VFB.bullet) let remove_bullet x = remove VFB.bullet x From a2f36fb4179705a812cc3b0f589d5fd0c9649dc9 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 11 Oct 2023 16:46:33 +0200 Subject: [PATCH 396/628] Reorganize memsafety regr. tests --- .../{77-mem-oob => 74-invalid_deref}/01-oob-heap-simple.c | 0 .../{74-use_after_free => 74-invalid_deref}/02-conditional-uaf.c | 0 .../{74-use_after_free => 74-invalid_deref}/03-nested-ptr-uaf.c | 0 .../04-function-call-uaf.c | 0 .../{77-mem-oob => 74-invalid_deref}/05-oob-implicit-deref.c | 0 tests/regression/{77-mem-oob => 74-invalid_deref}/06-memset-oob.c | 0 tests/regression/{77-mem-oob => 74-invalid_deref}/07-memcpy-oob.c | 0 .../{77-mem-oob => 74-invalid_deref}/08-memset-memcpy-array.c | 0 .../{74-use_after_free => 74-invalid_deref}/09-juliet-uaf.c | 0 .../{77-mem-oob => 74-invalid_deref}/10-oob-two-loops.c | 0 .../{77-mem-oob => 74-invalid_deref}/11-address-offset-oob.c | 0 .../{77-mem-oob => 74-invalid_deref}/12-memcpy-oob-src.c | 0 .../{77-mem-oob => 74-invalid_deref}/13-mem-oob-packed-struct.c | 0 .../{74-use_after_free => 74-invalid_deref}/14-alloca-uaf.c | 0 .../15-juliet-uaf-global-var.c | 0 .../16-uaf-packed-struct.c | 0 .../17-scopes-no-static.c} | 0 .../01-simple-uaf.c => 74-invalid_deref/18-simple-uaf.c} | 0 .../19-oob-stack-simple.c} | 0 .../20-scopes-global-var.c} | 0 .../{77-mem-oob/03-oob-loop.c => 74-invalid_deref/21-oob-loop.c} | 0 .../03-scopes-static.c => 74-invalid_deref/22-scopes-static.c} | 0 .../23-oob-deref-after-ptr-arith.c} | 0 .../24-uaf-free-in-wrapper-fun.c} | 0 .../06-uaf-struct.c => 74-invalid_deref/25-uaf-struct.c} | 0 .../26-memset-memcpy-addr-offs.c} | 0 .../27-wrapper-funs-uaf.c} | 0 .../28-multi-threaded-uaf.c} | 0 .../29-multi-threaded-uaf-with-joined-thread.c} | 0 .../01-invalid-dealloc-simple.c | 0 .../02-invalid-dealloc-struct.c | 0 .../03-invalid-dealloc-array.c | 0 .../{75-invalid_dealloc => 75-invalid_free}/04-invalid-realloc.c | 0 .../{75-invalid_dealloc => 75-invalid_free}/05-free-at-offset.c | 0 .../06-realloc-at-offset.c | 0 .../07-free-at-struct-offset.c | 0 .../08-itc-no-double-free.c | 0 .../09-juliet-invalid-dealloc-alloca.c | 0 .../10-invalid-dealloc-union.c | 0 .../07-itc-double-free.c => 75-invalid_free/11-itc-double-free.c} | 0 .../12-realloc-at-struct-offset.c} | 0 .../13-juliet-double-free.c} | 0 42 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{77-mem-oob => 74-invalid_deref}/01-oob-heap-simple.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/02-conditional-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/03-nested-ptr-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/04-function-call-uaf.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/05-oob-implicit-deref.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/06-memset-oob.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/07-memcpy-oob.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/08-memset-memcpy-array.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/09-juliet-uaf.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/10-oob-two-loops.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/11-address-offset-oob.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/12-memcpy-oob-src.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/13-mem-oob-packed-struct.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/14-alloca-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/15-juliet-uaf-global-var.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/16-uaf-packed-struct.c (100%) rename tests/regression/{78-invalid-deref-scopes/01-scopes-no-static.c => 74-invalid_deref/17-scopes-no-static.c} (100%) rename tests/regression/{74-use_after_free/01-simple-uaf.c => 74-invalid_deref/18-simple-uaf.c} (100%) rename tests/regression/{77-mem-oob/02-oob-stack-simple.c => 74-invalid_deref/19-oob-stack-simple.c} (100%) rename tests/regression/{78-invalid-deref-scopes/02-scopes-global-var.c => 74-invalid_deref/20-scopes-global-var.c} (100%) rename tests/regression/{77-mem-oob/03-oob-loop.c => 74-invalid_deref/21-oob-loop.c} (100%) rename tests/regression/{78-invalid-deref-scopes/03-scopes-static.c => 74-invalid_deref/22-scopes-static.c} (100%) rename tests/regression/{77-mem-oob/04-oob-deref-after-ptr-arith.c => 74-invalid_deref/23-oob-deref-after-ptr-arith.c} (100%) rename tests/regression/{74-use_after_free/05-uaf-free-in-wrapper-fun.c => 74-invalid_deref/24-uaf-free-in-wrapper-fun.c} (100%) rename tests/regression/{74-use_after_free/06-uaf-struct.c => 74-invalid_deref/25-uaf-struct.c} (100%) rename tests/regression/{77-mem-oob/09-memset-memcpy-addr-offs.c => 74-invalid_deref/26-memset-memcpy-addr-offs.c} (100%) rename tests/regression/{74-use_after_free/11-wrapper-funs-uaf.c => 74-invalid_deref/27-wrapper-funs-uaf.c} (100%) rename tests/regression/{74-use_after_free/12-multi-threaded-uaf.c => 74-invalid_deref/28-multi-threaded-uaf.c} (100%) rename tests/regression/{74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c => 74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c} (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/01-invalid-dealloc-simple.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/02-invalid-dealloc-struct.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/03-invalid-dealloc-array.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/04-invalid-realloc.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/05-free-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/06-realloc-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/07-free-at-struct-offset.c (100%) rename tests/regression/{74-use_after_free => 75-invalid_free}/08-itc-no-double-free.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/09-juliet-invalid-dealloc-alloca.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/10-invalid-dealloc-union.c (100%) rename tests/regression/{74-use_after_free/07-itc-double-free.c => 75-invalid_free/11-itc-double-free.c} (100%) rename tests/regression/{75-invalid_dealloc/08-realloc-at-struct-offset.c => 75-invalid_free/12-realloc-at-struct-offset.c} (100%) rename tests/regression/{74-use_after_free/10-juliet-double-free.c => 75-invalid_free/13-juliet-double-free.c} (100%) diff --git a/tests/regression/77-mem-oob/01-oob-heap-simple.c b/tests/regression/74-invalid_deref/01-oob-heap-simple.c similarity index 100% rename from tests/regression/77-mem-oob/01-oob-heap-simple.c rename to tests/regression/74-invalid_deref/01-oob-heap-simple.c diff --git a/tests/regression/74-use_after_free/02-conditional-uaf.c b/tests/regression/74-invalid_deref/02-conditional-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/02-conditional-uaf.c rename to tests/regression/74-invalid_deref/02-conditional-uaf.c diff --git a/tests/regression/74-use_after_free/03-nested-ptr-uaf.c b/tests/regression/74-invalid_deref/03-nested-ptr-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/03-nested-ptr-uaf.c rename to tests/regression/74-invalid_deref/03-nested-ptr-uaf.c diff --git a/tests/regression/74-use_after_free/04-function-call-uaf.c b/tests/regression/74-invalid_deref/04-function-call-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/04-function-call-uaf.c rename to tests/regression/74-invalid_deref/04-function-call-uaf.c diff --git a/tests/regression/77-mem-oob/05-oob-implicit-deref.c b/tests/regression/74-invalid_deref/05-oob-implicit-deref.c similarity index 100% rename from tests/regression/77-mem-oob/05-oob-implicit-deref.c rename to tests/regression/74-invalid_deref/05-oob-implicit-deref.c diff --git a/tests/regression/77-mem-oob/06-memset-oob.c b/tests/regression/74-invalid_deref/06-memset-oob.c similarity index 100% rename from tests/regression/77-mem-oob/06-memset-oob.c rename to tests/regression/74-invalid_deref/06-memset-oob.c diff --git a/tests/regression/77-mem-oob/07-memcpy-oob.c b/tests/regression/74-invalid_deref/07-memcpy-oob.c similarity index 100% rename from tests/regression/77-mem-oob/07-memcpy-oob.c rename to tests/regression/74-invalid_deref/07-memcpy-oob.c diff --git a/tests/regression/77-mem-oob/08-memset-memcpy-array.c b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c similarity index 100% rename from tests/regression/77-mem-oob/08-memset-memcpy-array.c rename to tests/regression/74-invalid_deref/08-memset-memcpy-array.c diff --git a/tests/regression/74-use_after_free/09-juliet-uaf.c b/tests/regression/74-invalid_deref/09-juliet-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/09-juliet-uaf.c rename to tests/regression/74-invalid_deref/09-juliet-uaf.c diff --git a/tests/regression/77-mem-oob/10-oob-two-loops.c b/tests/regression/74-invalid_deref/10-oob-two-loops.c similarity index 100% rename from tests/regression/77-mem-oob/10-oob-two-loops.c rename to tests/regression/74-invalid_deref/10-oob-two-loops.c diff --git a/tests/regression/77-mem-oob/11-address-offset-oob.c b/tests/regression/74-invalid_deref/11-address-offset-oob.c similarity index 100% rename from tests/regression/77-mem-oob/11-address-offset-oob.c rename to tests/regression/74-invalid_deref/11-address-offset-oob.c diff --git a/tests/regression/77-mem-oob/12-memcpy-oob-src.c b/tests/regression/74-invalid_deref/12-memcpy-oob-src.c similarity index 100% rename from tests/regression/77-mem-oob/12-memcpy-oob-src.c rename to tests/regression/74-invalid_deref/12-memcpy-oob-src.c diff --git a/tests/regression/77-mem-oob/13-mem-oob-packed-struct.c b/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c similarity index 100% rename from tests/regression/77-mem-oob/13-mem-oob-packed-struct.c rename to tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c diff --git a/tests/regression/74-use_after_free/14-alloca-uaf.c b/tests/regression/74-invalid_deref/14-alloca-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/14-alloca-uaf.c rename to tests/regression/74-invalid_deref/14-alloca-uaf.c diff --git a/tests/regression/74-use_after_free/15-juliet-uaf-global-var.c b/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c similarity index 100% rename from tests/regression/74-use_after_free/15-juliet-uaf-global-var.c rename to tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c diff --git a/tests/regression/74-use_after_free/16-uaf-packed-struct.c b/tests/regression/74-invalid_deref/16-uaf-packed-struct.c similarity index 100% rename from tests/regression/74-use_after_free/16-uaf-packed-struct.c rename to tests/regression/74-invalid_deref/16-uaf-packed-struct.c diff --git a/tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c b/tests/regression/74-invalid_deref/17-scopes-no-static.c similarity index 100% rename from tests/regression/78-invalid-deref-scopes/01-scopes-no-static.c rename to tests/regression/74-invalid_deref/17-scopes-no-static.c diff --git a/tests/regression/74-use_after_free/01-simple-uaf.c b/tests/regression/74-invalid_deref/18-simple-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/01-simple-uaf.c rename to tests/regression/74-invalid_deref/18-simple-uaf.c diff --git a/tests/regression/77-mem-oob/02-oob-stack-simple.c b/tests/regression/74-invalid_deref/19-oob-stack-simple.c similarity index 100% rename from tests/regression/77-mem-oob/02-oob-stack-simple.c rename to tests/regression/74-invalid_deref/19-oob-stack-simple.c diff --git a/tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c b/tests/regression/74-invalid_deref/20-scopes-global-var.c similarity index 100% rename from tests/regression/78-invalid-deref-scopes/02-scopes-global-var.c rename to tests/regression/74-invalid_deref/20-scopes-global-var.c diff --git a/tests/regression/77-mem-oob/03-oob-loop.c b/tests/regression/74-invalid_deref/21-oob-loop.c similarity index 100% rename from tests/regression/77-mem-oob/03-oob-loop.c rename to tests/regression/74-invalid_deref/21-oob-loop.c diff --git a/tests/regression/78-invalid-deref-scopes/03-scopes-static.c b/tests/regression/74-invalid_deref/22-scopes-static.c similarity index 100% rename from tests/regression/78-invalid-deref-scopes/03-scopes-static.c rename to tests/regression/74-invalid_deref/22-scopes-static.c diff --git a/tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c b/tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c similarity index 100% rename from tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c rename to tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c diff --git a/tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c b/tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c similarity index 100% rename from tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c rename to tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c diff --git a/tests/regression/74-use_after_free/06-uaf-struct.c b/tests/regression/74-invalid_deref/25-uaf-struct.c similarity index 100% rename from tests/regression/74-use_after_free/06-uaf-struct.c rename to tests/regression/74-invalid_deref/25-uaf-struct.c diff --git a/tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c b/tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c similarity index 100% rename from tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c rename to tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c diff --git a/tests/regression/74-use_after_free/11-wrapper-funs-uaf.c b/tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/11-wrapper-funs-uaf.c rename to tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c diff --git a/tests/regression/74-use_after_free/12-multi-threaded-uaf.c b/tests/regression/74-invalid_deref/28-multi-threaded-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/12-multi-threaded-uaf.c rename to tests/regression/74-invalid_deref/28-multi-threaded-uaf.c diff --git a/tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c b/tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c similarity index 100% rename from tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c rename to tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c diff --git a/tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c b/tests/regression/75-invalid_free/01-invalid-dealloc-simple.c similarity index 100% rename from tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c rename to tests/regression/75-invalid_free/01-invalid-dealloc-simple.c diff --git a/tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c b/tests/regression/75-invalid_free/02-invalid-dealloc-struct.c similarity index 100% rename from tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c rename to tests/regression/75-invalid_free/02-invalid-dealloc-struct.c diff --git a/tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c b/tests/regression/75-invalid_free/03-invalid-dealloc-array.c similarity index 100% rename from tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c rename to tests/regression/75-invalid_free/03-invalid-dealloc-array.c diff --git a/tests/regression/75-invalid_dealloc/04-invalid-realloc.c b/tests/regression/75-invalid_free/04-invalid-realloc.c similarity index 100% rename from tests/regression/75-invalid_dealloc/04-invalid-realloc.c rename to tests/regression/75-invalid_free/04-invalid-realloc.c diff --git a/tests/regression/75-invalid_dealloc/05-free-at-offset.c b/tests/regression/75-invalid_free/05-free-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/05-free-at-offset.c rename to tests/regression/75-invalid_free/05-free-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/06-realloc-at-offset.c b/tests/regression/75-invalid_free/06-realloc-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/06-realloc-at-offset.c rename to tests/regression/75-invalid_free/06-realloc-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c b/tests/regression/75-invalid_free/07-free-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c rename to tests/regression/75-invalid_free/07-free-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/08-itc-no-double-free.c b/tests/regression/75-invalid_free/08-itc-no-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/08-itc-no-double-free.c rename to tests/regression/75-invalid_free/08-itc-no-double-free.c diff --git a/tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c b/tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c similarity index 100% rename from tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c rename to tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c diff --git a/tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c b/tests/regression/75-invalid_free/10-invalid-dealloc-union.c similarity index 100% rename from tests/regression/75-invalid_dealloc/10-invalid-dealloc-union.c rename to tests/regression/75-invalid_free/10-invalid-dealloc-union.c diff --git a/tests/regression/74-use_after_free/07-itc-double-free.c b/tests/regression/75-invalid_free/11-itc-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/07-itc-double-free.c rename to tests/regression/75-invalid_free/11-itc-double-free.c diff --git a/tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c b/tests/regression/75-invalid_free/12-realloc-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c rename to tests/regression/75-invalid_free/12-realloc-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/10-juliet-double-free.c b/tests/regression/75-invalid_free/13-juliet-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/10-juliet-double-free.c rename to tests/regression/75-invalid_free/13-juliet-double-free.c From 3281c74399a6f4b9c16a64ca11e041897ff36d9a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 11 Oct 2023 17:54:59 +0300 Subject: [PATCH 397/628] Temporarily reintroduce old unqualified directory structure inside common library --- .github/workflows/options.yml | 6 +++--- .readthedocs.yaml | 2 +- docs/user-guide/configuring.md | 2 +- src/common/{ => cdomains}/basetype.ml | 0 src/common/{ => domains}/lattice.ml | 0 src/common/{ => domains}/myCheck.ml | 0 src/common/{ => domains}/printable.ml | 0 src/common/dune | 4 ++-- src/common/{ => framework}/analysisState.ml | 0 src/common/{ => framework}/controlSpecC.ml | 0 src/common/{ => framework}/controlSpecC.mli | 0 src/common/{ => framework}/edge.ml | 0 src/common/{ => framework}/myCFG.ml | 0 src/common/{ => framework}/node.ml | 0 src/common/{ => framework}/node0.ml | 0 src/common/{ => incremental}/updateCil0.ml | 0 src/common/{ => util}/afterConfig.ml | 0 src/common/{ => util}/cilType.ml | 0 src/common/{ => util}/cilfacade.ml | 0 src/common/{ => util}/cilfacade0.ml | 0 src/common/{ => util}/gobConfig.ml | 0 src/common/{ => util}/gobFormat.ml | 0 src/common/{ => util}/jsonSchema.ml | 0 src/common/{ => util}/lazyEval.ml | 0 src/common/{ => util}/messageCategory.ml | 0 src/common/{ => util}/messageUtil.ml | 0 src/common/{ => util}/messages.ml | 0 src/common/{ => util}/options.ml | 2 +- src/common/{ => util}/options.schema.json | 0 src/common/{ => util}/resettableLazy.ml | 0 src/common/{ => util}/resettableLazy.mli | 0 src/common/{ => util}/richVarinfo.ml | 0 src/common/{ => util}/richVarinfo.mli | 0 src/common/{ => util}/timing.ml | 0 src/common/{ => util}/tracing.ml | 0 src/common/{ => util}/xmlUtil.ml | 0 src/goblint_lib.ml | 2 +- 37 files changed, 9 insertions(+), 9 deletions(-) rename src/common/{ => cdomains}/basetype.ml (100%) rename src/common/{ => domains}/lattice.ml (100%) rename src/common/{ => domains}/myCheck.ml (100%) rename src/common/{ => domains}/printable.ml (100%) rename src/common/{ => framework}/analysisState.ml (100%) rename src/common/{ => framework}/controlSpecC.ml (100%) rename src/common/{ => framework}/controlSpecC.mli (100%) rename src/common/{ => framework}/edge.ml (100%) rename src/common/{ => framework}/myCFG.ml (100%) rename src/common/{ => framework}/node.ml (100%) rename src/common/{ => framework}/node0.ml (100%) rename src/common/{ => incremental}/updateCil0.ml (100%) rename src/common/{ => util}/afterConfig.ml (100%) rename src/common/{ => util}/cilType.ml (100%) rename src/common/{ => util}/cilfacade.ml (100%) rename src/common/{ => util}/cilfacade0.ml (100%) rename src/common/{ => util}/gobConfig.ml (100%) rename src/common/{ => util}/gobFormat.ml (100%) rename src/common/{ => util}/jsonSchema.ml (100%) rename src/common/{ => util}/lazyEval.ml (100%) rename src/common/{ => util}/messageCategory.ml (100%) rename src/common/{ => util}/messageUtil.ml (100%) rename src/common/{ => util}/messages.ml (100%) rename src/common/{ => util}/options.ml (98%) rename src/common/{ => util}/options.schema.json (100%) rename src/common/{ => util}/resettableLazy.ml (100%) rename src/common/{ => util}/resettableLazy.mli (100%) rename src/common/{ => util}/richVarinfo.ml (100%) rename src/common/{ => util}/richVarinfo.mli (100%) rename src/common/{ => util}/timing.ml (100%) rename src/common/{ => util}/tracing.ml (100%) rename src/common/{ => util}/xmlUtil.ml (100%) diff --git a/.github/workflows/options.yml b/.github/workflows/options.yml index 84906d4949..40652791fa 100644 --- a/.github/workflows/options.yml +++ b/.github/workflows/options.yml @@ -26,10 +26,10 @@ jobs: run: npm install -g ajv-cli - name: Migrate schema # https://github.com/ajv-validator/ajv-cli/issues/199 - run: ajv migrate -s src/common/options.schema.json + run: ajv migrate -s src/common/util/options.schema.json - name: Validate conf - run: ajv validate -s src/common/options.schema.json -d "conf/**/*.json" + run: ajv validate -s src/common/util/options.schema.json -d "conf/**/*.json" - name: Validate incremental tests - run: ajv validate -s src/common/options.schema.json -d "tests/incremental/*/*.json" + run: ajv validate -s src/common/util/options.schema.json -d "tests/incremental/*/*.json" diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 4827b825ef..08044d195c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,4 +20,4 @@ build: - pip install json-schema-for-humans post_build: - mkdir _readthedocs/html/jsfh/ - - generate-schema-doc --config-file jsfh.yml src/common/options.schema.json _readthedocs/html/jsfh/ + - generate-schema-doc --config-file jsfh.yml src/common/util/options.schema.json _readthedocs/html/jsfh/ diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index 348e15dac4..9a32a14a4c 100644 --- a/docs/user-guide/configuring.md +++ b/docs/user-guide/configuring.md @@ -24,7 +24,7 @@ In `.vscode/settings.json` add the following: "/conf/*.json", "/tests/incremental/*/*.json" ], - "url": "/src/common/options.schema.json" + "url": "/src/common/util/options.schema.json" } ] } diff --git a/src/common/basetype.ml b/src/common/cdomains/basetype.ml similarity index 100% rename from src/common/basetype.ml rename to src/common/cdomains/basetype.ml diff --git a/src/common/lattice.ml b/src/common/domains/lattice.ml similarity index 100% rename from src/common/lattice.ml rename to src/common/domains/lattice.ml diff --git a/src/common/myCheck.ml b/src/common/domains/myCheck.ml similarity index 100% rename from src/common/myCheck.ml rename to src/common/domains/myCheck.ml diff --git a/src/common/printable.ml b/src/common/domains/printable.ml similarity index 100% rename from src/common/printable.ml rename to src/common/domains/printable.ml diff --git a/src/common/dune b/src/common/dune index 03a93a3030..b937ecdd02 100644 --- a/src/common/dune +++ b/src/common/dune @@ -1,4 +1,4 @@ -(include_subdirs no) +(include_subdirs unqualified) (library (name goblint_common) @@ -24,5 +24,5 @@ ppx_deriving_hash ppx_deriving_yojson ppx_blob)) - (preprocessor_deps (file options.schema.json))) + (preprocessor_deps (file util/options.schema.json))) diff --git a/src/common/analysisState.ml b/src/common/framework/analysisState.ml similarity index 100% rename from src/common/analysisState.ml rename to src/common/framework/analysisState.ml diff --git a/src/common/controlSpecC.ml b/src/common/framework/controlSpecC.ml similarity index 100% rename from src/common/controlSpecC.ml rename to src/common/framework/controlSpecC.ml diff --git a/src/common/controlSpecC.mli b/src/common/framework/controlSpecC.mli similarity index 100% rename from src/common/controlSpecC.mli rename to src/common/framework/controlSpecC.mli diff --git a/src/common/edge.ml b/src/common/framework/edge.ml similarity index 100% rename from src/common/edge.ml rename to src/common/framework/edge.ml diff --git a/src/common/myCFG.ml b/src/common/framework/myCFG.ml similarity index 100% rename from src/common/myCFG.ml rename to src/common/framework/myCFG.ml diff --git a/src/common/node.ml b/src/common/framework/node.ml similarity index 100% rename from src/common/node.ml rename to src/common/framework/node.ml diff --git a/src/common/node0.ml b/src/common/framework/node0.ml similarity index 100% rename from src/common/node0.ml rename to src/common/framework/node0.ml diff --git a/src/common/updateCil0.ml b/src/common/incremental/updateCil0.ml similarity index 100% rename from src/common/updateCil0.ml rename to src/common/incremental/updateCil0.ml diff --git a/src/common/afterConfig.ml b/src/common/util/afterConfig.ml similarity index 100% rename from src/common/afterConfig.ml rename to src/common/util/afterConfig.ml diff --git a/src/common/cilType.ml b/src/common/util/cilType.ml similarity index 100% rename from src/common/cilType.ml rename to src/common/util/cilType.ml diff --git a/src/common/cilfacade.ml b/src/common/util/cilfacade.ml similarity index 100% rename from src/common/cilfacade.ml rename to src/common/util/cilfacade.ml diff --git a/src/common/cilfacade0.ml b/src/common/util/cilfacade0.ml similarity index 100% rename from src/common/cilfacade0.ml rename to src/common/util/cilfacade0.ml diff --git a/src/common/gobConfig.ml b/src/common/util/gobConfig.ml similarity index 100% rename from src/common/gobConfig.ml rename to src/common/util/gobConfig.ml diff --git a/src/common/gobFormat.ml b/src/common/util/gobFormat.ml similarity index 100% rename from src/common/gobFormat.ml rename to src/common/util/gobFormat.ml diff --git a/src/common/jsonSchema.ml b/src/common/util/jsonSchema.ml similarity index 100% rename from src/common/jsonSchema.ml rename to src/common/util/jsonSchema.ml diff --git a/src/common/lazyEval.ml b/src/common/util/lazyEval.ml similarity index 100% rename from src/common/lazyEval.ml rename to src/common/util/lazyEval.ml diff --git a/src/common/messageCategory.ml b/src/common/util/messageCategory.ml similarity index 100% rename from src/common/messageCategory.ml rename to src/common/util/messageCategory.ml diff --git a/src/common/messageUtil.ml b/src/common/util/messageUtil.ml similarity index 100% rename from src/common/messageUtil.ml rename to src/common/util/messageUtil.ml diff --git a/src/common/messages.ml b/src/common/util/messages.ml similarity index 100% rename from src/common/messages.ml rename to src/common/util/messages.ml diff --git a/src/common/options.ml b/src/common/util/options.ml similarity index 98% rename from src/common/options.ml rename to src/common/util/options.ml index c9bd41038f..3046f70809 100644 --- a/src/common/options.ml +++ b/src/common/util/options.ml @@ -1,4 +1,4 @@ -(** [src/common/options.schema.json] low-level access. *) +(** [src/common/util/options.schema.json] low-level access. *) open Json_schema diff --git a/src/common/options.schema.json b/src/common/util/options.schema.json similarity index 100% rename from src/common/options.schema.json rename to src/common/util/options.schema.json diff --git a/src/common/resettableLazy.ml b/src/common/util/resettableLazy.ml similarity index 100% rename from src/common/resettableLazy.ml rename to src/common/util/resettableLazy.ml diff --git a/src/common/resettableLazy.mli b/src/common/util/resettableLazy.mli similarity index 100% rename from src/common/resettableLazy.mli rename to src/common/util/resettableLazy.mli diff --git a/src/common/richVarinfo.ml b/src/common/util/richVarinfo.ml similarity index 100% rename from src/common/richVarinfo.ml rename to src/common/util/richVarinfo.ml diff --git a/src/common/richVarinfo.mli b/src/common/util/richVarinfo.mli similarity index 100% rename from src/common/richVarinfo.mli rename to src/common/util/richVarinfo.mli diff --git a/src/common/timing.ml b/src/common/util/timing.ml similarity index 100% rename from src/common/timing.ml rename to src/common/util/timing.ml diff --git a/src/common/tracing.ml b/src/common/util/tracing.ml similarity index 100% rename from src/common/tracing.ml rename to src/common/util/tracing.ml diff --git a/src/common/xmlUtil.ml b/src/common/util/xmlUtil.ml similarity index 100% rename from src/common/xmlUtil.ml rename to src/common/util/xmlUtil.ml diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a108058291..0b3829f11c 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -49,7 +49,7 @@ module VarQuery = VarQuery (** {2 Configuration} Runtime configuration is represented as JSON. - Options are specified and documented by the JSON schema [src/common/options.schema.json]. *) + Options are specified and documented by the JSON schema [src/common/util/options.schema.json]. *) module GobConfig = GobConfig module AfterConfig = AfterConfig From 956efd86e8f63aa75bc54808649354c4f7659e8b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 12 Oct 2023 10:39:24 +0300 Subject: [PATCH 398/628] Fix indentation in moved common library files --- src/common/domains/lattice.ml | 16 ++++++++-------- src/common/util/lazyEval.ml | 14 +++++++------- src/common/util/messageCategory.ml | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/common/domains/lattice.ml b/src/common/domains/lattice.ml index 4cdaa8fb9f..79455aea62 100644 --- a/src/common/domains/lattice.ml +++ b/src/common/domains/lattice.ml @@ -4,12 +4,12 @@ module Pretty = GoblintCil.Pretty (* module type Rel = -sig - type t - type relation = Less | Equal | Greater | Uncomparable - val rel : t -> t -> relation - val in_rel : t -> relation -> t -> bool -end *) + sig + type t + type relation = Less | Equal | Greater | Uncomparable + val rel : t -> t -> relation + val in_rel : t -> relation -> t -> bool + end *) (* partial order: elements might not be comparable and no bot/top -> join etc. might fail with exception Uncomparable *) exception Uncomparable @@ -324,14 +324,14 @@ struct match (x,y) with | (`Lifted x, `Lifted y) -> (try `Lifted (Base.widen x y) - with Uncomparable -> `Top) + with Uncomparable -> `Top) | _ -> y let narrow x y = match (x,y) with | (`Lifted x, `Lifted y) -> (try `Lifted (Base.narrow x y) - with Uncomparable -> `Bot) + with Uncomparable -> `Bot) | _ -> x end diff --git a/src/common/util/lazyEval.ml b/src/common/util/lazyEval.ml index e49a5f4693..9007cdd089 100644 --- a/src/common/util/lazyEval.ml +++ b/src/common/util/lazyEval.ml @@ -5,10 +5,10 @@ Node -> CilType -> Printable -> Goblintutil -> GobConfig -> Tracing -> Node *) module Make (M : sig - type t - type result - val eval : t -> result -end) : sig + type t + type result + val eval : t -> result + end) : sig type t val make : M.t -> t val force : t -> M.result @@ -20,8 +20,8 @@ end = struct let force l = match l.value with | `Closure arg -> - let v = M.eval arg in - l.value <- `Computed v; - v + let v = M.eval arg in + l.value <- `Computed v; + v | `Computed v -> v end diff --git a/src/common/util/messageCategory.ml b/src/common/util/messageCategory.ml index 1bb31d6d5b..c70b8faf5f 100644 --- a/src/common/util/messageCategory.ml +++ b/src/common/util/messageCategory.ml @@ -260,8 +260,8 @@ let categoryName = function | Behavior x -> behaviorName x | Integer x -> (match x with - | Overflow -> "Overflow"; - | DivByZero -> "DivByZero") + | Overflow -> "Overflow"; + | DivByZero -> "DivByZero") | Float -> "Float" From 59462c3e2614d79f63a4b8376b2304050f24f6d6 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 12 Oct 2023 10:52:20 +0300 Subject: [PATCH 399/628] Use batteries.unthreaded everywhere to avoid Gobview exception --- gobview | 2 +- src/common/dune | 2 +- src/util/std/dune | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gobview b/gobview index 41be36b548..42b07f8253 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit 41be36b54837b24e6de83740c34e810d3d1afdfb +Subproject commit 42b07f825316052ec030370daf0d00ebe28ec092 diff --git a/src/common/dune b/src/common/dune index b937ecdd02..c9ed9f9db2 100644 --- a/src/common/dune +++ b/src/common/dune @@ -5,7 +5,7 @@ (public_name goblint.common) (wrapped false) ; TODO: wrap (libraries - batteries + batteries.unthreaded zarith goblint_std goblint-cil diff --git a/src/util/std/dune b/src/util/std/dune index c85710a8d6..c6961a1725 100644 --- a/src/util/std/dune +++ b/src/util/std/dune @@ -4,7 +4,7 @@ (name goblint_std) (public_name goblint.std) (libraries - batteries + batteries.unthreaded zarith goblint-cil fpath From a0b376bfa6c587e293172c6d86aa2a1085ddb5c3 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 12 Oct 2023 11:40:03 +0300 Subject: [PATCH 400/628] Add odoc page for package --- src/common/common.mld | 74 +++++++++++++++++++++++++++++++++++++++++++ src/common/dune | 1 + src/dune | 2 ++ src/goblint_lib.ml | 1 + src/index.mld | 51 +++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 src/common/common.mld create mode 100644 src/index.mld diff --git a/src/common/common.mld b/src/common/common.mld new file mode 100644 index 0000000000..662c789572 --- /dev/null +++ b/src/common/common.mld @@ -0,0 +1,74 @@ +{0 Library goblint.common} +This library is unwrapped and provides the following top-level modules. +For better context, see {!Goblint_lib} which also documents these modules. + + +{1 Framework} + +{2 CFG} +{!modules: +Node +Edge +MyCFG +} + +{2 Specification} +{!modules: +AnalysisState +ControlSpecC +} + +{2 Configuration} +{!modules: +GobConfig +AfterConfig +JsonSchema +Options +} + + +{1 Domains} +{!modules: +Printable +Lattice +} + +{2 Analysis-specific} + +{3 Other} +{!modules:Basetype} + + +{1 I/O} +{!modules: +Messages +Tracing +} + + +{1 Utilities} +{!modules:Timing} + +{2 General} +{!modules: +LazyEval +ResettableLazy +MessageUtil +XmlUtil +} + +{2 CIL} +{!modules: +CilType +Cilfacade +RichVarinfo +} + + +{1 Library extensions} + +{2 Standard library} +{!modules:GobFormat} + +{2 Other libraries} +{!modules:MyCheck} diff --git a/src/common/dune b/src/common/dune index c9ed9f9db2..c8f1564782 100644 --- a/src/common/dune +++ b/src/common/dune @@ -26,3 +26,4 @@ ppx_blob)) (preprocessor_deps (file util/options.schema.json))) +(documentation) diff --git a/src/dune b/src/dune index df19f85340..acd5348acb 100644 --- a/src/dune +++ b/src/dune @@ -125,3 +125,5 @@ (flags (:standard -warn-error -A -w -unused-var-strict -w -unused-functor-parameter -w +9)) ; https://dune.readthedocs.io/en/stable/faq.html#how-to-make-warnings-non-fatal ) ) + +(documentation) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 0b3829f11c..dadeb2cda1 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -1,3 +1,4 @@ +(** Main library. *) (** {1 Framework} *) diff --git a/src/index.mld b/src/index.mld new file mode 100644 index 0000000000..2afbbc97ae --- /dev/null +++ b/src/index.mld @@ -0,0 +1,51 @@ +{0 goblint index} + +{1 Goblint} +The following libraries make up Goblint's main codebase. + +{2 Library goblint.lib} +{!modules:Goblint_lib} +This library currently contains the majority of Goblint and is in the process of being split into smaller libraries. + +{2 Library goblint.common} +This {{!page-common}unwrapped library} contains various common modules extracted from {!Goblint_lib}. + + +{1 Library extensions} +The following libraries provide extensions to other OCaml libraries. + +{2 Library goblint.std} +{!modules:Goblint_std} + + +{1 Package utilities} +The following libraries provide [goblint] package metadata for executables. + +{2 Library goblint.build-info} +{!modules:Goblint_build_info} +This library is virtual and has the following implementations +- goblint.build-info.dune for native executables, +- goblint.build-info.js for js_of_ocaml executables. + +{2 Library goblint.sites} +{!modules:Goblint_sites} +This library is virtual and has the following implementations +- goblint.sites.dune for native executables, +- goblint.sites.js for js_of_ocaml executables. + + +{1 Independent utilities} +The following libraries provide utilities which are completely independent of Goblint. + +{2 Library goblint.backtrace} +{!modules:Goblint_backtrace} + +{2 Library goblint.timing} +{!modules:Goblint_timing} + + +{1 Vendored} +The following libraries are vendored in Goblint. + +{2 Library goblint.zarith.mlgmpidl} +{!modules:Z_mlgmpidl} From 47cce4f58634308a4326683ab8031499eab2e9e0 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 12 Oct 2023 11:41:24 +0300 Subject: [PATCH 401/628] Use goblint library documentation page in Readthedocs --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 558c381e66..428e28078d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,7 +30,7 @@ nav: - 👶 Your first analysis: developer-guide/firstanalysis.md - 🏫 Extending library: developer-guide/extending-library.md - 📢 Messaging: developer-guide/messaging.md - - 🗃️ API reference: https://goblint.github.io/analyzer/ + - 🗃️ API reference: https://goblint.github.io/analyzer/goblint/ - 🚨 Testing: developer-guide/testing.md - 🪲 Debugging: developer-guide/debugging.md - 📉 Profiling: developer-guide/profiling.md From 7ebf97e9ef2f9167898f40bd304880d48f10cb08 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 12 Oct 2023 15:38:49 +0300 Subject: [PATCH 402/628] Fix scripts/goblint-lib-modules.py --- scripts/goblint-lib-modules.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/scripts/goblint-lib-modules.py b/scripts/goblint-lib-modules.py index 342f9a76bd..5f02271616 100755 --- a/scripts/goblint-lib-modules.py +++ b/scripts/goblint-lib-modules.py @@ -6,16 +6,20 @@ src_root_path = Path("./src") -goblint_lib_path = src_root_path / "goblint_lib.ml" +goblint_lib_paths = [ + src_root_path / "goblint_lib.ml", + src_root_path / "util" / "std" / "goblint_std.ml", +] goblint_lib_modules = set() -with goblint_lib_path.open() as goblint_lib_file: - for line in goblint_lib_file: - line = line.strip() - m = re.match(r"module (.*) = .*", line) - if m is not None: - module_name = m.group(1) - goblint_lib_modules.add(module_name) +for goblint_lib_path in goblint_lib_paths: + with goblint_lib_path.open() as goblint_lib_file: + for line in goblint_lib_file: + line = line.strip() + m = re.match(r"module (.*) = .*", line) + if m is not None: + module_name = m.group(1) + goblint_lib_modules.add(module_name) src_vendor_path = src_root_path / "vendor" exclude_module_names = set([ @@ -29,15 +33,21 @@ "Mainspec", # libraries + "Goblint_std", "Goblint_timing", "Goblint_backtrace", "Goblint_sites", "Goblint_build_info", + "Dune_build_info", "MessageCategory", # included in Messages "PreValueDomain", # included in ValueDomain "SpecCore", # spec stuff "SpecUtil", # spec stuff + + "ConfigVersion", + "ConfigProfile", + "ConfigOcaml", ]) src_modules = set() From 910a11f903e217efcc946d7d9d988c50575cd3ae Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 14:50:36 +0200 Subject: [PATCH 403/628] Activate `cil.addNestedScopeAttr` when `memOutOfBounds` analysis is active --- src/maingoblint.ml | 1 + tests/regression/74-invalid_deref/08-memset-memcpy-array.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 97f35214be..b5998df2d1 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -135,6 +135,7 @@ let check_arguments () = if get_bool "allfuns" && not (get_bool "exp.earlyglobs") then (set_bool "exp.earlyglobs" true; warn "allfuns enables exp.earlyglobs.\n"); if not @@ List.mem "escape" @@ get_string_list "ana.activated" then warn "Without thread escape analysis, every local variable whose address is taken is considered escaped, i.e., global!"; if List.mem "malloc_null" @@ get_string_list "ana.activated" && not @@ get_bool "sem.malloc.fail" then (set_bool "sem.malloc.fail" true; warn "The malloc_null analysis enables sem.malloc.fail."); + if List.mem "memOutOfBounds" @@ get_string_list "ana.activated" && not @@ get_bool "cil.addNestedScopeAttr" then (set_bool "cil.addNestedScopeAttr" true; warn "The memOutOfBounds analysis enables cil.addNestedScopeAttr."); if get_bool "ana.base.context.int" && not (get_bool "ana.base.context.non-ptr") then (set_bool "ana.base.context.int" false; warn "ana.base.context.int implicitly disabled by ana.base.context.non-ptr"); (* order matters: non-ptr=false, int=true -> int=false cascades to interval=false with warning *) if get_bool "ana.base.context.interval" && not (get_bool "ana.base.context.int") then (set_bool "ana.base.context.interval" false; warn "ana.base.context.interval implicitly disabled by ana.base.context.int"); diff --git a/tests/regression/74-invalid_deref/08-memset-memcpy-array.c b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c index f231ba2dc4..210a61d459 100644 --- a/tests/regression/74-invalid_deref/08-memset-memcpy-array.c +++ b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c @@ -6,13 +6,14 @@ int main(int argc, char const *argv[]) { int arr[42]; // Size should be 168 bytes (with 4 byte ints) int *b = arr; - + int random; + memset(b, 0, 168); //NOWARN memset(b, 0, sizeof(arr)); //NOWARN memset(b, 0, 169); //WARN memset(b, 0, sizeof(arr) + 1); //WARN - + int *c = malloc(sizeof(arr)); // Size should be 168 bytes (with 4 byte ints) memcpy(b, c, 168); //NOWARN memcpy(b, c, sizeof(arr)); //NOWARN @@ -26,7 +27,7 @@ int main(int argc, char const *argv[]) { memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN } else if (*(argv + 5)) { - int random = rand(); + random = rand(); b = &random; memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN From 44b44928668346c722ca23fb448c6da73f471276 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 15:37:25 +0200 Subject: [PATCH 404/628] Issue non-termination warning for `longjmp` calls --- src/framework/constraints.ml | 9 +++++++++ tests/regression/78-termination/49-longjmp.c | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/regression/78-termination/49-longjmp.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 924794b9ce..cf439f2c45 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1684,6 +1684,15 @@ struct ) in List.iter handle_path (S.paths_as_set conv_ctx); + if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( + AnalysisState.svcomp_may_not_terminate := true; + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Longjmp)", + None + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); S.D.bot () | _ -> S.special conv_ctx lv f args let threadenter ctx = S.threadenter (conv ctx) diff --git a/tests/regression/78-termination/49-longjmp.c b/tests/regression/78-termination/49-longjmp.c new file mode 100644 index 0000000000..be13cb286c --- /dev/null +++ b/tests/regression/78-termination/49-longjmp.c @@ -0,0 +1,11 @@ +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +jmp_buf buf; +int main() +{ + if(setjmp(buf)) { + + } + + longjmp(buf, 1); +} From ea38918e9e3247c622d8d1acf754f7ea021e6f9c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 15:42:42 +0200 Subject: [PATCH 405/628] Include termination tests into `coverage` and `unlocked` --- .github/workflows/coverage.yml | 3 +++ .github/workflows/unlocked.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5635ebbeea..0208af7c7a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -65,6 +65,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression diff --git a/.github/workflows/unlocked.yml b/.github/workflows/unlocked.yml index 6c23c7cdd4..22e1417ea4 100644 --- a/.github/workflows/unlocked.yml +++ b/.github/workflows/unlocked.yml @@ -92,6 +92,9 @@ jobs: if: ${{ matrix.apron }} run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From e28495363a932e40d4d0ec519e74e804aaaa55da Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:39:27 +0200 Subject: [PATCH 406/628] Simplify global invariant Co-authored-by: Simmo Saan --- src/framework/analyses.ml | 16 +++++++++ src/framework/constraints.ml | 70 ++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index bb2170509d..3426f98675 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -88,6 +88,22 @@ struct | `Right _ -> true end +module GVarFC (V:SpecSysVar) (C:Printable.S) = +struct + include Printable.Either (V) (Printable.Prod (CilType.Fundec) (C)) + let name () = "FromSpec" + let spec x = `Left x + let call (x, c) = `Right (x, c) + + (* from Basetype.Variables *) + let var_id = show + let node _ = MyCFG.Function Cil.dummyFunDec + let pretty_trace = pretty + let is_write_only = function + | `Left x -> V.is_write_only x + | `Right _ -> true +end + module GVarG (G: Lattice.S) (C: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index cf439f2c45..038068ea0d 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1723,36 +1723,35 @@ module RecursionTermLifter (S: Spec) struct include S - (* contains all the callee fundecs*) - module V = GVarF(S.V) + (* contains all the callee fundecs and contexts *) + module V = GVarFC(S.V)(S.C) - (* Tuple containing the fundec and context of the caller *) - module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) + (* Tuple containing the fundec and context of a caller *) + module Call = Printable.Prod (CilType.Fundec) (S.C) (* Set containing multiple caller tuples *) - module CallGraphSet = SetDomain.Make (CallGraphTuple) - - (* Mapping from the callee context to the set of all caller tuples*) - module CallGraphMap = MapDomain.MapBot (S.C) (CallGraphSet) + module CallerSet = SetDomain.Make (Call) module G = struct - include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) + include Lattice.Lift2 (G) (CallerSet) (Printable.DefaultNames) let spec = function | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTermLifter.spec" - let callGraph = function - | `Bot -> CallGraphMap.bot () + + let callers = function + | `Bot -> CallerSet.bot () | `Lifted2 x -> x | _ -> failwith "RecursionTermLifter.callGraph" + let create_spec spec = `Lifted1 spec - let create_callGraph callGraph = `Lifted2 callGraph + let create_singleton_caller caller = `Lifted2 (CallerSet.singleton caller) let printXml f = function | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CallerSet.printXml x | x -> BatPrintf.fprintf f "%a" printXml x end @@ -1785,19 +1784,15 @@ struct else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap = G.callGraph (ctx.global (fundec_e_typeV)) in - let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in - CallGraphSet.iter (fun to_call -> + let gvar = V.call (fundec_e, context_e) in + let callers = G.callers (ctx.global gvar) in + CallerSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; end in - let gmap = G.callGraph (ctx.global (v)) in - CallGraphMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) + let callers = G.callers (ctx.global v) in + CallerSet.iter (iter_call LS.empty) callers let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1825,30 +1820,27 @@ struct let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - (* c = context - t = set of tuples (fundec * context) - *) - let side_context sideg f c t = - if !AnalysisState.postsolving then - sideg (V.contexts f) (G.create_callGraph (CallGraphMap.singleton (c) (t))) + + let record_call sideg callee caller = + sideg (V.call callee) (G.create_singleton_caller caller) let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) let combine_env ctx r fe f args fc es f_ask = - if !AnalysisState.postsolving then - let c_r: S.C.t = ctx.context () in (*Caller context*) + if !AnalysisState.postsolving then ( + let c_r: S.C.t = ctx.context () in (* Caller context *) let nodeF = ctx.node in - let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) - let c_e: S.C.t = Option.get fc in (*Callee context*) - let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = CallGraphSet.singleton (tup) in - side_context ctx.sideg fd_e (c_e) t; - S.combine_env (conv ctx) r fe f args fc es f_ask - else - S.combine_env (conv ctx) r fe f args fc es f_ask + let fd_r : fundec = Node.find_fundec nodeF in (* Caller fundec *) + let caller: (fundec * S.C.t) = (fd_r, c_r) in + let c_e: S.C.t = Option.get fc in (* Callee context *) + let fd_e : fundec = f in (* Callee fundec *) + let callee = (fd_e, c_e) in + record_call ctx.sideg callee caller + ); + S.combine_env (conv ctx) r fe f args fc es f_ask + let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) let threadenter ctx = S.threadenter (conv ctx) From 7f3cadfaea69592fe03fb311613b14efc0cf4718 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:42:09 +0200 Subject: [PATCH 407/628] Adapt comments to simplified global invariant --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 038068ea0d..b4b72146d5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1710,14 +1710,14 @@ module RecursionTermLifter (S: Spec) and module C = S.C = (* two global invariants: - - V -> G + - S.V -> S.G Needed to store the previously built global invariants - - fundec -> Map (S.C) (Set (fundec * S.C)) - The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + - fundec * S.C -> (Set (fundec * S.C)) + The second global invariant maps from the callee fundec and context to a set of caller fundecs and contexts. This structure therefore stores the context-sensitive call graph. For example: let the function f in context c call function g in context c'. - In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} + In the global invariant structure it would be stored like this: (g,c') -> {(f, c)} *) struct From 515a8bd2f300fdfe2134d3608fab52c9ca56a6f4 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:55:08 +0200 Subject: [PATCH 408/628] Simplify cycle detection --- src/framework/constraints.ml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index b4b72146d5..ad35ef2633 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1764,35 +1764,33 @@ struct sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_spec g)); } - let cycleDetection ctx v v' = + let cycleDetection ctx call = let module LH = Hashtbl.Make (Printable.Prod (CilType.Fundec) (S.C)) in let module LS = Set.Make (Printable.Prod (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = - let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) + let rec iter_call (path_visited_calls: LS.t) ((fundec, _) as call) = if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec, Some (M.Location.CilLocation fundec.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let gvar = V.call (fundec_e, context_e) in + let gvar = V.call call in let callers = G.callers (ctx.global gvar) in CallerSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; end in - let callers = G.callers (ctx.global v) in - CallerSet.iter (iter_call LS.empty) callers + iter_call LS.empty call let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1804,7 +1802,7 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) + | `Right call -> cycleDetection ctx call (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) end | InvariantGlobal v -> let v: V.t = Obj.obj v in From b3016ff054bd714d7c9f9527a25226b2a1f4f06b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 17:05:15 +0200 Subject: [PATCH 409/628] Failwith meaningful message for invaliud calls to `__goblint_bounded` --- src/analyses/loopTermination.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfc600f830..61034a57c0 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -72,9 +72,7 @@ struct M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () with Not_found -> - (* This should not happen as long as __goblint_bounded is only used - * for this analysis. *) - ()) + failwith "Encountered a call to __goblint_bounded with an unknown loop counter variable.") | _ -> () else () From fe369158efccfe1c531429f18e03b79b49dab38e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:04:13 +0200 Subject: [PATCH 410/628] Add `AnalysisStateUtil` to `goblint_lib.ml` (#1201) --- src/goblint_lib.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index dadeb2cda1..a71a0c9684 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -23,6 +23,7 @@ module CfgTools = CfgTools module Analyses = Analyses module Constraints = Constraints module AnalysisState = AnalysisState +module AnalysisStateUtil = AnalysisStateUtil module ControlSpecC = ControlSpecC (** Master control program (MCP) is the analysis specification for the dynamic product of activated analyses. *) From 14c3ead5c61242b46be22b2c100082f66454d95e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:19:33 +0200 Subject: [PATCH 411/628] Merge branch 'master' into term --- scripts/goblint-lib-modules.py | 26 ++- src/analyses/base.ml | 117 ++++++++++-- src/analyses/memLeak.ml | 16 +- src/analyses/memOutOfBounds.ml | 171 ++++++++++++++---- src/analyses/useAfterFree.ml | 43 ++--- src/autoTune.ml | 40 +++- src/cdomains/arrayDomain.ml | 5 + src/common/framework/analysisState.ml | 5 +- src/common/util/cilfacade.ml | 3 +- src/common/util/options.schema.json | 6 + src/goblint_lib.ml | 1 + src/maingoblint.ml | 3 + src/util/analysisStateUtil.ml | 13 ++ src/witness/svcomp.ml | 2 + src/witness/svcompSpec.ml | 26 ++- src/witness/witness.ml | 45 +---- .../01-oob-heap-simple.c | 0 .../02-conditional-uaf.c | 0 .../03-nested-ptr-uaf.c | 0 .../04-function-call-uaf.c | 0 .../05-oob-implicit-deref.c | 0 .../06-memset-oob.c | 0 .../07-memcpy-oob.c | 4 +- .../08-memset-memcpy-array.c | 7 +- .../09-juliet-uaf.c | 0 .../74-invalid_deref/10-oob-two-loops.c | 22 +++ .../74-invalid_deref/11-address-offset-oob.c | 16 ++ .../74-invalid_deref/12-memcpy-oob-src.c | 43 +++++ .../13-mem-oob-packed-struct.c | 33 ++++ .../14-alloca-uaf.c | 0 .../15-juliet-uaf-global-var.c | 22 +++ .../74-invalid_deref/16-uaf-packed-struct.c | 40 ++++ .../74-invalid_deref/17-scopes-no-static.c | 22 +++ .../18-simple-uaf.c} | 0 .../19-oob-stack-simple.c} | 0 .../74-invalid_deref/20-scopes-global-var.c | 29 +++ .../21-oob-loop.c} | 0 .../74-invalid_deref/22-scopes-static.c | 52 ++++++ .../23-oob-deref-after-ptr-arith.c} | 0 .../24-uaf-free-in-wrapper-fun.c} | 0 .../25-uaf-struct.c} | 0 .../26-memset-memcpy-addr-offs.c} | 0 .../27-wrapper-funs-uaf.c} | 0 .../28-multi-threaded-uaf.c} | 0 ...9-multi-threaded-uaf-with-joined-thread.c} | 0 .../01-invalid-dealloc-simple.c | 0 .../02-invalid-dealloc-struct.c | 0 .../03-invalid-dealloc-array.c | 0 .../04-invalid-realloc.c | 0 .../05-free-at-offset.c | 0 .../06-realloc-at-offset.c | 0 .../07-free-at-struct-offset.c | 0 .../08-itc-no-double-free.c | 0 .../09-juliet-invalid-dealloc-alloca.c | 0 .../10-invalid-dealloc-union.c | 42 +++++ .../11-itc-double-free.c} | 0 .../12-realloc-at-struct-offset.c} | 0 .../13-juliet-double-free.c} | 0 tests/sv-comp/valid-memcleanup.prp | 2 + 59 files changed, 707 insertions(+), 149 deletions(-) create mode 100644 src/util/analysisStateUtil.ml rename tests/regression/{77-mem-oob => 74-invalid_deref}/01-oob-heap-simple.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/02-conditional-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/03-nested-ptr-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/04-function-call-uaf.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/05-oob-implicit-deref.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/06-memset-oob.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/07-memcpy-oob.c (94%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/08-memset-memcpy-array.c (96%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/09-juliet-uaf.c (100%) create mode 100644 tests/regression/74-invalid_deref/10-oob-two-loops.c create mode 100644 tests/regression/74-invalid_deref/11-address-offset-oob.c create mode 100644 tests/regression/74-invalid_deref/12-memcpy-oob-src.c create mode 100644 tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c rename tests/regression/{74-use_after_free => 74-invalid_deref}/14-alloca-uaf.c (100%) create mode 100644 tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c create mode 100644 tests/regression/74-invalid_deref/16-uaf-packed-struct.c create mode 100644 tests/regression/74-invalid_deref/17-scopes-no-static.c rename tests/regression/{74-use_after_free/01-simple-uaf.c => 74-invalid_deref/18-simple-uaf.c} (100%) rename tests/regression/{77-mem-oob/02-oob-stack-simple.c => 74-invalid_deref/19-oob-stack-simple.c} (100%) create mode 100644 tests/regression/74-invalid_deref/20-scopes-global-var.c rename tests/regression/{77-mem-oob/03-oob-loop.c => 74-invalid_deref/21-oob-loop.c} (100%) create mode 100644 tests/regression/74-invalid_deref/22-scopes-static.c rename tests/regression/{77-mem-oob/04-oob-deref-after-ptr-arith.c => 74-invalid_deref/23-oob-deref-after-ptr-arith.c} (100%) rename tests/regression/{74-use_after_free/05-uaf-free-in-wrapper-fun.c => 74-invalid_deref/24-uaf-free-in-wrapper-fun.c} (100%) rename tests/regression/{74-use_after_free/06-uaf-struct.c => 74-invalid_deref/25-uaf-struct.c} (100%) rename tests/regression/{77-mem-oob/09-memset-memcpy-addr-offs.c => 74-invalid_deref/26-memset-memcpy-addr-offs.c} (100%) rename tests/regression/{74-use_after_free/11-wrapper-funs-uaf.c => 74-invalid_deref/27-wrapper-funs-uaf.c} (100%) rename tests/regression/{74-use_after_free/12-multi-threaded-uaf.c => 74-invalid_deref/28-multi-threaded-uaf.c} (100%) rename tests/regression/{74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c => 74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c} (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/01-invalid-dealloc-simple.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/02-invalid-dealloc-struct.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/03-invalid-dealloc-array.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/04-invalid-realloc.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/05-free-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/06-realloc-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/07-free-at-struct-offset.c (100%) rename tests/regression/{74-use_after_free => 75-invalid_free}/08-itc-no-double-free.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/09-juliet-invalid-dealloc-alloca.c (100%) create mode 100644 tests/regression/75-invalid_free/10-invalid-dealloc-union.c rename tests/regression/{74-use_after_free/07-itc-double-free.c => 75-invalid_free/11-itc-double-free.c} (100%) rename tests/regression/{75-invalid_dealloc/08-realloc-at-struct-offset.c => 75-invalid_free/12-realloc-at-struct-offset.c} (100%) rename tests/regression/{74-use_after_free/10-juliet-double-free.c => 75-invalid_free/13-juliet-double-free.c} (100%) create mode 100644 tests/sv-comp/valid-memcleanup.prp diff --git a/scripts/goblint-lib-modules.py b/scripts/goblint-lib-modules.py index 342f9a76bd..5f02271616 100755 --- a/scripts/goblint-lib-modules.py +++ b/scripts/goblint-lib-modules.py @@ -6,16 +6,20 @@ src_root_path = Path("./src") -goblint_lib_path = src_root_path / "goblint_lib.ml" +goblint_lib_paths = [ + src_root_path / "goblint_lib.ml", + src_root_path / "util" / "std" / "goblint_std.ml", +] goblint_lib_modules = set() -with goblint_lib_path.open() as goblint_lib_file: - for line in goblint_lib_file: - line = line.strip() - m = re.match(r"module (.*) = .*", line) - if m is not None: - module_name = m.group(1) - goblint_lib_modules.add(module_name) +for goblint_lib_path in goblint_lib_paths: + with goblint_lib_path.open() as goblint_lib_file: + for line in goblint_lib_file: + line = line.strip() + m = re.match(r"module (.*) = .*", line) + if m is not None: + module_name = m.group(1) + goblint_lib_modules.add(module_name) src_vendor_path = src_root_path / "vendor" exclude_module_names = set([ @@ -29,15 +33,21 @@ "Mainspec", # libraries + "Goblint_std", "Goblint_timing", "Goblint_backtrace", "Goblint_sites", "Goblint_build_info", + "Dune_build_info", "MessageCategory", # included in Messages "PreValueDomain", # included in ValueDomain "SpecCore", # spec stuff "SpecUtil", # spec stuff + + "ConfigVersion", + "ConfigProfile", + "ConfigOcaml", ]) src_modules = set() diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 7b87d3ff51..908dc88401 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1043,10 +1043,24 @@ struct | Mem n, ofs -> begin match (eval_rv a gs st n) with | Address adr -> - (if AD.is_null adr - then M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" - else if AD.may_be_null adr - then M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer"); + ( + if AD.is_null adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" + ) + else if AD.may_be_null adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" + ); + (* Warn if any of the addresses contains a non-local and non-global variable *) + if AD.exists (function + | AD.Addr.Addr (v, _) -> not (CPA.mem v st.cpa) && not (is_global a v) + | _ -> false + ) adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval + ) + ); AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr | _ -> M.debug ~category:Analyzer "Failed evaluating %a to lvalue" d_lval lval; @@ -2023,14 +2037,78 @@ struct in match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with | Address a -> - if AD.is_top a then + if AD.is_top a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname - else if has_non_heap_var a then + ) else if has_non_heap_var a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr - else if has_non_zero_offset a then + ) else if has_non_zero_offset a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr - | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname + ) + | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidFree; + M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname + + let points_to_heap_only ctx ptr = + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a)-> + Queries.AD.for_all (function + | Addr (v, _) -> ctx.ask (Queries.IsHeapVar v) + | _ -> false + ) a + | _ -> false + let get_size_of_ptr_target ctx ptr = + let intdom_of_int x = + ID.of_int (Cilfacade.ptrdiff_ikind ()) (Z.of_int x) + in + let size_of_type_in_bytes typ = + let typ_size_in_bytes = (bitsSizeOf typ) / 8 in + intdom_of_int typ_size_in_bytes + in + if points_to_heap_only ctx ptr then + (* Ask for BlobSize from the base address (the second component being set to true) in order to avoid BlobSize giving us bot *) + ctx.ask (Queries.BlobSize {exp = ptr; base_address = true}) + else + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a) -> + let pts_list = Queries.AD.elements a in + let pts_elems_to_sizes (addr: Queries.AD.elt) = + begin match addr with + | Addr (v, _) -> + begin match v.vtype with + | TArray (item_typ, _, _) -> + let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in + begin match ctx.ask (Queries.EvalLength ptr) with + | `Lifted arr_len -> + let arr_len_casted = ID.cast_to (Cilfacade.ptrdiff_ikind ()) arr_len in + begin + try `Lifted (ID.mul item_typ_size_in_bytes arr_len_casted) + with IntDomain.ArithmeticOnIntegerBot _ -> `Bot + end + | `Bot -> `Bot + | `Top -> `Top + end + | _ -> + let type_size_in_bytes = size_of_type_in_bytes v.vtype in + `Lifted type_size_in_bytes + end + | _ -> `Top + end + in + (* Map each points-to-set element to its size *) + let pts_sizes = List.map pts_elems_to_sizes pts_list in + (* Take the smallest of all sizes that ptr's contents may have *) + begin match pts_sizes with + | [] -> `Bot + | [x] -> x + | x::xs -> List.fold_left ValueDomainQueries.ID.join x xs + end + | _ -> + (M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let special ctx (lv:lval option) (f: varinfo) (args: exp list) = let invalidate_ret_lv st = match lv with @@ -2050,13 +2128,28 @@ struct let st: store = ctx.local in let gs = ctx.global in let desc = LF.find f in - let memory_copying dst src = + let memory_copying dst src n = + let dest_size = get_size_of_ptr_target ctx dst in + let n_intdom = Option.map_default (fun exp -> ctx.ask (Queries.EvalInt exp)) `Bot n in + let dest_size_equal_n = + match dest_size, n_intdom with + | `Lifted ds, `Lifted n -> + let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in + let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in + let ds_eq_n = + begin try ID.eq casted_ds casted_n + with IntDomain.ArithmeticOnIntegerBot _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + end + in + Option.default false (ID.to_bool ds_eq_n) + | _ -> false + in let dest_a, dest_typ = addr_type_of_exp dst in let src_lval = mkMem ~addr:(Cil.stripCasts src) ~off:NoOffset in let src_typ = eval_lv (Analyses.ask_of_ctx ctx) gs st src_lval |> AD.type_of in (* when src and destination type coincide, take value from the source, otherwise use top *) - let value = if typeSig dest_typ = typeSig src_typ then + let value = if (typeSig dest_typ = typeSig src_typ) && dest_size_equal_n then let src_cast_lval = mkMem ~addr:(Cilfacade.mkCast ~e:src ~newt:(TPtr (dest_typ, []))) ~off:NoOffset in eval_rv (Analyses.ask_of_ctx ctx) gs st (Lval src_cast_lval) else @@ -2117,13 +2210,13 @@ struct let value = VD.zero_init_value dest_typ in set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value | Memcpy { dest = dst; src; n; }, _ -> (* TODO: use n *) - memory_copying dst src + memory_copying dst src (Some n) (* strcpy(dest, src); *) | Strcpy { dest = dst; src; n = None }, _ -> let dest_a, dest_typ = addr_type_of_exp dst in (* when dest surely isn't a string literal, try copying src to dest *) if AD.string_writing_defined dest_a then - memory_copying dst src + memory_copying dst src None else (* else return top (after a warning was issued) *) set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 8576096dfe..dbaa2d69fc 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) @@ -19,15 +20,24 @@ struct (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then + if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" + ) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in if not @@ D.is_empty state then match assert_exp_imprecise, exp with - | true, Some exp -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state - | _ -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state + | true, Some exp -> + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state + | _ -> + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index c715a1d2e7..fc60352298 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module AS = AnalysisState module VDQ = ValueDomainQueries @@ -88,6 +89,10 @@ struct let pts_elems_to_sizes (addr: Queries.AD.elt) = begin match addr with | Addr (v, _) -> + if hasAttribute "goblint_cil_nested" v.vattr then ( + set_mem_safety_flag InvalidDeref; + M.warn "Var %a is potentially accessed out-of-scope. Invalid memory access may occur" CilType.Varinfo.pretty v + ); begin match v.vtype with | TArray (item_typ, _, _) -> let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in @@ -117,8 +122,9 @@ struct | x::xs -> List.fold_left VDQ.ID.join x xs end | _ -> - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; - `Top + (set_mem_safety_flag InvalidDeref; + M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let get_ptr_deref_type ptr_typ = match ptr_typ with @@ -159,6 +165,50 @@ struct with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () end + let cil_offs_to_idx ctx typ offs = + (* TODO: Some duplication with convert_offset in base.ml, unclear how to immediately get more reuse *) + let rec convert_offset (ofs: offset) = + match ofs with + | NoOffset -> `NoOffset + | Field (fld, ofs) -> `Field (fld, convert_offset ofs) + | Index (exp, ofs) when CilType.Exp.equal exp Offset.Index.Exp.any -> (* special offset added by convertToQueryLval *) + `Index (ID.top (), convert_offset ofs) + | Index (exp, ofs) -> + let i = match ctx.ask (Queries.EvalInt exp) with + | `Lifted x -> x + | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + in + `Index (i, convert_offset ofs) + in + PreValueDomain.Offs.to_index (convert_offset offs) + + + let check_unknown_addr_deref ctx ptr = + let may_contain_unknown_addr = + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.may_be_unknown a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could potentially evaluate to the unknown address *) + | _ -> true + in + if may_contain_unknown_addr then begin + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior (Undefined Other)) "Pointer %a contains an unknown address. Invalid dereference may occur" d_exp ptr + end + + let ptr_only_has_str_addr ctx ptr = + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could all sorts of things and not only string addresses *) + | _ -> false + let rec get_addr_offs ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with | a when not (VDQ.AD.is_top a) -> @@ -174,22 +224,25 @@ struct | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a bot address offset. An invalid memory access may occur" d_exp ptr ) else if VDQ.AD.exists (function - | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o + | Addr (_, o) -> ID.is_top_of (Cilfacade.ptrdiff_ikind ()) (offs_to_idx t o) | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a top address offset. An invalid memory access may occur" d_exp ptr ); - (* Offset should be the same for all elements in the points-to set *) - (* Hence, we can just pick one element and obtain its offset *) - begin match VDQ.AD.choose a with - | Addr (_, o) -> offs_to_idx t o - | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + (* Get the address offsets of all points-to set elements *) + let addr_offsets = + VDQ.AD.filter (function Addr (v, o) -> true | _ -> false) a + |> VDQ.AD.to_mval + |> List.map (fun (_, o) -> offs_to_idx t o) + in + begin match addr_offsets with + | [] -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + | [x] -> x + | x::xs -> List.fold_left ID.join x xs end end | None -> @@ -197,18 +250,55 @@ struct ID.top_of @@ Cilfacade.ptrdiff_ikind () end | _ -> + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; ID.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = - if not @@ lval_contains_a_ptr lval then () + (* If the lval does not contain a pointer or if it does contain a pointer, but only points to string addresses, then no need to WARN *) + if (not @@ lval_contains_a_ptr lval) || ptr_only_has_str_addr ctx (Lval lval) then () else (* If the lval doesn't indicate an explicit dereference, we still need to check for an implicit dereference *) (* An implicit dereference is, e.g., printf("%p", ptr), where ptr is a pointer *) match lval, is_implicitly_derefed with | (Var _, _), false -> () | (Var v, _), true -> check_no_binop_deref ctx (Lval lval) - | (Mem e, _), _ -> + | (Mem e, o), _ -> + let ptr_deref_type = get_ptr_deref_type @@ typeOf e in + let offs_intdom = begin match ptr_deref_type with + | Some t -> cil_offs_to_idx ctx t o + | None -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end in + let e_size = get_size_of_ptr_target ctx e in + let () = begin match e_size with + | `Top -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is top. Out-of-bounds memory access may occur" d_exp e) + | `Bot -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is bot. Out-of-bounds memory access may occur" d_exp e) + | `Lifted es -> + let casted_es = ID.cast_to (Cilfacade.ptrdiff_ikind ()) es in + let one = intdom_of_int 1 in + let casted_es = ID.sub casted_es one in + let casted_offs = ID.cast_to (Cilfacade.ptrdiff_ikind ()) offs_intdom in + let ptr_size_lt_offs = + begin try ID.lt casted_es casted_offs + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + in + let behavior = Undefined MemoryOutOfBoundsAccess in + let cwe_number = 823 in + begin match ID.to_bool ptr_size_lt_offs with + | Some true -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of lval dereference expression is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" ID.pretty casted_es ID.pretty casted_offs) + | Some false -> () + | None -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of lval dereference expression (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_es ID.pretty casted_offs) + end + end in begin match e with | Lval (Var v, _) as lval_exp -> check_no_binop_deref ctx lval_exp | BinOp (binop, e1, e2, t) when binop = PlusPI || binop = MinusPI || binop = IndexPI -> @@ -219,6 +309,7 @@ struct end and check_no_binop_deref ctx lval_exp = + check_unknown_addr_deref ctx lval_exp; let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in let ptr_size = get_size_of_ptr_target ctx lval_exp in @@ -229,10 +320,10 @@ struct | Some t -> begin match ptr_size, addr_offs with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is top. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is bot. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Lifted ps, ao -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -240,11 +331,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_ao in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer is %a (in bytes). It is offset by %a (in bytes) due to pointer arithmetic. Memory out-of-bounds access must occur" ID.pretty casted_ps ID.pretty casted_ao | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of pointer (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_ps ID.pretty casted_ao end end @@ -275,6 +366,7 @@ struct | AddrOf lval -> check_lval_for_oob_access ctx ~is_implicitly_derefed lval and check_binop_exp ctx binop e1 e2 t = + check_unknown_addr_deref ctx e1; let binopexp = BinOp (binop, e1, e2, t) in let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in @@ -303,16 +395,16 @@ struct in begin match ptr_size, offset_size_with_addr_size with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is top. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Top -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is top. Memory out-of-bounds access might occur" d_exp binopexp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is bottom. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Bot -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is bottom. Memory out-of-bounds access might occur" d_exp binopexp | `Lifted ps, `Lifted o -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -320,11 +412,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_o in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer in expression %a is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" d_exp binopexp ID.pretty casted_ps ID.pretty casted_o | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare pointer size (%a) with offset (%a). Memory out-of-bounds access may occur" ID.pretty casted_ps ID.pretty casted_o end end @@ -333,23 +425,24 @@ struct | _ -> () (* For memset() and memcpy() *) - let check_count ctx fun_name dest n = + let check_count ctx fun_name ptr n = let (behavior:MessageCategory.behavior) = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in - let dest_size = get_size_of_ptr_target ctx dest in + let ptr_size = get_size_of_ptr_target ctx ptr in let eval_n = ctx.ask (Queries.EvalInt n) in - let addr_offs = get_addr_offs ctx dest in - match dest_size, eval_n with + let addr_offs = get_addr_offs ctx ptr in + match ptr_size, eval_n with | `Top, _ -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp dest fun_name + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Top -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is unknown. Memory out-of-bounds access might occur" fun_name | `Bot, _ -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp dest fun_name + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Bot -> + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is bottom" fun_name | `Lifted ds, `Lifted en -> let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in @@ -358,11 +451,11 @@ struct let dest_size_lt_count = ID.lt casted_ds (ID.add casted_en casted_ao) in begin match ID.to_bool dest_size_lt_count with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of %a in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" d_exp ptr fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of dest (%a) with address offset (%a) count (%a) in function %s. Memory out-of-bounds access may occur" ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en fun_name end @@ -396,7 +489,9 @@ struct (* Check calls to memset and memcpy for out-of-bounds-accesses *) match desc.special arglist with | Memset { dest; ch; count; } -> check_count ctx f.vname dest count; - | Memcpy { dest; src; n = count; } -> check_count ctx f.vname dest count; + | Memcpy { dest; src; n = count; } -> + (check_count ctx f.vname src count; + check_count ctx f.vname dest count;) | _ -> ctx.local let enter ctx (lval: lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = @@ -412,4 +507,4 @@ struct end let _ = - MCP.register_analysis (module Spec : MCPSpec) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 02231336c0..ef63ab3e91 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module AllocaVars = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All alloca() Variables" end) module HeapVars = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) @@ -14,7 +15,7 @@ module ThreadIdToJoinedThreadsMap = MapDomain.MapBot(ThreadIdDomain.ThreadLifted module Spec : Analyses.MCPSpec = struct - include Analyses.DefaultSpec + include Analyses.IdentitySpec let name () = "useAfterFree" @@ -23,18 +24,11 @@ struct module G = ThreadIdToJoinedThreadsMap module V = VarinfoV - (** TODO: Try out later in benchmarks to see how we perform with and without context-sensititivty *) let context _ _ = () (* HELPER FUNCTIONS *) - let set_global_svcomp_var is_double_free = - if is_double_free then - AnalysisState.svcomp_may_invalid_free := true - else - AnalysisState.svcomp_may_invalid_deref := true - let get_current_threadid ctx = ctx.ask Queries.CurrentThreadId @@ -70,23 +64,23 @@ struct | `Lifted current -> let possibly_started = G.exists (possibly_started current) freeing_threads in if possibly_started then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "There's a thread that's been started in parallel with the memory-freeing threads for heap variable %a. %s might occur" CilType.Varinfo.pretty heap_var bug_name end else begin let current_is_unique = ThreadId.Thread.is_unique current in let any_equal_current threads = G.exists (equal_current current) threads in if not current_is_unique && any_equal_current freeing_threads then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Current thread is not unique and a %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var end else if HeapVars.mem heap_var (snd ctx.local) then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "%s might occur in current unique thread %a for heap variable %a" bug_name ThreadIdDomain.FlagConfiguredTID.pretty current CilType.Varinfo.pretty heap_var end end | `Top -> - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "CurrentThreadId is top. %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var | `Bot -> M.warn ~category:MessageCategory.Analyzer "CurrentThreadId is bottom" @@ -115,8 +109,10 @@ struct begin match ctx.ask (Queries.MayPointTo lval_to_query) with | ad when not (Queries.AD.is_top ad) -> let warn_for_heap_var v = - if HeapVars.mem v (snd state) then + if HeapVars.mem v (snd state) then begin + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior undefined_behavior) ~tags:[CWE cwe_number] "lval (%s) in \"%s\" points to a maybe freed memory region" v.vname transfer_fn_name + end in let pointed_to_heap_vars = Queries.AD.fold (fun addr vars -> @@ -179,9 +175,6 @@ struct warn_exp_might_contain_freed "branch" ctx exp; ctx.local - let body ctx (f:fundec) : D.t = - ctx.local - let return ctx (exp:exp option) (f:fundec) : D.t = Option.iter (fun x -> warn_exp_might_contain_freed "return" ctx x) exp; ctx.local @@ -189,17 +182,10 @@ struct let enter ctx (lval:lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = let caller_state = ctx.local in List.iter (fun arg -> warn_exp_might_contain_freed "enter" ctx arg) args; - if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then - [caller_state, caller_state] - else ( - let reachable_from_args = List.fold_left (fun ad arg -> Queries.AD.join ad (ctx.ask (ReachableFrom arg))) (Queries.AD.empty ()) args in - if Queries.AD.is_top reachable_from_args || D.is_top caller_state then - [caller_state, caller_state] - else - let reachable_vars = Queries.AD.to_var_may reachable_from_args in - let callee_state = (AllocaVars.empty (), HeapVars.filter (fun var -> List.mem var reachable_vars) (snd caller_state)) in (* TODO: use AD.mem directly *) - [caller_state, callee_state] - ) + (* TODO: The 2nd component of the callee state needs to contain only the heap vars from the caller state which are reachable from: *) + (* * Global program variables *) + (* * The callee arguments *) + [caller_state, (AllocaVars.empty (), snd caller_state)] let combine_env ctx (lval:lval option) fexp (f:fundec) (args:exp list) fc (callee_local:D.t) (f_ask:Queries.ask) : D.t = let (caller_stack_state, caller_heap_state) = ctx.local in @@ -251,9 +237,6 @@ struct end | _ -> state - let threadenter ctx lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = ctx.local - let startstate v = D.bot () let exitstate v = D.top () diff --git a/src/autoTune.ml b/src/autoTune.ml index e72764ceb6..9e89a18045 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -210,6 +210,38 @@ let activateLongjmpAnalysesWhenRequired () = enableAnalyses longjmpAnalyses; ) +let focusOnMemSafetySpecification () = + match Svcomp.Specification.of_option () with + | ValidFree -> (* Enable the useAfterFree analysis *) + let uafAna = ["useAfterFree"] in + print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; + enableAnalyses uafAna + | ValidDeref -> (* Enable the memOutOfBounds analysis *) + let memOobAna = ["memOutOfBounds"] in + print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; + print_endline @@ "Specification: ValidDeref -> enabling memOutOfBounds analysis \"" ^ (String.concat ", " memOobAna) ^ "\""; + enableAnalyses memOobAna + | ValidMemtrack + | ValidMemcleanup -> (* Enable the memLeak analysis *) + let memLeakAna = ["memLeak"] in + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); + print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; + enableAnalyses memLeakAna + | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) + (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); + let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in + enableAnalyses memSafetyAnas) + | _ -> () + let focusOnSpecification () = match Svcomp.Specification.of_option () with | UnreachCall s -> () @@ -220,13 +252,7 @@ let focusOnSpecification () = | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true - | ValidFree -> (* Enable the useAfterFree analysis *) - let uafAna = ["useAfterFree"] in - print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; - enableAnalyses uafAna - (* TODO: Finish these two below later *) - | ValidDeref - | ValidMemtrack -> () + | _ -> () (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound diff --git a/src/cdomains/arrayDomain.ml b/src/cdomains/arrayDomain.ml index c099a94f96..2f91e47663 100644 --- a/src/cdomains/arrayDomain.ml +++ b/src/cdomains/arrayDomain.ml @@ -787,14 +787,19 @@ let array_oob_check ( type a ) (module Idx: IntDomain.Z with type t = a) (x, l) | Some true, Some true -> (* Certainly in bounds on both sides.*) () | Some true, Some false -> (* The following matching differentiates the must and may cases*) + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "Must access array past end" | Some true, None -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "May access array past end" | Some false, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "Must access array before start" | None, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "May access array before start" | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.unknown "May access array out of bounds" else () diff --git a/src/common/framework/analysisState.ml b/src/common/framework/analysisState.ml index 19377520cd..fd76e1bb67 100644 --- a/src/common/framework/analysisState.ml +++ b/src/common/framework/analysisState.ml @@ -15,9 +15,12 @@ let svcomp_may_invalid_free = ref false (** Whether an invalid pointer dereference happened *) let svcomp_may_invalid_deref = ref false -(** Whether an invalid memtrack happened *) +(** Whether a memory leak occurred and there's no reference to the leaked memory *) let svcomp_may_invalid_memtrack = ref false +(** Whether a memory leak occurred *) +let svcomp_may_invalid_memcleanup = ref false + (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 52d5f52f25..2075cda890 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -40,7 +40,8 @@ let is_first_field x = match x.fcomp.cfields with let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); - Cil.gnu89inline := get_bool "cil.gnu89inline" + Cil.gnu89inline := get_bool "cil.gnu89inline"; + Cabs2cil.addNestedScopeAttr := get_bool "cil.addNestedScopeAttr" let init () = initCIL (); diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 3dd43530bd..e8510e86f3 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -288,6 +288,12 @@ "type": "boolean", "description": "Indicates whether gnu89 semantic should be used for inline functions.", "default": false + }, + "addNestedScopeAttr": { + "title": "cil.addNestedScopeAttr", + "type": "boolean", + "description": "Indicates whether variables that CIL pulls out of their scope should be marked.", + "default": false } }, "additionalProperties": false diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index dadeb2cda1..a71a0c9684 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -23,6 +23,7 @@ module CfgTools = CfgTools module Analyses = Analyses module Constraints = Constraints module AnalysisState = AnalysisState +module AnalysisStateUtil = AnalysisStateUtil module ControlSpecC = ControlSpecC (** Master control program (MCP) is the analysis specification for the dynamic product of activated analyses. *) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index e80ae12661..d187fc70f0 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -135,6 +135,7 @@ let check_arguments () = if get_bool "allfuns" && not (get_bool "exp.earlyglobs") then (set_bool "exp.earlyglobs" true; warn "allfuns enables exp.earlyglobs.\n"); if not @@ List.mem "escape" @@ get_string_list "ana.activated" then warn "Without thread escape analysis, every local variable whose address is taken is considered escaped, i.e., global!"; if List.mem "malloc_null" @@ get_string_list "ana.activated" && not @@ get_bool "sem.malloc.fail" then (set_bool "sem.malloc.fail" true; warn "The malloc_null analysis enables sem.malloc.fail."); + if List.mem "memOutOfBounds" @@ get_string_list "ana.activated" && not @@ get_bool "cil.addNestedScopeAttr" then (set_bool "cil.addNestedScopeAttr" true; warn "The memOutOfBounds analysis enables cil.addNestedScopeAttr."); if get_bool "ana.base.context.int" && not (get_bool "ana.base.context.non-ptr") then (set_bool "ana.base.context.int" false; warn "ana.base.context.int implicitly disabled by ana.base.context.non-ptr"); (* order matters: non-ptr=false, int=true -> int=false cascades to interval=false with warning *) if get_bool "ana.base.context.interval" && not (get_bool "ana.base.context.int") then (set_bool "ana.base.context.interval" false; warn "ana.base.context.interval implicitly disabled by ana.base.context.int"); @@ -190,6 +191,8 @@ let handle_options () = check_arguments (); AfterConfig.run (); Sys.set_signal (GobSys.signal_of_string (get_string "dbg.solver-signal")) Signal_ignore; (* Ignore solver-signal before solving (e.g. MyCFG), otherwise exceptions self-signal the default, which crashes instead of printing backtrace. *) + if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then + AutoTune.focusOnMemSafetySpecification (); Cilfacade.init_options (); handle_flags () diff --git a/src/util/analysisStateUtil.ml b/src/util/analysisStateUtil.ml new file mode 100644 index 0000000000..a34be33f18 --- /dev/null +++ b/src/util/analysisStateUtil.ml @@ -0,0 +1,13 @@ +type mem_safety_violation = + | InvalidFree + | InvalidDeref + | InvalidMemTrack + | InvalidMemcleanup + +let set_mem_safety_flag violation_type = + if !AnalysisState.postsolving then + match violation_type with + | InvalidFree -> AnalysisState.svcomp_may_invalid_free := true + | InvalidDeref -> AnalysisState.svcomp_may_invalid_deref := true + | InvalidMemTrack -> AnalysisState.svcomp_may_invalid_memtrack := true + | InvalidMemcleanup -> AnalysisState.svcomp_may_invalid_memcleanup := true \ No newline at end of file diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 6c050aa5b1..2e29993e91 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -56,6 +56,8 @@ struct | ValidFree -> "valid-free" | ValidDeref -> "valid-deref" | ValidMemtrack -> "valid-memtrack" + | MemorySafety -> "memory-safety" (* TODO: Currently here only to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 39a42cebae..de2d7c5283 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -10,10 +10,13 @@ type t = | ValidFree | ValidDeref | ValidMemtrack + | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) + | ValidMemcleanup let of_string s = let s = String.strip s in - let regexp = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in @@ -30,14 +33,19 @@ let of_string s = UnreachCall f else failwith "Svcomp.Specification.of_string: unknown global not expression" - else if Str.string_match regexp s 0 then + else if Str.string_match regexp_multiple s 0 then + let global1 = Str.matched_group 1 s in + let global2 = Str.matched_group 2 s in + let global3 = Str.matched_group 3 s in + let mem_safety_props = ["valid-free"; "valid-deref"; "valid-memtrack";] in + if (global1 <> global2 && global1 <> global3 && global2 <> global3) && List.for_all (fun x -> List.mem x mem_safety_props) [global1; global2; global3] then + MemorySafety + else + failwith "Svcomp.Specification.of_string: unknown global expression" + else if Str.string_match regexp_single s 0 then let global = Str.matched_group 1 s in - if global = "valid-free" then - ValidFree - else if global = "valid-deref" then - ValidDeref - else if global = "valid-memtrack" then - ValidMemtrack + if global = "valid-memcleanup" then + ValidMemcleanup else failwith "Svcomp.Specification.of_string: unknown global expression" else @@ -69,5 +77,7 @@ let to_string spec = | ValidDeref -> "valid-deref", false | ValidMemtrack -> "valid-memtrack", false | Termination -> "no-termination", true + | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup", false in print_output spec_str is_neg diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 2031f266f4..08a796c307 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -535,14 +535,17 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidFree -> + | ValidFree + | ValidDeref + | ValidMemtrack + | MemorySafety -> let module TrivialArg = struct include Arg let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_free then + if not !AnalysisState.svcomp_may_invalid_free && not !AnalysisState.svcomp_may_invalid_deref && not !AnalysisState.svcomp_may_invalid_memtrack then ( let module TaskResult = struct module Arg = Arg @@ -553,37 +556,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) - | ValidDeref -> - let module TrivialArg = - struct - include Arg - let next _ = [] - end - in - if not !AnalysisState.svcomp_may_invalid_deref then - let module TaskResult = - struct - module Arg = Arg - let result = Result.True - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg @@ -595,14 +568,14 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidMemtrack -> + | ValidMemcleanup -> let module TrivialArg = struct include Arg let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_memtrack then + if not !AnalysisState.svcomp_may_invalid_memcleanup then ( let module TaskResult = struct module Arg = Arg @@ -613,7 +586,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg diff --git a/tests/regression/77-mem-oob/01-oob-heap-simple.c b/tests/regression/74-invalid_deref/01-oob-heap-simple.c similarity index 100% rename from tests/regression/77-mem-oob/01-oob-heap-simple.c rename to tests/regression/74-invalid_deref/01-oob-heap-simple.c diff --git a/tests/regression/74-use_after_free/02-conditional-uaf.c b/tests/regression/74-invalid_deref/02-conditional-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/02-conditional-uaf.c rename to tests/regression/74-invalid_deref/02-conditional-uaf.c diff --git a/tests/regression/74-use_after_free/03-nested-ptr-uaf.c b/tests/regression/74-invalid_deref/03-nested-ptr-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/03-nested-ptr-uaf.c rename to tests/regression/74-invalid_deref/03-nested-ptr-uaf.c diff --git a/tests/regression/74-use_after_free/04-function-call-uaf.c b/tests/regression/74-invalid_deref/04-function-call-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/04-function-call-uaf.c rename to tests/regression/74-invalid_deref/04-function-call-uaf.c diff --git a/tests/regression/77-mem-oob/05-oob-implicit-deref.c b/tests/regression/74-invalid_deref/05-oob-implicit-deref.c similarity index 100% rename from tests/regression/77-mem-oob/05-oob-implicit-deref.c rename to tests/regression/74-invalid_deref/05-oob-implicit-deref.c diff --git a/tests/regression/77-mem-oob/06-memset-oob.c b/tests/regression/74-invalid_deref/06-memset-oob.c similarity index 100% rename from tests/regression/77-mem-oob/06-memset-oob.c rename to tests/regression/74-invalid_deref/06-memset-oob.c diff --git a/tests/regression/77-mem-oob/07-memcpy-oob.c b/tests/regression/74-invalid_deref/07-memcpy-oob.c similarity index 94% rename from tests/regression/77-mem-oob/07-memcpy-oob.c rename to tests/regression/74-invalid_deref/07-memcpy-oob.c index 012f92996e..5605404a87 100644 --- a/tests/regression/77-mem-oob/07-memcpy-oob.c +++ b/tests/regression/74-invalid_deref/07-memcpy-oob.c @@ -31,13 +31,13 @@ int main(int argc, char const *argv[]) { memcpy(a, b, 40); //WARN memcpy(a, b, sizeof(a)); //WARN - memcpy(b, a, 60); //NOWARN + memcpy(b, a, 60); //WARN b += 1; memcpy(b, a, 60); //WARN s *s_ptr = malloc(sizeof(s)); - memcpy(s_ptr, a, sizeof(s)); //NOWARN + memcpy(s_ptr, a, sizeof(s)); //WARN memcpy(s_ptr->a, 0, sizeof(s)); //WARN memcpy(s_ptr->b, 0, sizeof(s)); //WARN diff --git a/tests/regression/77-mem-oob/08-memset-memcpy-array.c b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c similarity index 96% rename from tests/regression/77-mem-oob/08-memset-memcpy-array.c rename to tests/regression/74-invalid_deref/08-memset-memcpy-array.c index f231ba2dc4..210a61d459 100644 --- a/tests/regression/77-mem-oob/08-memset-memcpy-array.c +++ b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c @@ -6,13 +6,14 @@ int main(int argc, char const *argv[]) { int arr[42]; // Size should be 168 bytes (with 4 byte ints) int *b = arr; - + int random; + memset(b, 0, 168); //NOWARN memset(b, 0, sizeof(arr)); //NOWARN memset(b, 0, 169); //WARN memset(b, 0, sizeof(arr) + 1); //WARN - + int *c = malloc(sizeof(arr)); // Size should be 168 bytes (with 4 byte ints) memcpy(b, c, 168); //NOWARN memcpy(b, c, sizeof(arr)); //NOWARN @@ -26,7 +27,7 @@ int main(int argc, char const *argv[]) { memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN } else if (*(argv + 5)) { - int random = rand(); + random = rand(); b = &random; memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN diff --git a/tests/regression/74-use_after_free/09-juliet-uaf.c b/tests/regression/74-invalid_deref/09-juliet-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/09-juliet-uaf.c rename to tests/regression/74-invalid_deref/09-juliet-uaf.c diff --git a/tests/regression/74-invalid_deref/10-oob-two-loops.c b/tests/regression/74-invalid_deref/10-oob-two-loops.c new file mode 100644 index 0000000000..303aac242e --- /dev/null +++ b/tests/regression/74-invalid_deref/10-oob-two-loops.c @@ -0,0 +1,22 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +#include + +int main() { + int *p = malloc(1048 * sizeof(int)); + + for (int i = 0; i < 1048; ++i) { + p[i] = rand(); //NOWARN + } + + int *q = p; + + while (*q >= 0 && q < p + 1048 * sizeof(int)) { //WARN + if (rand()) { + q++; + } else { + (*q)--; //WARN + } + } + free(p); + return 0; +} diff --git a/tests/regression/74-invalid_deref/11-address-offset-oob.c b/tests/regression/74-invalid_deref/11-address-offset-oob.c new file mode 100644 index 0000000000..ba01a12873 --- /dev/null +++ b/tests/regression/74-invalid_deref/11-address-offset-oob.c @@ -0,0 +1,16 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +int main() { + int *p = malloc(2 * sizeof(int)); + int *q = p; + int x; + + if (x) { + q++; + q++; + q++; + x = *q; //WARN + } + + x = *q; //WARN + return 0; +} diff --git a/tests/regression/74-invalid_deref/12-memcpy-oob-src.c b/tests/regression/74-invalid_deref/12-memcpy-oob-src.c new file mode 100644 index 0000000000..0f3a609fbe --- /dev/null +++ b/tests/regression/74-invalid_deref/12-memcpy-oob-src.c @@ -0,0 +1,43 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info +// TODO: The "--disable warn.info" part is a temporary fix and needs to be removed once the MacOS CI job is fixed +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d:5; + unsigned char e; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(5); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + // It's an OOB error, because sizeof(d) == 4 + memcpy(p, &d, 5); //WARN + if (p->a != 1) { + free(p); + } + if (p->b != 2) { + free(p); + } + if (p->c != 3) { + free(p); + } + if (p->d != 4) { + free(p); + } + if (p->e != 5) { + free(p); + } + free(p); +} + diff --git a/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c b/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c new file mode 100644 index 0000000000..552cd1bb0b --- /dev/null +++ b/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c @@ -0,0 +1,33 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d; +} __attribute__((packed)); + +int main(void) +{ + struct A *p; + p = malloc(2); + p->a = 1; + if (p->a != 1) { + free(p); + } + p->b = 2; + if (p->b != 2) { + free(p); + } + p->c = 3; + if (p->c != 3) { + free(p); + } + p->d = 4; //WARN + if (p->d != 4) {//WARN + free(p); + } + free(p); +} + diff --git a/tests/regression/74-use_after_free/14-alloca-uaf.c b/tests/regression/74-invalid_deref/14-alloca-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/14-alloca-uaf.c rename to tests/regression/74-invalid_deref/14-alloca-uaf.c diff --git a/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c b/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c new file mode 100644 index 0000000000..cc9819950f --- /dev/null +++ b/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c @@ -0,0 +1,22 @@ +//PARAM: --set ana.activated[+] useAfterFree +#include + +int *global; + +void other(void) +{ + int *data = global; + free((void *)data); + return; +} + +int main(int argc, char **argv) +{ + int *data = (int *)malloc(400UL); + free((void *)data); + + global = data; + other(); + + return 0; +} \ No newline at end of file diff --git a/tests/regression/74-invalid_deref/16-uaf-packed-struct.c b/tests/regression/74-invalid_deref/16-uaf-packed-struct.c new file mode 100644 index 0000000000..e10aa28486 --- /dev/null +++ b/tests/regression/74-invalid_deref/16-uaf-packed-struct.c @@ -0,0 +1,40 @@ +// PARAM: --set ana.activated[+] useAfterFree +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char pad1[2]; + unsigned int d; + unsigned char e; + unsigned char pad2[3]; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(12); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + memcpy(p, &d, 4); + if (p->a != 1) { + free(p); + } + if (p->b != 2) {//WARN + free(p);//WARN + } + if (p->c != 3) {//WARN + free(p);//WARN + } + if (p->d != 4) { //WARN + free(p);//WARN + } + free(p);//WARN +} + diff --git a/tests/regression/74-invalid_deref/17-scopes-no-static.c b/tests/regression/74-invalid_deref/17-scopes-no-static.c new file mode 100644 index 0000000000..e0c4b47b73 --- /dev/null +++ b/tests/regression/74-invalid_deref/17-scopes-no-static.c @@ -0,0 +1,22 @@ +// PARAM: --set ana.activated[+] memOutOfBounds +// TODO: I haven't checked why, but we need memOutOfBounds for this case +extern int printf ( const char * format, ... ); + +int *foo2(void) +{ + int arr[1024]; + arr[194] = 13; + return arr + 1; +} + +int *foo(void) +{ + int arr[123]; + return foo2(); +} + +int main(void) { + int *a = foo(); + printf("%d\n", *a);//WARN + return 0; +} diff --git a/tests/regression/74-use_after_free/01-simple-uaf.c b/tests/regression/74-invalid_deref/18-simple-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/01-simple-uaf.c rename to tests/regression/74-invalid_deref/18-simple-uaf.c diff --git a/tests/regression/77-mem-oob/02-oob-stack-simple.c b/tests/regression/74-invalid_deref/19-oob-stack-simple.c similarity index 100% rename from tests/regression/77-mem-oob/02-oob-stack-simple.c rename to tests/regression/74-invalid_deref/19-oob-stack-simple.c diff --git a/tests/regression/74-invalid_deref/20-scopes-global-var.c b/tests/regression/74-invalid_deref/20-scopes-global-var.c new file mode 100644 index 0000000000..9491e1c574 --- /dev/null +++ b/tests/regression/74-invalid_deref/20-scopes-global-var.c @@ -0,0 +1,29 @@ +int array[10]; + +// function returns array of numbers +int* getNumbers(void) { + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2(void) { + int* numbers = getNumbers(); + // numbers2 is local + int numbers2[10]; + + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + + return numbers2; +} + +int main(void) { + int *numbers = getNumbers2(); + numbers[0] = 100;//WARN + + return 0; +} diff --git a/tests/regression/77-mem-oob/03-oob-loop.c b/tests/regression/74-invalid_deref/21-oob-loop.c similarity index 100% rename from tests/regression/77-mem-oob/03-oob-loop.c rename to tests/regression/74-invalid_deref/21-oob-loop.c diff --git a/tests/regression/74-invalid_deref/22-scopes-static.c b/tests/regression/74-invalid_deref/22-scopes-static.c new file mode 100644 index 0000000000..c13b665c84 --- /dev/null +++ b/tests/regression/74-invalid_deref/22-scopes-static.c @@ -0,0 +1,52 @@ +extern int printf (const char* format, ...); + +// function returns array of numbers +int* getNumbers() { + + static int array[10]; + + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2() { + int* numbers = getNumbers(); + static int numbers2[10]; + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + return numbers2; +} + +int* getNumbers3() { + int* numbers = getNumbers2(); + int numbers3[10]; + for (int i = 0; i < 10; ++i) { + numbers3[i] = numbers[i];//NOWARN + } + + return numbers3; +} + +int* getNumbers4() { + int* numbers = getNumbers3(); + static int numbers4[10]; + for (int i = 0; i < 10; ++i) { + numbers4[i] = numbers[i];//WARN + } + return numbers4; +} + +int main (void) { + + int *numbers = getNumbers4(); + + for (int i = 0; i < 10; i++ ) { + printf( "%d\n", *(numbers + i));//NOWARN + } + + return 0; +} diff --git a/tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c b/tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c similarity index 100% rename from tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c rename to tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c diff --git a/tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c b/tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c similarity index 100% rename from tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c rename to tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c diff --git a/tests/regression/74-use_after_free/06-uaf-struct.c b/tests/regression/74-invalid_deref/25-uaf-struct.c similarity index 100% rename from tests/regression/74-use_after_free/06-uaf-struct.c rename to tests/regression/74-invalid_deref/25-uaf-struct.c diff --git a/tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c b/tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c similarity index 100% rename from tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c rename to tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c diff --git a/tests/regression/74-use_after_free/11-wrapper-funs-uaf.c b/tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/11-wrapper-funs-uaf.c rename to tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c diff --git a/tests/regression/74-use_after_free/12-multi-threaded-uaf.c b/tests/regression/74-invalid_deref/28-multi-threaded-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/12-multi-threaded-uaf.c rename to tests/regression/74-invalid_deref/28-multi-threaded-uaf.c diff --git a/tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c b/tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c similarity index 100% rename from tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c rename to tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c diff --git a/tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c b/tests/regression/75-invalid_free/01-invalid-dealloc-simple.c similarity index 100% rename from tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c rename to tests/regression/75-invalid_free/01-invalid-dealloc-simple.c diff --git a/tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c b/tests/regression/75-invalid_free/02-invalid-dealloc-struct.c similarity index 100% rename from tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c rename to tests/regression/75-invalid_free/02-invalid-dealloc-struct.c diff --git a/tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c b/tests/regression/75-invalid_free/03-invalid-dealloc-array.c similarity index 100% rename from tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c rename to tests/regression/75-invalid_free/03-invalid-dealloc-array.c diff --git a/tests/regression/75-invalid_dealloc/04-invalid-realloc.c b/tests/regression/75-invalid_free/04-invalid-realloc.c similarity index 100% rename from tests/regression/75-invalid_dealloc/04-invalid-realloc.c rename to tests/regression/75-invalid_free/04-invalid-realloc.c diff --git a/tests/regression/75-invalid_dealloc/05-free-at-offset.c b/tests/regression/75-invalid_free/05-free-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/05-free-at-offset.c rename to tests/regression/75-invalid_free/05-free-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/06-realloc-at-offset.c b/tests/regression/75-invalid_free/06-realloc-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/06-realloc-at-offset.c rename to tests/regression/75-invalid_free/06-realloc-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c b/tests/regression/75-invalid_free/07-free-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c rename to tests/regression/75-invalid_free/07-free-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/08-itc-no-double-free.c b/tests/regression/75-invalid_free/08-itc-no-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/08-itc-no-double-free.c rename to tests/regression/75-invalid_free/08-itc-no-double-free.c diff --git a/tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c b/tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c similarity index 100% rename from tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c rename to tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c diff --git a/tests/regression/75-invalid_free/10-invalid-dealloc-union.c b/tests/regression/75-invalid_free/10-invalid-dealloc-union.c new file mode 100644 index 0000000000..be1eaa056d --- /dev/null +++ b/tests/regression/75-invalid_free/10-invalid-dealloc-union.c @@ -0,0 +1,42 @@ +extern void abort(void); +#include + +extern int __VERIFIER_nondet_int(void); + +int main() +{ + union { + void *p0; + + struct { + char c[2]; + int p1; + int p2; + } str; + + } data; + + // alloc 37B on heap + data.p0 = malloc(37U); + + // avoid introducing a memleak + void *ptr = data.p0; + + // this should be fine + if(__VERIFIER_nondet_int()) { + data.str.p2 = 20; + } else { + data.str.p2 = 30; + } + + if(25 > data.str.p2) { + // avoids memleak + data.str.c[1] = sizeof data.str.p1; + } + + // invalid free() + free(data.p0);//WARN + + free(ptr);//NOWARN + return 0; +} diff --git a/tests/regression/74-use_after_free/07-itc-double-free.c b/tests/regression/75-invalid_free/11-itc-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/07-itc-double-free.c rename to tests/regression/75-invalid_free/11-itc-double-free.c diff --git a/tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c b/tests/regression/75-invalid_free/12-realloc-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c rename to tests/regression/75-invalid_free/12-realloc-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/10-juliet-double-free.c b/tests/regression/75-invalid_free/13-juliet-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/10-juliet-double-free.c rename to tests/regression/75-invalid_free/13-juliet-double-free.c diff --git a/tests/sv-comp/valid-memcleanup.prp b/tests/sv-comp/valid-memcleanup.prp new file mode 100644 index 0000000000..778c49e5dc --- /dev/null +++ b/tests/sv-comp/valid-memcleanup.prp @@ -0,0 +1,2 @@ +CHECK( init(main()), LTL(G valid-memcleanup) ) + From 58445527a7e46dfce695a36cd0d97e1e7840b9e3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:37:03 +0200 Subject: [PATCH 412/628] Cleanup termination property --- src/witness/svcompSpec.ml | 46 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index de2d7c5283..ceedfcc8a9 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -18,14 +18,13 @@ let of_string s = let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in + let regexp_finally = Str.regexp "CHECK( init(main()), LTL(F \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in if global_not = "data-race" then NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "no-termination" then - Termination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -48,6 +47,12 @@ let of_string s = ValidMemcleanup else failwith "Svcomp.Specification.of_string: unknown global expression" + else if Str.string_match regexp_finally s 0 then + let finally = Str.matched_group 1 s in + if finally = "end" then + Termination + else + failwith "Svcomp.Specification.of_string: unknown finally expression" else failwith "Svcomp.Specification.of_string: unknown expression" @@ -63,21 +68,30 @@ let of_option () = of_string s let to_string spec = - let print_output spec_str is_neg = + let module Prop = struct + type prop = F | G + let string_of_prop = function + | F -> "F" + | G -> "G" + end + in + let open Prop in + let print_output prop spec_str is_neg = + let prop = string_of_prop prop in if is_neg then - Printf.sprintf "CHECK( init(main()), LTL(G ! %s) )" spec_str + Printf.sprintf "CHECK( init(main()), LTL(%s ! %s) )" prop spec_str else - Printf.sprintf "CHECK( init(main()), LTL(G %s) )" spec_str + Printf.sprintf "CHECK( init(main()), LTL(%s %s) )" prop spec_str in - let spec_str, is_neg = match spec with - | UnreachCall f -> "call(" ^ f ^ "())", true - | NoDataRace -> "data-race", true - | NoOverflow -> "overflow", true - | ValidFree -> "valid-free", false - | ValidDeref -> "valid-deref", false - | ValidMemtrack -> "valid-memtrack", false - | Termination -> "no-termination", true - | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) - | ValidMemcleanup -> "valid-memcleanup", false + let prop, spec_str, is_neg = match spec with + | UnreachCall f -> G, "call(" ^ f ^ "())", true + | NoDataRace -> G, "data-race", true + | NoOverflow -> G, "overflow", true + | ValidFree -> G, "valid-free", false + | ValidDeref -> G, "valid-deref", false + | ValidMemtrack -> G, "valid-memtrack", false + | MemorySafety -> G, "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) + | ValidMemcleanup -> G, "valid-memcleanup", false + | Termination -> F, "termination", false in - print_output spec_str is_neg + print_output prop spec_str is_neg From 7cca2cf595a506e6ab9865633c192d304d8c76f1 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:39:26 +0200 Subject: [PATCH 413/628] LTL for termination is `F end` --- src/witness/svcompSpec.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index ceedfcc8a9..e51e691154 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -92,6 +92,6 @@ let to_string spec = | ValidMemtrack -> G, "valid-memtrack", false | MemorySafety -> G, "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) | ValidMemcleanup -> G, "valid-memcleanup", false - | Termination -> F, "termination", false + | Termination -> F, "end", false in print_output prop spec_str is_neg From a4261deb3f784720d0806cf92c1c9165d2cbe36e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 16 Oct 2023 17:36:23 +0300 Subject: [PATCH 414/628] Add final message for unknown ignored longjmp --- src/framework/constraints.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 21f3958a81..95a13ed516 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1663,7 +1663,8 @@ struct if M.tracing then Messages.tracel "longjmp" "Jumping to %a\n" JmpBufDomain.JmpBufSet.pretty targets; let handle_target target = match target with | JmpBufDomain.BufferEntryOrTop.AllTargets -> - M.warn ~category:Imprecise "Longjmp to potentially invalid target, as contents of buffer %a may be unknown! (imprecision due to heap?)" d_exp env + M.warn ~category:Imprecise "Longjmp to potentially invalid target, as contents of buffer %a may be unknown! (imprecision due to heap?)" d_exp env; + M.msg_final Error ~category:Unsound ~tags:[Category Imprecise; Category Call] "Longjmp to unknown target ignored" | Target (target_node, target_context) -> let target_fundec = Node.find_fundec target_node in if CilType.Fundec.equal target_fundec current_fundec && ControlSpecC.equal target_context (ctx.control_context ()) then ( From 5948ca4212df4c896ee20082a4eb6422c70bd06d Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 16 Oct 2023 17:37:45 +0300 Subject: [PATCH 415/628] Mark longjmp-top reachability test as TODO --- tests/regression/68-longjmp/56-longjmp-top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/68-longjmp/56-longjmp-top.c b/tests/regression/68-longjmp/56-longjmp-top.c index 4d57b42fd3..adb3a47476 100644 --- a/tests/regression/68-longjmp/56-longjmp-top.c +++ b/tests/regression/68-longjmp/56-longjmp-top.c @@ -15,7 +15,7 @@ int main() { longjmp(*buf_ptr, 1); // NO CRASH: problem?! } else { - __goblint_check(1); // reachable + __goblint_check(1); // TODO reachable: https://github.com/goblint/analyzer/pull/1210#discussion_r1350021903 } return 0; } From 32be7d50615878bb400b6d665d5bb589be28b79c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 20 Oct 2023 13:39:23 +0300 Subject: [PATCH 416/628] Improve names of some global constraint variables --- src/analyses/commonPriv.ml | 2 +- src/framework/constraints.ml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/commonPriv.ml b/src/analyses/commonPriv.ml index db75455b40..793978980b 100644 --- a/src/analyses/commonPriv.ml +++ b/src/analyses/commonPriv.ml @@ -84,7 +84,7 @@ struct module V = struct (* TODO: Either3? *) - include Printable.Either (Printable.Either (VMutex) (VMutexInits)) (VGlobal) + include Printable.Either (struct include Printable.Either (VMutex) (VMutexInits) let name () = "mutex" end) (VGlobal) let name () = "MutexGlobals" let mutex x: t = `Left (`Left x) let mutex_inits: t = `Left (`Right ()) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 95a13ed516..812d056de4 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1467,6 +1467,7 @@ struct module V = struct include Printable.Either (S.V) (Printable.Either (Printable.Prod (Node) (C)) (Printable.Prod (CilType.Fundec) (C))) + let name () = "longjmp" let s x = `Left x let longjmpto x = `Right (`Left x) let longjmpret x = `Right (`Right x) From af904ac55762f3b9bb59bce54a13ed8e311894d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:19:25 +0000 Subject: [PATCH 417/628] Bump actions/setup-node from 3 to 4 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/locked.yml | 2 +- .github/workflows/metadata.yml | 2 +- .github/workflows/options.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/locked.yml b/.github/workflows/locked.yml index 007ea34619..65dfbe7bac 100644 --- a/.github/workflows/locked.yml +++ b/.github/workflows/locked.yml @@ -153,7 +153,7 @@ jobs: ocaml-compiler: ${{ matrix.ocaml-compiler }} - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/metadata.yml b/.github/workflows/metadata.yml index 1092606bc6..6c7360f9e3 100644 --- a/.github/workflows/metadata.yml +++ b/.github/workflows/metadata.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/options.yml b/.github/workflows/options.yml index 40652791fa..94c49e4bf6 100644 --- a/.github/workflows/options.yml +++ b/.github/workflows/options.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} From 0cf9bc498741c24abda05007134c067f297a1b72 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 26 Oct 2023 10:28:06 +0300 Subject: [PATCH 418/628] Add smtprc-tid unsound case --- tests/regression/03-practical/32-smtprc-tid.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/regression/03-practical/32-smtprc-tid.c diff --git a/tests/regression/03-practical/32-smtprc-tid.c b/tests/regression/03-practical/32-smtprc-tid.c new file mode 100644 index 0000000000..1d4810ee2e --- /dev/null +++ b/tests/regression/03-practical/32-smtprc-tid.c @@ -0,0 +1,38 @@ +#include +#include + +int threads_total = 4; +pthread_t *tids; + +void *cleaner(void *arg) { + while (1) { + for (int i = 0; i < threads_total; i++) { + if (tids[i]) { // RACE! + if (!pthread_join(tids[i], NULL)) // RACE! + tids[i] = 0; // RACE! + } + } + } + return NULL; +} + +void *thread(int i) { // wrong argument type is important + tids[i] = pthread_self(); // RACE! + return NULL; +} + +int main() { + pthread_t tid; + tids = malloc(threads_total * sizeof(pthread_t)); + + for(int i = 0; i < threads_total; i++) + tids[i] = 0; + + pthread_create(&tid, NULL, cleaner, NULL); + + for(int i = 0; i < threads_total; i++) { + pthread_create(&tid, NULL, thread, (int *)i); // cast is important + } + + return 0; +} From 2a958bd7e1a71c0216a0d49317796a45fd13ddf7 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 20 Sep 2023 17:47:35 +0300 Subject: [PATCH 419/628] Fix smtprc-tid unsoundness --- src/analyses/base.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index caa2a41533..6536a9c496 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -399,6 +399,8 @@ struct Int (if AD.is_bot (AD.meet p1 p2) then ID.of_int ik BI.one else match eq p1 p2 with Some x when x -> ID.of_int ik BI.zero | _ -> bool_top ik) | IndexPI when AD.to_string p2 = ["all_index"] -> addToAddrOp p1 (ID.top_of (Cilfacade.ptrdiff_ikind ())) + | IndexPI | PlusPI -> + addToAddrOp p1 (AD.to_int p2) (* sometimes index is AD for some reason... *) | _ -> VD.top () end (* For other values, we just give up! *) From 6899d444f27c1f434ade07565ab5d23a631ea753 Mon Sep 17 00:00:00 2001 From: Karoliine Holter Date: Fri, 27 Oct 2023 15:10:48 +0300 Subject: [PATCH 420/628] Add --enable ana.sv-comp.functions to 20-race-2_1-container_of.c --- tests/regression/10-synch/20-race-2_1-container_of.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/10-synch/20-race-2_1-container_of.c b/tests/regression/10-synch/20-race-2_1-container_of.c index 6083cf4ca0..940649c43b 100644 --- a/tests/regression/10-synch/20-race-2_1-container_of.c +++ b/tests/regression/10-synch/20-race-2_1-container_of.c @@ -1,4 +1,4 @@ -// PARAM: --set ana.activated[+] thread --set ana.path_sens[+] threadflag +// PARAM: --set ana.activated[+] thread --set ana.path_sens[+] threadflag --enable ana.sv-comp.functions #include #include #include @@ -60,7 +60,7 @@ int my_drv_probe(struct my_data *data) { ldv_assert(data->shared.a==0); // NORACE ldv_assert(data->shared.b==0); // NORACE - int res = __VERIFIER_nondet_int(); + int res = magic(); if(res) goto exit; //register callback From 2c0a08f0e356d7e92fff2db874d081e38831e272 Mon Sep 17 00:00:00 2001 From: Karoliine Holter Date: Sun, 29 Oct 2023 20:14:11 +0200 Subject: [PATCH 421/628] Fix accident in 20 10 test --- tests/regression/10-synch/20-race-2_1-container_of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/10-synch/20-race-2_1-container_of.c b/tests/regression/10-synch/20-race-2_1-container_of.c index 940649c43b..04d5facbb7 100644 --- a/tests/regression/10-synch/20-race-2_1-container_of.c +++ b/tests/regression/10-synch/20-race-2_1-container_of.c @@ -60,7 +60,7 @@ int my_drv_probe(struct my_data *data) { ldv_assert(data->shared.a==0); // NORACE ldv_assert(data->shared.b==0); // NORACE - int res = magic(); + int res = __VERIFIER_nondet_int(); if(res) goto exit; //register callback From 7ad12249c111c7dbdb906be7f57311c49a3a15be Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 16:52:50 +0200 Subject: [PATCH 422/628] Move GraphML witness options into witness.graphml (issue #1217) --- conf/ldv-races.json | 6 +- conf/svcomp-yaml.json | 4 +- conf/svcomp.json | 6 +- conf/svcomp21.json | 4 +- ...vcomp22-intervals-novareq-affeq-apron.json | 6 +- ...comp22-intervals-novareq-affeq-native.json | 6 +- ...omp22-intervals-novareq-octagon-apron.json | 6 +- ...p22-intervals-novareq-polyhedra-apron.json | 6 +- conf/svcomp22.json | 6 +- conf/svcomp23.json | 6 +- src/common/util/options.schema.json | 93 ++++++++++--------- src/framework/control.ml | 2 +- src/witness/myARG.ml | 4 +- src/witness/witness.ml | 14 +-- sv-comp/sv-comp-run-no-overflow.py | 2 +- sv-comp/sv-comp-run.py | 2 +- .../observer/path_nofun_true-unreach-call.c | 2 +- 17 files changed, 101 insertions(+), 74 deletions(-) diff --git a/conf/ldv-races.json b/conf/ldv-races.json index 01c60efc8d..2840bb368c 100644 --- a/conf/ldv-races.json +++ b/conf/ldv-races.json @@ -53,8 +53,10 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } }, "solver": "td3", "sem": { diff --git a/conf/svcomp-yaml.json b/conf/svcomp-yaml.json index e09d1c80d7..10a977ff47 100644 --- a/conf/svcomp-yaml.json +++ b/conf/svcomp-yaml.json @@ -76,7 +76,9 @@ "region-offsets": true }, "witness": { - "enabled": false, + "graphml": { + "enabled": false + }, "yaml": { "enabled": true }, diff --git a/conf/svcomp.json b/conf/svcomp.json index 913d43784b..87fef277c3 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -90,8 +90,10 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } }, "pre": { "enabled": false diff --git a/conf/svcomp21.json b/conf/svcomp21.json index a19bfdb9d0..eda5cdfb88 100644 --- a/conf/svcomp21.json +++ b/conf/svcomp21.json @@ -64,6 +64,8 @@ } }, "witness": { - "id": "enumerate" + "graphml": { + "id": "enumerate" + } } } diff --git a/conf/svcomp22-intervals-novareq-affeq-apron.json b/conf/svcomp22-intervals-novareq-affeq-apron.json index 7f72f5d0d8..1dafe0a76d 100644 --- a/conf/svcomp22-intervals-novareq-affeq-apron.json +++ b/conf/svcomp22-intervals-novareq-affeq-apron.json @@ -68,7 +68,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } \ No newline at end of file diff --git a/conf/svcomp22-intervals-novareq-affeq-native.json b/conf/svcomp22-intervals-novareq-affeq-native.json index 3ae1b19788..47b5cbbd8f 100644 --- a/conf/svcomp22-intervals-novareq-affeq-native.json +++ b/conf/svcomp22-intervals-novareq-affeq-native.json @@ -65,7 +65,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } diff --git a/conf/svcomp22-intervals-novareq-octagon-apron.json b/conf/svcomp22-intervals-novareq-octagon-apron.json index 3bf149800e..c6c7144cf6 100644 --- a/conf/svcomp22-intervals-novareq-octagon-apron.json +++ b/conf/svcomp22-intervals-novareq-octagon-apron.json @@ -68,7 +68,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } diff --git a/conf/svcomp22-intervals-novareq-polyhedra-apron.json b/conf/svcomp22-intervals-novareq-polyhedra-apron.json index e4e513415a..e636b6fcdf 100644 --- a/conf/svcomp22-intervals-novareq-polyhedra-apron.json +++ b/conf/svcomp22-intervals-novareq-polyhedra-apron.json @@ -68,7 +68,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } diff --git a/conf/svcomp22.json b/conf/svcomp22.json index 85ea693375..09113a38c9 100644 --- a/conf/svcomp22.json +++ b/conf/svcomp22.json @@ -67,7 +67,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } diff --git a/conf/svcomp23.json b/conf/svcomp23.json index 56474fbe2b..6f404060ba 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -90,7 +90,9 @@ } }, "witness": { - "id": "enumerate", - "unknown": false + "graphml": { + "id": "enumerate", + "unknown": false + } } } diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 400dde06dc..5f2081e8d6 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2279,24 +2279,56 @@ "title": "witness", "type": "object", "properties": { - "enabled": { - "title": "witness.enabled", - "description": "Output witness", - "type": "boolean", - "default": true - }, - "path": { - "title": "witness.path", - "description": "Witness output path", - "type": "string", - "default": "witness.graphml" - }, - "id": { - "title": "witness.id", - "description": "Which witness node IDs to use? node/enumerate", - "type": "string", - "enum": ["node", "enumerate"], - "default": "node" + "graphml": { + "title": "witness.graphml", + "type": "object", + "properties": { + "enabled": { + "title": "witness.graphml.enabled", + "description": "Output GraphML witness", + "type": "boolean", + "default": true + }, + "path": { + "title": "witness.graphml.path", + "description": "GraphML witness output path", + "type": "string", + "default": "witness.graphml" + }, + "id": { + "title": "witness.graphml.id", + "description": "Which witness node IDs to use? node/enumerate", + "type": "string", + "enum": ["node", "enumerate"], + "default": "node" + }, + "minimize": { + "title": "witness.graphml.minimize", + "description": "Try to minimize the witness", + "type": "boolean", + "default": false + }, + "uncil": { + "title": "witness.graphml.uncil", + "description": + "Try to undo CIL control flow transformations in witness", + "type": "boolean", + "default": false + }, + "stack": { + "title": "witness.graphml.stack", + "description": "Construct stacktrace-based witness nodes", + "type": "boolean", + "default": true + }, + "unknown": { + "title": "witness.graphml.unknown", + "description": "Output witness for unknown result", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false }, "invariant": { "title": "witness.invariant", @@ -2376,31 +2408,6 @@ }, "additionalProperties": false }, - "minimize": { - "title": "witness.minimize", - "description": "Try to minimize the witness", - "type": "boolean", - "default": false - }, - "uncil": { - "title": "witness.uncil", - "description": - "Try to undo CIL control flow transformations in witness", - "type": "boolean", - "default": false - }, - "stack": { - "title": "witness.stack", - "description": "Construct stacktrace-based witness nodes", - "type": "boolean", - "default": true - }, - "unknown": { - "title": "witness.unknown", - "description": "Output witness for unknown result", - "type": "boolean", - "default": true - }, "yaml": { "title": "witness.yaml", "type": "object", diff --git a/src/framework/control.ml b/src/framework/control.ml index 9baa2dd1ca..fe43deb45f 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -14,7 +14,7 @@ module type S2S = functor (X : Spec) -> Spec (* spec is lazy, so HConsed table in Hashcons lifters is preserved between analyses in server mode *) let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; - let arg_enabled = (get_bool "ana.sv-comp.enabled" && get_bool "witness.enabled") || get_bool "exp.arg" in + let arg_enabled = (get_bool "ana.sv-comp.enabled" && get_bool "witness.graphml.enabled") || get_bool "exp.arg" in let open Batteries in (* 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 diff --git a/src/witness/myARG.ml b/src/witness/myARG.ml index 62c705f5b1..068aed7a22 100644 --- a/src/witness/myARG.ml +++ b/src/witness/myARG.ml @@ -320,7 +320,7 @@ struct let rec next_opt' n = match n with - | Statement {sid; skind=If (_, _, _, loc, eloc); _} when GobConfig.get_bool "witness.uncil" -> (* TODO: use elocs instead? *) + | Statement {sid; skind=If (_, _, _, loc, eloc); _} when GobConfig.get_bool "witness.graphml.uncil" -> (* TODO: use elocs instead? *) let (e, if_true_next_n, if_false_next_n) = partition_if_next (Arg.next n) in (* avoid infinite recursion with sid <> sid2 in if_nondet_var *) (* TODO: why physical comparison if_false_next_n != n doesn't work? *) @@ -373,7 +373,7 @@ struct Question(e_cond, e_true, e_false, Cilfacade.typeOf e_false) let next_opt' n = match n with - | Statement {skind=If (_, _, _, loc, eloc); _} when GobConfig.get_bool "witness.uncil" -> (* TODO: use eloc instead? *) + | Statement {skind=If (_, _, _, loc, eloc); _} when GobConfig.get_bool "witness.graphml.uncil" -> (* TODO: use eloc instead? *) let (e_cond, if_true_next_n, if_false_next_n) = partition_if_next (Arg.next n) in if Node.location if_true_next_n = loc && Node.location if_false_next_n = loc then match Arg.next if_true_next_n, Arg.next if_false_next_n with diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 9f5a3c1801..2d94f4a18d 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -13,7 +13,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module Invariant = WitnessUtil.Invariant (Task) in let module TaskResult = - (val if get_bool "witness.stack" then + (val if get_bool "witness.graphml.stack" then (module StackTaskResult (Task.Cfg) (TaskResult) : WitnessTaskResult) else (module TaskResult) @@ -24,7 +24,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) struct (* type node = N.t type edge = TaskResult.Arg.Edge.t *) - let minwitness = get_bool "witness.minimize" + let minwitness = get_bool "witness.graphml.minimize" let is_interesting_real from_node edge to_node = (* TODO: don't duplicate this logic with write_node, write_edge *) (* startlines aren't currently interesting because broken, see below *) @@ -58,12 +58,12 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module N = Arg.Node in let module GML = XmlGraphMlWriter in let module GML = - (val match get_string "witness.id" with + (val match get_string "witness.graphml.id" with | "node" -> (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) | "enumerate" -> (module EnumerateNodeGraphMlWriter (N) (GML)) - | _ -> failwith "witness.id: illegal value" + | _ -> failwith "witness.graphml.id: illegal value" ) in let module GML = DeDupGraphMlWriter (N) (GML) in @@ -305,7 +305,7 @@ struct let determine_result entrystates (module Task:Task): (module WitnessTaskResult) = let module Arg: BiArgInvariant = - (val if GobConfig.get_bool "witness.enabled" then ( + (val if GobConfig.get_bool "witness.graphml.enabled" then ( let module Arg = (val ArgTool.create entrystates) in let module Arg = struct @@ -576,8 +576,8 @@ struct print_task_result (module TaskResult); - if get_bool "witness.enabled" && (TaskResult.result <> Result.Unknown || get_bool "witness.unknown") then ( - let witness_path = get_string "witness.path" in + if get_bool "witness.graphml.enabled" && (TaskResult.result <> Result.Unknown || get_bool "witness.graphml.unknown") then ( + let witness_path = get_string "witness.graphml.path" in Timing.wrap "write" (write_file witness_path (module Task)) (module TaskResult) ) diff --git a/sv-comp/sv-comp-run-no-overflow.py b/sv-comp/sv-comp-run-no-overflow.py index a3461b1a64..88ee2c0e53 100755 --- a/sv-comp/sv-comp-run-no-overflow.py +++ b/sv-comp/sv-comp-run-no-overflow.py @@ -13,7 +13,7 @@ OVERVIEW = False # with True Goblint isn't executed # TODO: don't hard-code specification -GOBLINT_COMMAND = "./goblint --conf conf/svcomp21.json --set ana.specification ./tests/sv-comp/no-overflow.prp --set witness.path {witness_filename} {code_filename} -v" +GOBLINT_COMMAND = "./goblint --conf conf/svcomp21.json --set ana.specification ./tests/sv-comp/no-overflow.prp --set witness.graphml.path {witness_filename} {code_filename} -v" TIMEOUT = 10 # with some int that's Goblint timeout for single execution START = 1 EXIT_ON_ERROR = True diff --git a/sv-comp/sv-comp-run.py b/sv-comp/sv-comp-run.py index af7cada051..977aa69ab6 100755 --- a/sv-comp/sv-comp-run.py +++ b/sv-comp/sv-comp-run.py @@ -13,7 +13,7 @@ OVERVIEW = False # with True Goblint isn't executed # TODO: don't hard-code specification -GOBLINT_COMMAND = "./goblint --conf conf/svcomp21.json --set ana.specification ./tests/sv-comp/unreach-call-__VERIFIER_error.prp --set witness.path {witness_filename} {code_filename}" +GOBLINT_COMMAND = "./goblint --conf conf/svcomp21.json --set ana.specification ./tests/sv-comp/unreach-call-__VERIFIER_error.prp --set witness.graphml.path {witness_filename} {code_filename}" TIMEOUT = 30 # with some int that's Goblint timeout for single execution START = 1 EXIT_ON_ERROR = True diff --git a/tests/sv-comp/observer/path_nofun_true-unreach-call.c b/tests/sv-comp/observer/path_nofun_true-unreach-call.c index 0cb70d23e9..cf1191e9fd 100644 --- a/tests/sv-comp/observer/path_nofun_true-unreach-call.c +++ b/tests/sv-comp/observer/path_nofun_true-unreach-call.c @@ -21,4 +21,4 @@ int main() return 0; } -// ./goblint --enable ana.sv-comp --enable ana.wp --enable witness.uncil --disable ana.int.def_exc --enable ana.int.interval --set ana.activated '["base"]' --html tests/sv-comp/observer/path_nofun_true-unreach-call.c +// ./goblint --enable ana.sv-comp --enable ana.wp --enable witness.graphml.uncil --disable ana.int.def_exc --enable ana.int.interval --set ana.activated '["base"]' --html tests/sv-comp/observer/path_nofun_true-unreach-call.c From 8399258dc31e0f12bbeea04be749f730bac080e0 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 17:01:12 +0200 Subject: [PATCH 423/628] Disable witness.graphml.enabled by default --- conf/ldv-races.json | 1 + conf/svcomp.json | 1 + conf/svcomp21.json | 1 + conf/svcomp22-intervals-novareq-affeq-apron.json | 1 + conf/svcomp22-intervals-novareq-affeq-native.json | 1 + conf/svcomp22-intervals-novareq-octagon-apron.json | 1 + conf/svcomp22-intervals-novareq-polyhedra-apron.json | 1 + conf/svcomp22.json | 1 + conf/svcomp23.json | 1 + src/common/util/options.schema.json | 2 +- 10 files changed, 10 insertions(+), 1 deletion(-) diff --git a/conf/ldv-races.json b/conf/ldv-races.json index 2840bb368c..8db800d74c 100644 --- a/conf/ldv-races.json +++ b/conf/ldv-races.json @@ -54,6 +54,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp.json b/conf/svcomp.json index 87fef277c3..2c310c076d 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -91,6 +91,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp21.json b/conf/svcomp21.json index eda5cdfb88..2e36e61d0c 100644 --- a/conf/svcomp21.json +++ b/conf/svcomp21.json @@ -65,6 +65,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate" } } diff --git a/conf/svcomp22-intervals-novareq-affeq-apron.json b/conf/svcomp22-intervals-novareq-affeq-apron.json index 1dafe0a76d..f7f7662b6a 100644 --- a/conf/svcomp22-intervals-novareq-affeq-apron.json +++ b/conf/svcomp22-intervals-novareq-affeq-apron.json @@ -69,6 +69,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp22-intervals-novareq-affeq-native.json b/conf/svcomp22-intervals-novareq-affeq-native.json index 47b5cbbd8f..00db00f30f 100644 --- a/conf/svcomp22-intervals-novareq-affeq-native.json +++ b/conf/svcomp22-intervals-novareq-affeq-native.json @@ -66,6 +66,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp22-intervals-novareq-octagon-apron.json b/conf/svcomp22-intervals-novareq-octagon-apron.json index c6c7144cf6..a0c09e8937 100644 --- a/conf/svcomp22-intervals-novareq-octagon-apron.json +++ b/conf/svcomp22-intervals-novareq-octagon-apron.json @@ -69,6 +69,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp22-intervals-novareq-polyhedra-apron.json b/conf/svcomp22-intervals-novareq-polyhedra-apron.json index e636b6fcdf..3a478bf687 100644 --- a/conf/svcomp22-intervals-novareq-polyhedra-apron.json +++ b/conf/svcomp22-intervals-novareq-polyhedra-apron.json @@ -69,6 +69,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp22.json b/conf/svcomp22.json index 09113a38c9..316c3c5534 100644 --- a/conf/svcomp22.json +++ b/conf/svcomp22.json @@ -68,6 +68,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/conf/svcomp23.json b/conf/svcomp23.json index 6f404060ba..af584f1593 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -91,6 +91,7 @@ }, "witness": { "graphml": { + "enabled": true, "id": "enumerate", "unknown": false } diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 5f2081e8d6..8255be2b48 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2287,7 +2287,7 @@ "title": "witness.graphml.enabled", "description": "Output GraphML witness", "type": "boolean", - "default": true + "default": false }, "path": { "title": "witness.graphml.path", From a2a4fa2be47c1f2fc2f3eff167c9e57db9e346ee Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 17:11:28 +0200 Subject: [PATCH 424/628] Don't output trivial congruence invariant (closes #1218) --- src/cdomains/intDomain.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 748df62300..3bc84ae676 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -3274,6 +3274,7 @@ struct let invariant_ikind e ik x = match x with + | x when is_top x -> Invariant.top () | Some (c, m) when m =: Ints_t.zero -> if get_bool "witness.invariant.exact" then let c = Ints_t.to_bigint c in From 783442572bdc03837dd1378c71994e4f53bae360 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 17:27:09 +0200 Subject: [PATCH 425/628] Forbid witness.graphml.enabled outside of SV-COMP mode --- src/framework/control.ml | 2 +- src/maingoblint.ml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index fe43deb45f..948dce6075 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -14,7 +14,7 @@ module type S2S = functor (X : Spec) -> Spec (* spec is lazy, so HConsed table in Hashcons lifters is preserved between analyses in server mode *) let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; - let arg_enabled = (get_bool "ana.sv-comp.enabled" && get_bool "witness.graphml.enabled") || get_bool "exp.arg" in + let arg_enabled = get_bool "witness.graphml.enabled" || get_bool "exp.arg" in let open Batteries in (* 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 diff --git a/src/maingoblint.ml b/src/maingoblint.ml index b5998df2d1..6c55f43ba1 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -160,7 +160,8 @@ let check_arguments () = ^ String.concat " and " @@ List.map (fun s -> "'" ^ s ^ "'") imprecise_options) ); if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; - if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'" + if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; + if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" (** Initialize some globals in other modules. *) let handle_flags () = From e01caccff051316ecb3ff26ba176656f06a9fb76 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 17:31:30 +0200 Subject: [PATCH 426/628] Disable witness.invariant.accessed by default Makes access analysis more expensive --- src/common/util/options.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 8255be2b48..188e5a77e8 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2365,7 +2365,7 @@ "title": "witness.invariant.accessed", "description": "Only emit invariants for locally accessed variables", "type": "boolean", - "default": true + "default": false }, "full": { "title": "witness.invariant.full", From 6cd62e5163aaaa5deb6ac046d6ab7995e358d1a1 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 30 Oct 2023 17:39:48 +0200 Subject: [PATCH 427/628] Update witness timings --- src/witness/witness.ml | 7 ++----- src/witness/yamlWitness.ml | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 2d94f4a18d..af2e1c03ec 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -572,13 +572,13 @@ struct let write entrystates = let module Task = (val (BatOption.get !task)) in - let module TaskResult = (val (Timing.wrap "determine" (determine_result entrystates) (module Task))) in + let module TaskResult = (val (Timing.wrap "sv-comp result" (determine_result entrystates) (module Task))) in print_task_result (module TaskResult); if get_bool "witness.graphml.enabled" && (TaskResult.result <> Result.Unknown || get_bool "witness.graphml.unknown") then ( let witness_path = get_string "witness.graphml.path" in - Timing.wrap "write" (write_file witness_path (module Task)) (module TaskResult) + Timing.wrap "graphml witness" (write_file witness_path (module Task)) (module TaskResult) ) let write entrystates = @@ -595,7 +595,4 @@ struct ) else write entrystates - - let write entrystates = - Timing.wrap "witness" write entrystates end diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 72ff21f6bd..9e8ebeff51 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -392,6 +392,9 @@ struct ]; yaml_entries_to_file yaml_entries (Fpath.v (GobConfig.get_string "witness.yaml.path")) + + let write () = + Timing.wrap "yaml witness" write () end From 1cf3942190226126befdac561159c15758153a52 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 16:07:47 +0200 Subject: [PATCH 428/628] Make memsafety autotuner enable ana.arrayoob (PR #1201) https://github.com/goblint/analyzer/pull/1201#issuecomment-1787126733 --- src/autoTune.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index 186d930189..b96848c841 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -218,6 +218,7 @@ let focusOnMemSafetySpecification () = enableAnalyses uafAna | ValidDeref -> (* Enable the memOutOfBounds analysis *) let memOobAna = ["memOutOfBounds"] in + set_bool "ana.arrayoob" true; print_endline "Setting \"cil.addNestedScopeAttr\" to true"; set_bool "cil.addNestedScopeAttr" true; print_endline @@ "Specification: ValidDeref -> enabling memOutOfBounds analysis \"" ^ (String.concat ", " memOobAna) ^ "\""; @@ -232,6 +233,7 @@ let focusOnMemSafetySpecification () = print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) + set_bool "ana.arrayoob" true; (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; set_bool "cil.addNestedScopeAttr" true; if (get_int "ana.malloc.unique_address_count") < 1 then ( From 6131273c1c95bf762749aa7a6a857fec09603def Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 16:10:14 +0200 Subject: [PATCH 429/628] Separate memsafetySpecification autotuner and enable in svcomp conf Normal specification autotuner does other things we didn't want in SV-COMP. --- conf/svcomp.json | 3 ++- src/common/util/options.schema.json | 2 +- src/maingoblint.ml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 913d43784b..342ac6f298 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -70,7 +70,8 @@ "congruence", "octagon", "wideningThresholds", - "loopUnrollHeuristic" + "loopUnrollHeuristic", + "memsafetySpecification" ] } }, diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 400dde06dc..4d1b012701 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -544,7 +544,7 @@ "type": "array", "items": { "type": "string" }, "default": [ - "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds" + "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds", "memsafetySpecification" ] } }, diff --git a/src/maingoblint.ml b/src/maingoblint.ml index b5998df2d1..9e0b41fe3c 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -186,7 +186,7 @@ let handle_options () = check_arguments (); AfterConfig.run (); Sys.set_signal (GobSys.signal_of_string (get_string "dbg.solver-signal")) Signal_ignore; (* Ignore solver-signal before solving (e.g. MyCFG), otherwise exceptions self-signal the default, which crashes instead of printing backtrace. *) - if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then + if AutoTune.isActivated "memsafetySpecification" && get_string "ana.specification" <> "" then AutoTune.focusOnMemSafetySpecification (); Cilfacade.init_options (); handle_flags () From 4d6b570d6d3c20850fcbe0e95f86638e8595c78b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 16:29:10 +0200 Subject: [PATCH 430/628] Add type for SV-COMP multiproperty --- src/autoTune.ml | 21 ++++++++++++++------- src/util/loopUnrolling.ml | 7 ++++--- src/witness/svcomp.ml | 16 +++++++++------- src/witness/svcompSpec.ml | 9 +++++++++ src/witness/witness.ml | 10 +++++++--- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index b96848c841..c00564bce7 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -210,8 +210,8 @@ let activateLongjmpAnalysesWhenRequired () = enableAnalyses longjmpAnalyses; ) -let focusOnMemSafetySpecification () = - match Svcomp.Specification.of_option () with +let focusOnMemSafetySpecification (spec: Svcomp.Specification.t) = + match spec with | ValidFree -> (* Enable the useAfterFree analysis *) let uafAna = ["useAfterFree"] in print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; @@ -244,8 +244,11 @@ let focusOnMemSafetySpecification () = enableAnalyses memSafetyAnas) | _ -> () -let focusOnSpecification () = - match Svcomp.Specification.of_option () with +let focusOnMemSafetySpecification () = + List.iter focusOnMemSafetySpecification (Svcomp.Specification.of_option ()) + +let focusOnSpecification (spec: Svcomp.Specification.t) = + match spec with | UnreachCall s -> () | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; @@ -255,6 +258,9 @@ let focusOnSpecification () = set_bool "ana.int.interval" true | _ -> () +let focusOnSpecification () = + List.iter focusOnSpecification (Svcomp.Specification.of_option ()) + (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound class enumVisitor = object @@ -411,9 +417,10 @@ let congruenceOption factors file = let apronOctagonOption factors file = let locals = if List.mem "specification" (get_string_list "ana.autotune.activated" ) && get_string "ana.specification" <> "" then - match Svcomp.Specification.of_option () with - | NoOverflow -> 12 - | _ -> 8 + if List.mem Svcomp.Specification.NoOverflow (Svcomp.Specification.of_option ()) then + 12 + else + 8 else 8 in let globals = 2 in let selectedLocals = diff --git a/src/util/loopUnrolling.ml b/src/util/loopUnrolling.ml index 62d0f662f3..9a2f6c7b29 100644 --- a/src/util/loopUnrolling.ml +++ b/src/util/loopUnrolling.ml @@ -324,9 +324,10 @@ class loopUnrollingCallVisitor = object raise Found; | _ -> if List.mem "specification" @@ get_string_list "ana.autotune.activated" && get_string "ana.specification" <> "" then ( - match SvcompSpec.of_option () with - | UnreachCall s -> if info.vname = s then raise Found - | _ -> () + List.iter (function + | SvcompSpec.UnreachCall s -> if info.vname = s then raise Found + | _ -> () + ) (SvcompSpec.of_option ()) ); DoChildren ) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 22543d48a9..6d773f666b 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -8,7 +8,7 @@ module Specification = SvcompSpec module type Task = sig val file: Cil.file - val specification: Specification.t + val specification: Specification.multi module Cfg: MyCFG.CfgBidir end @@ -18,9 +18,10 @@ let task: (module Task) option ref = ref None let is_error_function f = let module Task = (val (Option.get !task)) in - match Task.specification with - | UnreachCall f_spec -> f.vname = f_spec - | _ -> false + List.exists (function + | Specification.UnreachCall f_spec -> f.vname = f_spec + | _ -> false + ) Task.specification (* TODO: unused, but should be used? *) let is_special_function f = @@ -30,9 +31,10 @@ let is_special_function f = | fname when String.starts_with fname "__VERIFIER" -> true | fname -> let module Task = (val (Option.get !task)) in - match Task.specification with - | UnreachCall f_spec -> fname = f_spec - | _ -> false + List.exists (function + | Specification.UnreachCall f_spec -> fname = f_spec + | _ -> false + ) Task.specification in is_svcomp && is_verifier diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 4a3da23d9b..185f1fbf67 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -12,6 +12,8 @@ type t = | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) | ValidMemcleanup +type multi = t list + let of_string s = let s = String.strip s in let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in @@ -48,6 +50,8 @@ let of_string s = else failwith "Svcomp.Specification.of_string: unknown expression" +let of_string s: multi = [of_string s] + let of_file path = let s = BatFile.with_file_in path BatIO.read_all in of_string s @@ -77,3 +81,8 @@ let to_string spec = | ValidMemcleanup -> "valid-memcleanup", false in print_output spec_str is_neg + +let to_string spec = + match spec with + | [spec] -> to_string spec + | _ -> assert false (* TODO: aggregate *) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 9f5a3c1801..310717b9c3 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -303,7 +303,7 @@ struct val find_invariant: Node.t -> Invariant.t end - let determine_result entrystates (module Task:Task): (module WitnessTaskResult) = + let determine_result entrystates (module Task:Task) (spec: Svcomp.Specification.t): (module WitnessTaskResult) = let module Arg: BiArgInvariant = (val if GobConfig.get_bool "witness.enabled" then ( let module Arg = (val ArgTool.create entrystates) in @@ -338,7 +338,7 @@ struct ) in - match Task.specification with + match spec with | UnreachCall _ -> (* error function name is globally known through Svcomp.task *) let is_unreach_call = @@ -410,7 +410,7 @@ struct let module TaskResult = struct module Arg = PathArg - let result = Result.False (Some Task.specification) + let result = Result.False (Some spec) let invariant _ = Invariant.none let is_violation = is_violation let is_sink _ = false @@ -569,6 +569,10 @@ struct (module TaskResult:WitnessTaskResult) ) + let determine_result entrystates (module Task:Task): (module WitnessTaskResult) = + match Task.specification with + | [spec] -> determine_result entrystates (module Task) spec + | _ -> assert false (* TODO: aggregate *) let write entrystates = let module Task = (val (BatOption.get !task)) in From 3747556e90acdced4e01fc21e9c83107d10f93fc Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 17:23:40 +0200 Subject: [PATCH 431/628] Remove special MemorySafety SV-COMP property, add full multiproperty handling --- src/autoTune.ml | 10 ---------- src/witness/svcomp.ml | 2 +- src/witness/svcompSpec.ml | 34 +++++++++++++++++----------------- src/witness/witness.ml | 27 ++++++++++++++++++++++----- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index c00564bce7..06347f3190 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -232,16 +232,6 @@ let focusOnMemSafetySpecification (spec: Svcomp.Specification.t) = ); print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna - | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) - set_bool "ana.arrayoob" true; - (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; - set_bool "cil.addNestedScopeAttr" true; - if (get_int "ana.malloc.unique_address_count") < 1 then ( - print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; - set_int "ana.malloc.unique_address_count" 1; - ); - let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in - enableAnalyses memSafetyAnas) | _ -> () let focusOnMemSafetySpecification () = diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 6d773f666b..736de0efae 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -45,6 +45,7 @@ struct | True | False of Specification.t option | Unknown + [@@deriving ord] let to_string = function | True -> "true" @@ -57,7 +58,6 @@ struct | ValidFree -> "valid-free" | ValidDeref -> "valid-deref" | ValidMemtrack -> "valid-memtrack" - | MemorySafety -> "memory-safety" (* TODO: Currently here only to complete the pattern match *) | ValidMemcleanup -> "valid-memcleanup" in "false(" ^ result_spec ^ ")" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 185f1fbf67..9bd5a35e3e 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -9,14 +9,13 @@ type t = | ValidFree | ValidDeref | ValidMemtrack - | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) | ValidMemcleanup +[@@deriving ord] type multi = t list let of_string s = let s = String.strip s in - let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then @@ -32,25 +31,29 @@ let of_string s = UnreachCall f else failwith "Svcomp.Specification.of_string: unknown global not expression" - else if Str.string_match regexp_multiple s 0 then - let global1 = Str.matched_group 1 s in - let global2 = Str.matched_group 2 s in - let global3 = Str.matched_group 3 s in - let mem_safety_props = ["valid-free"; "valid-deref"; "valid-memtrack";] in - if (global1 <> global2 && global1 <> global3 && global2 <> global3) && List.for_all (fun x -> List.mem x mem_safety_props) [global1; global2; global3] then - MemorySafety - else - failwith "Svcomp.Specification.of_string: unknown global expression" else if Str.string_match regexp_single s 0 then let global = Str.matched_group 1 s in - if global = "valid-memcleanup" then + if global = "valid-free" then + ValidFree + else if global = "valid-deref" then + ValidDeref + else if global = "valid-memtrack" then + ValidMemtrack + else if global = "valid-memcleanup" then ValidMemcleanup else failwith "Svcomp.Specification.of_string: unknown global expression" else failwith "Svcomp.Specification.of_string: unknown expression" -let of_string s: multi = [of_string s] +let of_string s: multi = + List.filter_map (fun line -> + let line = String.strip line in + if line = "" then + None + else + Some (of_string line) + ) (String.split_on_char '\n' s) let of_file path = let s = BatFile.with_file_in path BatIO.read_all in @@ -77,12 +80,9 @@ let to_string spec = | ValidFree -> "valid-free", false | ValidDeref -> "valid-deref", false | ValidMemtrack -> "valid-memtrack", false - | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) | ValidMemcleanup -> "valid-memcleanup", false in print_output spec_str is_neg let to_string spec = - match spec with - | [spec] -> to_string spec - | _ -> assert false (* TODO: aggregate *) + String.concat "\n" (List.map to_string spec) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 310717b9c3..419185400c 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -507,8 +507,7 @@ struct ) | ValidFree | ValidDeref - | ValidMemtrack - | MemorySafety -> + | ValidMemtrack -> let module TrivialArg = struct include Arg @@ -570,9 +569,27 @@ struct ) let determine_result entrystates (module Task:Task): (module WitnessTaskResult) = - match Task.specification with - | [spec] -> determine_result entrystates (module Task) spec - | _ -> assert false (* TODO: aggregate *) + Task.specification + |> List.fold_left (fun acc spec -> + let module TaskResult = (val determine_result entrystates (module Task) spec) in + match acc with + | None -> Some (module TaskResult: WitnessTaskResult) + | Some (module Acc: WitnessTaskResult) -> + match Acc.result, TaskResult.result with + (* keep old violation/unknown *) + | False _, True + | False _, Unknown + | Unknown, True -> Some (module Acc: WitnessTaskResult) + (* use new violation/unknown *) + | True, False _ + | Unknown, False _ + | True, Unknown -> Some (module TaskResult: WitnessTaskResult) + (* both same, arbitrarily keep old *) + | True, True -> Some (module Acc: WitnessTaskResult) + | Unknown, Unknown -> Some (module Acc: WitnessTaskResult) + | False _, False _ -> failwith "multiple violations" + ) None + |> Option.get let write entrystates = let module Task = (val (BatOption.get !task)) in From 5093b5dd90a6ec7aca4c541e007c7d4f3025b707 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 17:25:11 +0200 Subject: [PATCH 432/628] Fix witness determine_result for memsafety --- src/witness/witness.ml | 64 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 419185400c..dd829dd9e2 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -505,8 +505,66 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidFree - | ValidDeref + | ValidFree -> + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + if not !AnalysisState.svcomp_may_invalid_free then ( + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) + | ValidDeref -> + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + if not !AnalysisState.svcomp_may_invalid_deref then ( + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) | ValidMemtrack -> let module TrivialArg = struct @@ -514,7 +572,7 @@ struct let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_free && not !AnalysisState.svcomp_may_invalid_deref && not !AnalysisState.svcomp_may_invalid_memtrack then ( + if not !AnalysisState.svcomp_may_invalid_memtrack then ( let module TaskResult = struct module Arg = Arg From bb163a55ba1e06afcd267a02e521a4907f694db2 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 31 Oct 2023 19:13:04 +0200 Subject: [PATCH 433/628] Deduplicate Svcomp.is_error_function --- src/util/loopUnrolling.ml | 6 ++---- src/witness/svcomp.ml | 15 +++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/util/loopUnrolling.ml b/src/util/loopUnrolling.ml index 9a2f6c7b29..4ce8fc06b4 100644 --- a/src/util/loopUnrolling.ml +++ b/src/util/loopUnrolling.ml @@ -324,10 +324,8 @@ class loopUnrollingCallVisitor = object raise Found; | _ -> if List.mem "specification" @@ get_string_list "ana.autotune.activated" && get_string "ana.specification" <> "" then ( - List.iter (function - | SvcompSpec.UnreachCall s -> if info.vname = s then raise Found - | _ -> () - ) (SvcompSpec.of_option ()) + if Svcomp.is_error_function' info (SvcompSpec.of_option ()) then + raise Found ); DoChildren ) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 736de0efae..218f0716ae 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -16,12 +16,16 @@ end let task: (module Task) option ref = ref None -let is_error_function f = +let is_error_function' f spec = let module Task = (val (Option.get !task)) in List.exists (function | Specification.UnreachCall f_spec -> f.vname = f_spec | _ -> false - ) Task.specification + ) spec + +let is_error_function f = + let module Task = (val (Option.get !task)) in + is_error_function' f Task.specification (* TODO: unused, but should be used? *) let is_special_function f = @@ -29,12 +33,7 @@ let is_special_function f = let is_svcomp = String.ends_with loc.file "sv-comp.c" in (* only includes/sv-comp.c functions, not __VERIFIER_assert in benchmark *) let is_verifier = match f.vname with | fname when String.starts_with fname "__VERIFIER" -> true - | fname -> - let module Task = (val (Option.get !task)) in - List.exists (function - | Specification.UnreachCall f_spec -> fname = f_spec - | _ -> false - ) Task.specification + | fname -> is_error_function f in is_svcomp && is_verifier From 35f9323854d7e358a63b374c0bad3ced5cc1d4ed Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 12:10:56 +0200 Subject: [PATCH 434/628] Use threadflag path-sensitivity instead of threadid in svcomp conf This is enough for ldv-races/race-2_1-container_of, etc, but cheaper. --- conf/svcomp.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index df624e4b83..d17e1a5f1e 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -38,7 +38,7 @@ "uninit", "expsplit", "activeSetjmp", - "threadid" + "threadflag" ], "context": { "widen": false From f4b37100d7a9edd544518b434aa39950ef1edb88 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 12:22:46 +0200 Subject: [PATCH 435/628] Copy svcomp conf to svcomp24 --- conf/svcomp24.json | 116 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 conf/svcomp24.json diff --git a/conf/svcomp24.json b/conf/svcomp24.json new file mode 100644 index 0000000000..178035eb8a --- /dev/null +++ b/conf/svcomp24.json @@ -0,0 +1,116 @@ +{ + "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", + "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" + ] + } + }, + "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 + } + }, + "pre": { + "enabled": false + } +} From 529a415a03f50dcd69ca4869b5dddf4194535638 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 12:56:11 +0200 Subject: [PATCH 436/628] Add YAML witness generation to svcomp confs --- conf/svcomp.json | 23 +++++++++++++++++++++++ conf/svcomp24.json | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/conf/svcomp.json b/conf/svcomp.json index 178035eb8a..77f519a568 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -108,6 +108,29 @@ "enabled": true, "id": "enumerate", "unknown": false + }, + "yaml": { + "enabled": true, + "entry-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": { diff --git a/conf/svcomp24.json b/conf/svcomp24.json index 178035eb8a..77f519a568 100644 --- a/conf/svcomp24.json +++ b/conf/svcomp24.json @@ -108,6 +108,29 @@ "enabled": true, "id": "enumerate", "unknown": false + }, + "yaml": { + "enabled": true, + "entry-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": { From ab9eacc13ba44deea33edd146615914cdf2d544e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 12:56:33 +0200 Subject: [PATCH 437/628] Copy svcomp24 conf to svcomp24-validate --- conf/svcomp24-validate.json | 139 ++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 conf/svcomp24-validate.json diff --git a/conf/svcomp24-validate.json b/conf/svcomp24-validate.json new file mode 100644 index 0000000000..77f519a568 --- /dev/null +++ b/conf/svcomp24-validate.json @@ -0,0 +1,139 @@ +{ + "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", + "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" + ] + } + }, + "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, + "entry-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 95ee32e6ea1bcb0a7075e9cea1f439d45f0d4965 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 13:08:21 +0200 Subject: [PATCH 438/628] Add YAML witness validation to svcomp24-validate conf --- conf/svcomp24-validate.json | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/conf/svcomp24-validate.json b/conf/svcomp24-validate.json index 77f519a568..3727c3e9f8 100644 --- a/conf/svcomp24-validate.json +++ b/conf/svcomp24-validate.json @@ -12,6 +12,10 @@ "float": { "interval": true }, + "apron": { + "domain": "polyhedra", + "strengthening": true + }, "activated": [ "base", "threadid", @@ -30,7 +34,9 @@ "symb_locks", "region", "thread", - "threadJoins" + "threadJoins", + "unassume", + "apron" ], "path_sens": [ "mutex", @@ -86,6 +92,9 @@ "loopUnrollHeuristic", "memsafetySpecification" ] + }, + "widen": { + "tokens": true } }, "exp": { @@ -105,32 +114,19 @@ }, "witness": { "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false + "enabled": false }, "yaml": { - "enabled": true, + "enabled": false, "entry-types": [ + "location_invariant", "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]+" - ] + "after-lock": true, + "other": true } }, "pre": { From ce917e639d88c0777cd929de635c030fe060cf2b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 13:13:52 +0200 Subject: [PATCH 439/628] Update sv-comp/archive.sh for 2024 --- sv-comp/archive.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sv-comp/archive.sh b/sv-comp/archive.sh index 9bab49f70d..87dcd75eb9 100755 --- a/sv-comp/archive.sh +++ b/sv-comp/archive.sh @@ -4,7 +4,7 @@ make clean -git tag -m "SV-COMP 2023" svcomp23 +git tag -m "SV-COMP 2024" svcomp24 dune build --profile=release src/goblint.exe rm -f goblint @@ -32,7 +32,8 @@ zip goblint/sv-comp/goblint.zip \ goblint/lib/libboxD.so \ goblint/lib/libpolkaMPQ.so \ goblint/lib/LICENSE.APRON \ - goblint/conf/svcomp23.json \ + goblint/conf/svcomp24.json \ + goblint/conf/svcomp24-validate.json \ goblint/lib/libc/stub/include/assert.h \ goblint/lib/goblint/runtime/include/goblint.h \ goblint/lib/libc/stub/src/stdlib.c \ From 6bad00c305c18578af314b3f1b83ee76aa23f8a6 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 1 Nov 2023 13:22:09 +0200 Subject: [PATCH 440/628] Fix Apron license for unpinned package for SV-COMP --- sv-comp/archive.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sv-comp/archive.sh b/sv-comp/archive.sh index 87dcd75eb9..5d8605dc70 100755 --- a/sv-comp/archive.sh +++ b/sv-comp/archive.sh @@ -18,7 +18,7 @@ cp _opam/share/apron/lib/libapron.so lib/ cp _opam/share/apron/lib/liboctD.so lib/ cp _opam/share/apron/lib/libboxD.so lib/ cp _opam/share/apron/lib/libpolkaMPQ.so lib/ -cp _opam/.opam-switch/sources/apron/COPYING lib/LICENSE.APRON +wget -O lib/LICENSE.APRON https://raw.githubusercontent.com/antoinemine/apron/master/COPYING # done outside to ensure archive contains goblint/ directory cd .. From 031dde1e9538335a0691462a946b571866c1674b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 16:58:38 +0100 Subject: [PATCH 441/628] Add test for joinign thread array --- tests/regression/10-synch/28-join-array.c | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/regression/10-synch/28-join-array.c diff --git a/tests/regression/10-synch/28-join-array.c b/tests/regression/10-synch/28-join-array.c new file mode 100644 index 0000000000..99813b9810 --- /dev/null +++ b/tests/regression/10-synch/28-join-array.c @@ -0,0 +1,25 @@ +// PARAM: --set ana.activated[+] thread +#include + +int data = 0; +pthread_mutex_t data_mutex; + +void *thread(void *arg) { + pthread_mutex_lock(&data_mutex); + data = 3; // RACE! + pthread_mutex_unlock(&data_mutex); + return NULL; +} + +int main() { + pthread_t tids[2]; + + pthread_create(&tids[0], NULL, &thread, NULL); + pthread_create(&tids[1], NULL, &thread, NULL); + + pthread_join(tids[0], NULL); + + data = 1; //RACE! + + return 1; +} From 1d55756147f3dba8cc5f42a996ae3ffaf7c6dbce Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 16:59:08 +0100 Subject: [PATCH 442/628] threadAnalysis: Only add definite tids to set of mustJoined thread --- src/analyses/threadAnalysis.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index 1e679a4707..1f6e9fabb3 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -61,7 +61,8 @@ struct s in match TS.elements (ctx.ask (Queries.EvalThread id)) with - | threads -> List.fold_left join_thread ctx.local threads + | [t] -> join_thread ctx.local t (* single thread *) + | _ -> ctx.local (* if several possible threads are may-joined, none are must-joined *) | exception SetDomain.Unsupported _ -> ctx.local) | _ -> ctx.local From a7d02c42ddcdb21c5042b28d0af7d39a0058a6cf Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:25:55 +0100 Subject: [PATCH 443/628] Simplify warning --- src/analyses/loopTermination.ml | 8 ++------ src/framework/constraints.ml | 14 +++----------- src/framework/control.ml | 7 +------ 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 61034a57c0..077615ad10 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -64,12 +64,8 @@ struct ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Loop analysis)", - Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:NonTerminating "The program might not terminate! (Loop analysis)" + ); () with Not_found -> failwith "Encountered a call to __goblint_bounded with an unknown loop counter variable.") diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 963e6e4996..307f6d0260 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1688,12 +1688,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Longjmp)", - None - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + M.warn ~category:NonTerminating "The program might not terminate! (Longjmp)" ); S.D.bot () | _ -> S.special conv_ctx lv f args @@ -1777,11 +1772,8 @@ struct if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec, Some (M.Location.CilLocation fundec.svar.vdecl)); - ] in - M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) + let loc = M.Location.CilLocation fundec.svar.vdecl in + M.warn ~loc ~category:NonTerminating "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in diff --git a/src/framework/control.ml b/src/framework/control.ml index 65eda50f03..8768fa00c9 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -146,12 +146,7 @@ struct let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Upjumping Goto)", - Some (M.Location.CilLocation l) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + M.warn ~loc:(M.Location.CilLocation l) ~category:NonTerminating "The program might not terminate! (Upjumping Goto)"); ) (!live_lines)) (!Cilfacade.upjumping_gotos); From cf22550ceb4e9e0a70ec193f0d64294b0ce8d340 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:36:03 +0100 Subject: [PATCH 444/628] Delete old termination analysis --- src/analyses/termination.ml | 239 ------------------------------------ 1 file changed, 239 deletions(-) delete mode 100644 src/analyses/termination.ml diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml deleted file mode 100644 index 6da9225d3f..0000000000 --- a/src/analyses/termination.ml +++ /dev/null @@ -1,239 +0,0 @@ -(** Termination analysis of loops using counter variables ([term]). *) - -open Batteries -open GoblintCil -open Analyses - -module M = Messages -let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None - -module TermDomain = struct - include SetDomain.ToppedSet (Basetype.Variables) (struct let topname = "All Variables" end) -end - -(* some kind of location string suitable for variable names? *) -let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column - -class loopCounterVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - (* insert loop counter variable *) - let name = "term"^show_location_id loc in - let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) - let v = Cilfacade.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - (* make an init stmt since the init above is apparently ignored *) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - (* increment it every iteration *) - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end - -let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) -class loopBreaksVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - (match s.skind with - | Loop (b, loc, eloc, Some continue, Some break) -> Hashtbl.add loopBreaks break.sid loc (* TODO: use eloc? *) - | Loop _ -> failwith "Termination.preprocess: every loop should have a break and continue stmt after prepareCFG" - | _ -> ()); - DoChildren -end - -(* if the given block contains a goto while_break.* we have the termination condition for a loop *) -let exits = function - | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid - | _ -> None (* TODO handle return (need to find out what loop we are in) *) - -let lvals_of_expr = - let rec f a = function - | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a - | Lval l | AddrOf l | StartOf l -> l :: a - | SizeOfE e | AlignOfE e | UnOp (_,e,_) | CastE (_,e) | Imag e | Real e -> f a e - | BinOp (_,e1,e2,_) -> f a e1 @ f a e2 - | Question (c,t,e,_) -> f a c @ f a t @ f a e - in f [] - -let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) -class loopVarsVisitor (fd : fundec) = object - inherit nopCilVisitor - method! vstmt s = - let add_exit_cond e loc = - match lvals_of_expr e with - | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval - | _ -> () - in - (match s.skind with - | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) - | _ -> ()); - DoChildren -end - -let stripCastsDeep e = - let v = object - inherit nopCilVisitor - method! vexpr e = ChangeTo (stripCasts e) - end - in visitCilExpr v e - -(* keep the enclosing loop for statements *) -let cur_loop = ref None (* current loop *) -let cur_loop' = ref None (* for nested loops *) -let makeVar fd loc name = - let id = name ^ "__" ^ show_location_id loc in - try List.find (fun v -> v.vname = id) fd.slocals - with Not_found -> - let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) - Cilfacade.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) -let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) -let f_check = Lval (var (emptyFunction "__goblint_check").svar) -class loopInstrVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - (* TODO: use Loop eloc? *) - (match s.skind with - | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; - cur_loop := Some loc - | _ -> ()); - let action s = - (* first, restore old cur_loop *) - (match s.skind with - | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; - | _ -> ()); - let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in - match s.skind with - | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> - (* find loop var for current loop *) - let x = Hashtbl.find loopVars loc in - (* insert loop counter and diff to loop var *) - let t = var @@ makeVar fd loc "t" in - let d1 = var @@ makeVar fd loc "d1" in - let d2 = var @@ makeVar fd loc "d2" in - (* make init stmts *) - let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in - let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in - let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in - (* increment/decrement in every iteration *) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in - let typ = intType in - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in - let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in - let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with - | cont :: cond :: ss -> - (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in - s.skind <- Block nb; - | _ -> ()); - s - | Loop (b, loc, eloc, Some continue, Some break) -> - print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; - s - | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in - let t = var @@ makeVar fd loc "t" in - let e3 = BinOp (Ge, Lval t, zero, intType) in - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in - let nb = mkBlock [mkStmt s.skind; inv3] in - s.skind <- Block nb; - s - | Instr [Set (lval, e, loc, eloc)] when in_loop () -> - (* find loop var for current loop *) - let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in - if x <> lval then - s - else (* we only care about the loop var *) - let d1 = makeVar fd cur_loop "d1" in - let d2 = makeVar fd cur_loop "d2" in - (match stripCastsDeep e with - | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) - (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> - (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in - let te = Cilfacade.typeOf e in - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in - s.skind <- Block nb; - s - ) - | _ -> s - in - ChangeDoChildrenPost (s, action) -end - - -module Spec = -struct - include Analyses.IdentitySpec - - let name () = "term" - module D = TermDomain - module C = TermDomain - - (* queries *) - (*let query ctx (q:Queries.t) : Queries.Result.t =*) - (*match q with*) - (*| Queries.MustTerm loc -> `Bool (D.mem v ctx.local)*) - (*| _ -> Queries.Result.top ()*) - - (* transfer functions *) - - let branch ctx (exp:exp) (tv:bool) : D.t = - ctx.local - (* if the then-block contains a goto while_break.* we have the termination condition for a loop *) - (* match !MyCFG.current_node with *) - (* | Some (MyCFG.Statement({ skind = If (e, tb, fb, loc) })) -> *) - (* let str_exit b = match exits b with Some loc -> string_of_int loc.line | None -> "None" in *) - (* M.debug @@ *) - (* "\nCil-exp: " ^ sprint d_exp e *) - (* (*^ "; Goblint-exp: " ^ sprint d_exp exp*) *) - (* ^ "; Goblint: " ^ sprint Queries.Result.pretty (ctx.ask (Queries.EvalInt exp)) *) - (* ^ "\nCurrent block: " ^ (if tv then "Then" else "Else") *) - (* ^ "\nThen block (exits " ^ str_exit tb ^ "): " ^ sprint d_block tb *) - (* ^ "\nElse block (exits " ^ str_exit fb ^ "): " ^ sprint d_block fb *) - (* ; *) - (* ctx.local *) - (* | _ -> ctx.local *) - - let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] - let exitstate v = D.bot () -end - -class recomputeVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vfunc fd = - computeCFGInfo fd true; - SkipChildren -end - -let _ = - (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); - Hashtbl.clear loopBreaks; (* because the sids are now different *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - MCP.register_analysis (module Spec : MCPSpec) From 67cc037057a69e446bc35e906e256a5c63621138 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:36:59 +0100 Subject: [PATCH 445/628] Rm old Termination also from `goblint_lib.ml` --- src/goblint_lib.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a71a0c9684..e1087f8fc9 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 Uninit = Uninit -module Termination = Termination module Expsplit = Expsplit module StackTrace = StackTrace module Spec = Spec From dff7be0446336b3e9ac8810fce326004f767a293 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:54:43 +0100 Subject: [PATCH 446/628] Make `do_preprocess_cil` more efficient --- src/common/util/cilfacade.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 2075cda890..47cf6d6210 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -93,12 +93,13 @@ let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] let do_preprocess_cil ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors_cil in + let f fd visitor_fun = ignore @@ visitCilFunction (visitor_fun fd) fd in + if active_visitors <> [] then + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) active_visitors | _ -> ()) + else + () (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) From 2d8fe096da4f54d585ce65748a28cf06de18d124 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:59:03 +0100 Subject: [PATCH 447/628] Remove outdated TODO --- src/witness/witness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 08a796c307..1612667a30 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -475,7 +475,7 @@ struct in (module TaskResult:WitnessTaskResult) ) - | Termination -> (* TODO: implement this properly*) + | Termination -> let module TrivialArg = struct include Arg From f147d9bdd67fda7d77907631b643678eebe4284a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 2 Nov 2023 10:05:22 +0200 Subject: [PATCH 448/628] Remove unused [@@deriving ord] on SV-COMP spec --- src/witness/svcomp.ml | 1 - src/witness/svcompSpec.ml | 1 - 2 files changed, 2 deletions(-) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 218f0716ae..eae97b1199 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -44,7 +44,6 @@ struct | True | False of Specification.t option | Unknown - [@@deriving ord] let to_string = function | True -> "true" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 9bd5a35e3e..66b3b83ac8 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -10,7 +10,6 @@ type t = | ValidDeref | ValidMemtrack | ValidMemcleanup -[@@deriving ord] type multi = t list From c42ec6b1e19eca1f1b899387a023d6505e285b7d Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 26 Sep 2023 18:09:51 +0300 Subject: [PATCH 449/628] Refactor Access.may_race with match --- src/domains/access.ml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/domains/access.ml b/src/domains/access.ml index 8907ccbc32..3ba7aaee74 100644 --- a/src/domains/access.ml +++ b/src/domains/access.ml @@ -438,16 +438,13 @@ struct end -(* Check if two accesses may race and if yes with which confidence *) +(** Check if two accesses may race. *) let may_race A.{kind; acc; _} A.{kind=kind2; acc=acc2; _} = - if kind = Read && kind2 = Read then - false (* two read/read accesses do not race *) - else if not (get_bool "ana.race.free") && (kind = Free || kind2 = Free) then - false - else if not (MCPAccess.A.may_race acc acc2) then - false (* analysis-specific information excludes race *) - else - true + match kind, kind2 with + | Read, Read -> false (* two read/read accesses do not race *) + | Free, _ + | _, Free when not (get_bool "ana.race.free") -> false + | _, _ -> MCPAccess.A.may_race acc acc2 (* analysis-specific information excludes race *) (** Access sets for race detection and warnings. *) module WarnAccs = From e690d9ad81291ee34360e72fd2aceb33742c5d2d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 2 Nov 2023 16:11:18 +0100 Subject: [PATCH 450/628] Prioritze termination warnings in `update_suite.rb` --- scripts/update_suite.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 28d6ddb52d..a7d60b5c21 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -160,13 +160,13 @@ def collect_warnings when /invariant confirmed/ then "success" when /invariant unconfirmed/ then "unknown" when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" when /^\[Warning\]/ then "warn" when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) From 04516adf08e43517eb13bcfcf3fb06dda310c164 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 3 Nov 2023 12:58:46 +0100 Subject: [PATCH 451/628] Make memLeak path- & ctx-sensitive --- src/analyses/memLeak.ml | 7 ++++--- src/common/util/options.schema.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index dbaa2d69fc..62b6bbe3a7 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -14,9 +14,10 @@ struct let name () = "memLeak" module D = ToppedVarInfoSet - module C = Lattice.Unit + module C = D + module P = IdentityP (D) - let context _ _ = () + let context _ d = d (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = @@ -95,4 +96,4 @@ struct end let _ = - MCP.register_analysis (module Spec : MCPSpec) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 40669ff729..4e282b19a4 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -352,7 +352,7 @@ "description": "List of path-sensitive analyses", "type": "array", "items": { "type": "string" }, - "default": [ "mutex", "malloc_null", "uninit", "expsplit","activeSetjmp" ] + "default": [ "mutex", "malloc_null", "uninit", "expsplit","activeSetjmp","memLeak" ] }, "ctx_insens": { "title": "ana.ctx_insens", From 27cf7f58c44e50d45bf5e98ef8ad097d0ed126b9 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 3 Nov 2023 14:05:30 +0100 Subject: [PATCH 452/628] Set unique address count to 5 --- src/autoTune.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 06347f3190..7ddc1aee43 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -227,8 +227,8 @@ let focusOnMemSafetySpecification (spec: Svcomp.Specification.t) = | ValidMemcleanup -> (* Enable the memLeak analysis *) let memLeakAna = ["memLeak"] in if (get_int "ana.malloc.unique_address_count") < 1 then ( - print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; - set_int "ana.malloc.unique_address_count" 1; + print_endline "Setting \"ana.malloc.unique_address_count\" to 5"; + set_int "ana.malloc.unique_address_count" 5; ); print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; enableAnalyses memLeakAna From 2174f108cf0c179d027d94684bee149547c3bf77 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:06:35 +0200 Subject: [PATCH 453/628] Make memLeak path- & ctx-sensitive Co-authored-by: Michael Schwarz --- src/analyses/memLeak.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index dbaa2d69fc..9c09c05cf6 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -14,9 +14,10 @@ struct let name () = "memLeak" module D = ToppedVarInfoSet - module C = Lattice.Unit + module C = D + module P = IdentityP (D) - let context _ _ = () + let context _ d = d (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = From 4279417b24a5c2e3c0bb46dd6cb0c2c6c29a0d03 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:07:57 +0200 Subject: [PATCH 454/628] Add test from #1235 --- .../56-witness/52-witness-lifter-ps2.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/regression/56-witness/52-witness-lifter-ps2.c diff --git a/tests/regression/56-witness/52-witness-lifter-ps2.c b/tests/regression/56-witness/52-witness-lifter-ps2.c new file mode 100644 index 0000000000..bcb7c1410c --- /dev/null +++ b/tests/regression/56-witness/52-witness-lifter-ps2.c @@ -0,0 +1,35 @@ +// PARAM: --enable ana.sv-comp.enabled --enable ana.sv-comp.functions --enable witness.graphml.enabled --set ana.specification 'CHECK( init(main()), LTL(G valid-memtrack) )' --set ana.activated[+] memLeak --set ana.path_sens[+] memLeak --set ana.malloc.unique_address_count 1 +struct _twoIntsStruct { + int intOne ; + int intTwo ; +}; + +typedef struct _twoIntsStruct twoIntsStruct; + +void printStructLine(twoIntsStruct const *structTwoIntsStruct) +{ + return; +} + + +int main(int argc, char **argv) +{ + twoIntsStruct *data; + int tmp_1; + + + if (tmp_1 != 0) { + twoIntsStruct *dataBuffer = malloc(800UL); + data = dataBuffer; + } + else { + + twoIntsStruct *dataBuffer_0 = malloc(800UL); + data = dataBuffer_0; + } + + printStructLine((twoIntsStruct const *)data); + free((void *)data); + + return; +} From 5c8a37773067c55709c6f0cc7a3e20da6bdb08c7 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:08:27 +0200 Subject: [PATCH 455/628] Use inline_edge in more witness interfaces --- src/witness/myARG.ml | 2 +- src/witness/svcomp.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/witness/myARG.ml b/src/witness/myARG.ml index 068aed7a22..0dd42bc910 100644 --- a/src/witness/myARG.ml +++ b/src/witness/myARG.ml @@ -141,7 +141,7 @@ struct let equal_node_context _ _ = failwith "StackNode: equal_node_context" end -module Stack (Cfg:CfgForward) (Arg: S): +module Stack (Cfg:CfgForward) (Arg: S with module Edge = InlineEdge): S with module Node = StackNode (Arg.Node) and module Edge = Arg.Edge = struct module Node = StackNode (Arg.Node) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index eae97b1199..9aab121196 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -76,7 +76,7 @@ sig val is_sink: Arg.Node.t -> bool end -module StackTaskResult (Cfg:MyCFG.CfgForward) (TaskResult: TaskResult) = +module StackTaskResult (Cfg:MyCFG.CfgForward) (TaskResult: TaskResult with module Arg.Edge = MyARG.InlineEdge) = struct module Arg = MyARG.Stack (Cfg) (TaskResult.Arg) From 23771e41e1afac7268761b8ceb1de0d033b01370 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:09:36 +0200 Subject: [PATCH 456/628] Remove CFG-based function return node from MyARG.Stack (closes #1235) --- src/witness/myARG.ml | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/witness/myARG.ml b/src/witness/myARG.ml index 0dd42bc910..a11ba44178 100644 --- a/src/witness/myARG.ml +++ b/src/witness/myARG.ml @@ -161,38 +161,30 @@ struct (* | [] -> failwith "StackArg.next: return stack empty" *) | [] -> [] (* main return *) | call_n :: call_stack -> - let call_cfgnode = Arg.Node.cfgnode call_n in let call_next = - Cfg.next call_cfgnode + Arg.next call_n (* filter because infinite loops starting with function call will have another Neg(1) edge from the head *) - |> List.filter (fun (locedges, to_node) -> - List.exists (function - | (_, Proc _) -> true - | (_, _) -> false - ) locedges + |> List.filter (fun (edge, to_n) -> + match edge with + | InlinedEdge _ -> true + | _ -> false ) in begin match call_next with - | [] -> failwith "StackArg.next: call next empty" - | [(_, return_node)] -> - begin match Arg.Node.move_opt call_n return_node with - (* TODO: Is it possible to have a calling node without a returning node? *) - (* | None -> [] *) - | None -> failwith "StackArg.next: no return node" - | Some return_n -> - (* TODO: Instead of next & filter, construct unique return_n directly. Currently edge missing. *) - Arg.next n - |> List.filter (fun (edge, to_n) -> - (* let to_cfgnode = Arg.Node.cfgnode to_n in - MyCFG.Node.equal to_cfgnode return_node *) - Arg.Node.equal_node_context to_n return_n - ) - |> List.map (fun (edge, to_n) -> - let to_n' = to_n :: call_stack in - (edge, to_n') - ) - end + | [] -> failwith "StackArg.next: call next empty" (* TODO: Is it possible to have a calling node without a returning node? *) + | [(_, return_n)] -> + (* TODO: Instead of next & filter, construct unique return_n directly. Currently edge missing. *) + Arg.next n + |> List.filter (fun (edge, to_n) -> + (* let to_cfgnode = Arg.Node.cfgnode to_n in + MyCFG.Node.equal to_cfgnode return_node *) + Arg.Node.equal_node_context to_n return_n + ) + |> List.map (fun (edge, to_n) -> + let to_n' = to_n :: call_stack in + (edge, to_n') + ) | _ :: _ :: _ -> failwith "StackArg.next: call next ambiguous" end end From 3299b75380b60073f075efcc3d46e97513f92ab3 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:15:26 +0200 Subject: [PATCH 457/628] Remove now-unused Cfg argument from stack ARG functor --- src/witness/myARG.ml | 4 ++-- src/witness/svcomp.ml | 4 ++-- src/witness/witness.ml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/witness/myARG.ml b/src/witness/myARG.ml index a11ba44178..ae8b5f6772 100644 --- a/src/witness/myARG.ml +++ b/src/witness/myARG.ml @@ -141,7 +141,7 @@ struct let equal_node_context _ _ = failwith "StackNode: equal_node_context" end -module Stack (Cfg:CfgForward) (Arg: S with module Edge = InlineEdge): +module Stack (Arg: S with module Edge = InlineEdge): S with module Node = StackNode (Arg.Node) and module Edge = Arg.Edge = struct module Node = StackNode (Arg.Node) @@ -156,7 +156,7 @@ struct | n :: stack -> let cfgnode = Arg.Node.cfgnode n in match cfgnode with - | Function _ -> (* TODO: can this be done without Cfg? *) + | Function _ -> (* TODO: can this be done without cfgnode? *) begin match stack with (* | [] -> failwith "StackArg.next: return stack empty" *) | [] -> [] (* main return *) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 9aab121196..89487ea8d4 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -76,9 +76,9 @@ sig val is_sink: Arg.Node.t -> bool end -module StackTaskResult (Cfg:MyCFG.CfgForward) (TaskResult: TaskResult with module Arg.Edge = MyARG.InlineEdge) = +module StackTaskResult (TaskResult: TaskResult with module Arg.Edge = MyARG.InlineEdge) = struct - module Arg = MyARG.Stack (Cfg) (TaskResult.Arg) + module Arg = MyARG.Stack (TaskResult.Arg) let result = TaskResult.result diff --git a/src/witness/witness.ml b/src/witness/witness.ml index d94960d542..235461c348 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -14,7 +14,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module TaskResult = (val if get_bool "witness.graphml.stack" then - (module StackTaskResult (Task.Cfg) (TaskResult) : WitnessTaskResult) + (module StackTaskResult (TaskResult) : WitnessTaskResult) else (module TaskResult) ) From 38e82eb7620200427bbc13040c5758471e862fa3 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:22:08 +0200 Subject: [PATCH 458/628] Add 56-witness/53-witness-lifter-ps2 version with functon introducing path-sensitivity --- .../56-witness/53-witness-lifter-ps3.c | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/regression/56-witness/53-witness-lifter-ps3.c diff --git a/tests/regression/56-witness/53-witness-lifter-ps3.c b/tests/regression/56-witness/53-witness-lifter-ps3.c new file mode 100644 index 0000000000..06b73b3888 --- /dev/null +++ b/tests/regression/56-witness/53-witness-lifter-ps3.c @@ -0,0 +1,39 @@ +// PARAM: --enable ana.sv-comp.enabled --enable ana.sv-comp.functions --enable witness.graphml.enabled --set ana.specification 'CHECK( init(main()), LTL(G valid-memtrack) )' --set ana.activated[+] memLeak --set ana.path_sens[+] memLeak --set ana.malloc.unique_address_count 1 +struct _twoIntsStruct { + int intOne ; + int intTwo ; +}; + +typedef struct _twoIntsStruct twoIntsStruct; + +void printStructLine(twoIntsStruct const *structTwoIntsStruct) +{ + return; +} + +twoIntsStruct *foo() { + twoIntsStruct *data; + int tmp_1; + + if (tmp_1 != 0) { + twoIntsStruct *dataBuffer = malloc(800UL); + data = dataBuffer; + } + else { + + twoIntsStruct *dataBuffer_0 = malloc(800UL); + data = dataBuffer_0; + } + return data; +} + +int main(int argc, char **argv) +{ + twoIntsStruct *data; + data = foo(); + + printStructLine((twoIntsStruct const *)data); + free((void *)data); + + return; +} From cb32b12a377ba255b02735890e4eb50afab16cca Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 6 Nov 2023 14:44:30 +0200 Subject: [PATCH 459/628] Fix 56-witness/53-witness-lifter-ps3 --- src/witness/myARG.ml | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/witness/myARG.ml b/src/witness/myARG.ml index ae8b5f6772..373a66d3d6 100644 --- a/src/witness/myARG.ml +++ b/src/witness/myARG.ml @@ -165,28 +165,21 @@ struct Arg.next call_n (* filter because infinite loops starting with function call will have another Neg(1) edge from the head *) - |> List.filter (fun (edge, to_n) -> + |> List.filter_map (fun (edge, to_n) -> match edge with - | InlinedEdge _ -> true - | _ -> false + | InlinedEdge _ -> Some to_n + | _ -> None ) in - begin match call_next with - | [] -> failwith "StackArg.next: call next empty" (* TODO: Is it possible to have a calling node without a returning node? *) - | [(_, return_n)] -> - (* TODO: Instead of next & filter, construct unique return_n directly. Currently edge missing. *) - Arg.next n - |> List.filter (fun (edge, to_n) -> - (* let to_cfgnode = Arg.Node.cfgnode to_n in - MyCFG.Node.equal to_cfgnode return_node *) - Arg.Node.equal_node_context to_n return_n - ) - |> List.map (fun (edge, to_n) -> - let to_n' = to_n :: call_stack in - (edge, to_n') - ) - | _ :: _ :: _ -> failwith "StackArg.next: call next ambiguous" - end + Arg.next n + |> List.filter_map (fun (edge, to_n) -> + if BatList.mem_cmp Arg.Node.compare to_n call_next then ( + let to_n' = to_n :: call_stack in + Some (edge, to_n') + ) + else + None + ) end | _ -> let+ (edge, to_n) = Arg.next n in From 476795e22774535cfb38820011cd261b1df58218 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 14:07:27 +0200 Subject: [PATCH 460/628] Add YAML invariant_set entry type (issue #1238) --- src/witness/yamlWitnessType.ml | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/witness/yamlWitnessType.ml b/src/witness/yamlWitnessType.ml index 3390c1e3ab..c68b1a45c9 100644 --- a/src/witness/yamlWitnessType.ml +++ b/src/witness/yamlWitnessType.ml @@ -242,6 +242,100 @@ struct {location; loop_invariant; precondition} end +module InvariantSet = +struct + module LoopInvariant = + struct + type t = { + location: Location.t; + value: string; + format: string; + } + + let invariant_type = "loop_invariant" + + let to_yaml' {location; value; format} = + [ + ("location", Location.to_yaml location); + ("value", `String value); + ("format", `String format); + ] + + let of_yaml y = + let open GobYaml in + let+ location = y |> find "location" >>= Location.of_yaml + and+ value = y |> find "value" >>= to_string + and+ format = y |> find "format" >>= to_string in + {location; value; format} + end + + module LocationInvariant = + struct + include LoopInvariant + + let invariant_type = "location_invariant" + end + + (* TODO: could maybe use GADT, but adds ugly existential layer to entry type pattern matching *) + module InvariantType = + struct + type t = + | LocationInvariant of LocationInvariant.t + | LoopInvariant of LoopInvariant.t + + let invariant_type = function + | LocationInvariant _ -> LocationInvariant.invariant_type + | LoopInvariant _ -> LoopInvariant.invariant_type + + let to_yaml' = function + | LocationInvariant x -> LocationInvariant.to_yaml' x + | LoopInvariant x -> LoopInvariant.to_yaml' x + + let of_yaml y = + let open GobYaml in + let* invariant_type = y |> find "type" >>= to_string in + if invariant_type = LocationInvariant.invariant_type then + let+ x = y |> LocationInvariant.of_yaml in + LocationInvariant x + else if invariant_type = LoopInvariant.invariant_type then + let+ x = y |> LoopInvariant.of_yaml in + LoopInvariant x + else + Error (`Msg "type") + end + + module Invariant = + struct + type t = { + invariant_type: InvariantType.t; + } + + let to_yaml {invariant_type} = + `O ([ + ("type", `String (InvariantType.invariant_type invariant_type)); + ] @ InvariantType.to_yaml' invariant_type) + + let of_yaml y = + let open GobYaml in + let+ invariant_type = y |> InvariantType.of_yaml in + {invariant_type} + end + + type t = { + content: Invariant.t list; + } + + let entry_type = "invariant_set" + + let to_yaml' {content} = + [("content", `A (List.map Invariant.to_yaml content))] + + let of_yaml y = + let open GobYaml in + let+ content = y |> list >>= list_map Invariant.of_yaml in + {content} +end + module Target = struct type t = { @@ -326,6 +420,7 @@ struct | PreconditionLoopInvariant of PreconditionLoopInvariant.t | LoopInvariantCertificate of LoopInvariantCertificate.t | PreconditionLoopInvariantCertificate of PreconditionLoopInvariantCertificate.t + | InvariantSet of InvariantSet.t let entry_type = function | LocationInvariant _ -> LocationInvariant.entry_type @@ -334,6 +429,7 @@ struct | PreconditionLoopInvariant _ -> PreconditionLoopInvariant.entry_type | LoopInvariantCertificate _ -> LoopInvariantCertificate.entry_type | PreconditionLoopInvariantCertificate _ -> PreconditionLoopInvariantCertificate.entry_type + | InvariantSet _ -> InvariantSet.entry_type let to_yaml' = function | LocationInvariant x -> LocationInvariant.to_yaml' x @@ -342,6 +438,7 @@ struct | PreconditionLoopInvariant x -> PreconditionLoopInvariant.to_yaml' x | LoopInvariantCertificate x -> LoopInvariantCertificate.to_yaml' x | PreconditionLoopInvariantCertificate x -> PreconditionLoopInvariantCertificate.to_yaml' x + | InvariantSet x -> InvariantSet.to_yaml' x let of_yaml y = let open GobYaml in @@ -364,6 +461,9 @@ struct else if entry_type = PreconditionLoopInvariantCertificate.entry_type then let+ x = y |> PreconditionLoopInvariantCertificate.of_yaml in PreconditionLoopInvariantCertificate x + else if entry_type = InvariantSet.entry_type then + let+ x = y |> InvariantSet.of_yaml in + InvariantSet x else Error (`Msg "entry_type") end From f25051c5e6b55220e572d9a536f8b2e1ccba450a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 14:31:04 +0200 Subject: [PATCH 461/628] Add options for YAML invariant_set --- src/common/util/options.schema.json | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 40669ff729..a51c5c59cf 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2430,7 +2430,8 @@ "flow_insensitive_invariant", "precondition_loop_invariant", "loop_invariant_certificate", - "precondition_loop_invariant_certificate" + "precondition_loop_invariant_certificate", + "invariant_set" ] }, "default": [ @@ -2438,7 +2439,24 @@ "loop_invariant", "flow_insensitive_invariant", "loop_invariant_certificate", - "precondition_loop_invariant_certificate" + "precondition_loop_invariant_certificate", + "invariant_set" + ] + }, + "invariant-types": { + "title": "witness.yaml.invariant-types", + "description": "YAML witness invariant types to output/input.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "location_invariant", + "loop_invariant" + ] + }, + "default": [ + "location_invariant", + "loop_invariant" ] }, "path": { From 4a329b0373462cc3bc266d21d4f693ccc424abfb Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 14:31:33 +0200 Subject: [PATCH 462/628] Add YAML invariant_set generation --- src/witness/yamlWitness.ml | 93 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 9e8ebeff51..c83d5b48be 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -91,6 +91,29 @@ struct metadata = metadata ~task (); } + let location_invariant' ~location ~(invariant): InvariantSet.Invariant.t = { + invariant_type = LocationInvariant { + location; + value = invariant; + format = "c_expression"; + }; + } + + let loop_invariant' ~location ~(invariant): InvariantSet.Invariant.t = { + invariant_type = LoopInvariant { + location; + value = invariant; + format = "c_expression"; + }; + } + + let invariant_set ~task ~(invariants): Entry.t = { + entry_type = InvariantSet { + content = invariants; + }; + metadata = metadata ~task (); + } + let target ~uuid ~type_ ~(file_name): Target.t = { uuid; type_; @@ -134,6 +157,9 @@ let yaml_entries_to_file yaml_entries file = let entry_type_enabled entry_type = List.mem entry_type (GobConfig.get_string_list "witness.yaml.entry-types") +let invariant_type_enabled invariant_type = + List.mem invariant_type (GobConfig.get_string_list "witness.yaml.invariant-types") + module Make (R: ResultQuery.SpecSysSol2) = struct open R @@ -385,6 +411,73 @@ struct entries in + (* Generate invariant set *) + let entries = + if entry_type_enabled YamlWitnessType.InvariantSet.entry_type then ( + let invariants = [] in + + (* Generate location invariants *) + let invariants = + if invariant_type_enabled YamlWitnessType.InvariantSet.LocationInvariant.invariant_type then ( + NH.fold (fun n local acc -> + let loc = Node.location n in + if is_invariant_node n then ( + let lvals = local_lvals n local in + match R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals}) with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Node.find_fundec n).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = CilType.Exp.show inv in + let invariant = Entry.location_invariant' ~location ~invariant in + invariant :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else + acc + ) (Lazy.force nh) invariants + ) + else + invariants + in + + (* Generate loop invariants *) + let invariants = + if entry_type_enabled YamlWitnessType.InvariantSet.LoopInvariant.invariant_type then ( + NH.fold (fun n local acc -> + let loc = Node.location n in + if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( + match R.ask_local_node n ~local (Invariant Invariant.default_context) with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Node.find_fundec n).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = CilType.Exp.show inv in + let invariant = Entry.loop_invariant' ~location ~invariant in + invariant :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else + acc + ) (Lazy.force nh) invariants + ) + else + invariants + in + + let entry = Entry.invariant_set ~task ~invariants in + entry :: entries + ) + else + entries + in + let yaml_entries = List.rev_map YamlWitnessType.Entry.to_yaml entries in (* reverse to make entries in file in the same order as generation messages *) M.msg_group Info ~category:Witness "witness generation summary" [ From fcd18652628e74bcaec601614f0852d13be4ea13 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 14:58:07 +0200 Subject: [PATCH 463/628] Add YAML invariant_set validation --- src/witness/yamlWitness.ml | 46 +++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index c83d5b48be..c66938961b 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -732,6 +732,48 @@ struct None in + let validate_invariant_set (invariant_set: YamlWitnessType.InvariantSet.t) = + + let validate_location_invariant (location_invariant: YamlWitnessType.InvariantSet.LocationInvariant.t) = + let loc = loc_of_location location_invariant.location in + let inv = location_invariant.value in + + match Locator.find_opt locator loc with + | Some lvars -> + ignore (validate_lvars_invariant ~entry_certificate:None ~loc ~lvars inv) + | None -> + incr cnt_error; + M.warn ~category:Witness ~loc:(CilLocation loc) "couldn't locate invariant: %s" inv; + in + + let validate_loop_invariant (loop_invariant: YamlWitnessType.InvariantSet.LoopInvariant.t) = + let loc = loc_of_location loop_invariant.location in + let inv = loop_invariant.value in + + match Locator.find_opt loop_locator loc with + | Some lvars -> + ignore (validate_lvars_invariant ~entry_certificate:None ~loc ~lvars inv) + | None -> + incr cnt_error; + M.warn ~category:Witness ~loc:(CilLocation loc) "couldn't locate invariant: %s" inv; + in + + let validate_invariant (invariant: YamlWitnessType.InvariantSet.Invariant.t) = + let target_type = YamlWitnessType.InvariantSet.InvariantType.invariant_type invariant.invariant_type in + match invariant_type_enabled target_type, invariant.invariant_type with + | true, LocationInvariant x -> + validate_location_invariant x + | true, LoopInvariant x -> + validate_loop_invariant x + | false, (LocationInvariant _ | LoopInvariant _) -> + incr cnt_disabled; + M.info_noloc ~category:Witness "disabled invariant of type %s" target_type; + in + + List.iter validate_invariant invariant_set.content; + None + in + match entry_type_enabled target_type, entry.entry_type with | true, LocationInvariant x -> validate_location_invariant x @@ -739,7 +781,9 @@ struct validate_loop_invariant x | true, PreconditionLoopInvariant x -> validate_precondition_loop_invariant x - | false, (LocationInvariant _ | LoopInvariant _ | PreconditionLoopInvariant _) -> + | true, InvariantSet x -> + validate_invariant_set x + | false, (LocationInvariant _ | LoopInvariant _ | PreconditionLoopInvariant _ | InvariantSet _) -> incr cnt_disabled; M.info_noloc ~category:Witness "disabled entry of type %s" target_type; None From e13bb5c3131f066fc1b793269a15c04c56cc9dbd Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 15:02:39 +0200 Subject: [PATCH 464/628] Add YAML invariant_set unassume --- src/analyses/unassumeAnalysis.ml | 44 +++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/analyses/unassumeAnalysis.ml b/src/analyses/unassumeAnalysis.ml index 43707acd1e..5895f242c9 100644 --- a/src/analyses/unassumeAnalysis.ml +++ b/src/analyses/unassumeAnalysis.ml @@ -200,6 +200,46 @@ struct M.warn ~category:Witness ~loc:msgLoc "couldn't locate invariant: %s" inv in + let unassume_invariant_set (invariant_set: YamlWitnessType.InvariantSet.t) = + + let unassume_location_invariant (location_invariant: YamlWitnessType.InvariantSet.LocationInvariant.t) = + let loc = loc_of_location location_invariant.location in + let inv = location_invariant.value in + let msgLoc: M.Location.t = CilLocation loc in + + match Locator.find_opt locator loc with + | Some nodes -> + unassume_nodes_invariant ~loc ~nodes inv + | None -> + M.warn ~category:Witness ~loc:msgLoc "couldn't locate invariant: %s" inv + in + + let unassume_loop_invariant (loop_invariant: YamlWitnessType.InvariantSet.LoopInvariant.t) = + let loc = loc_of_location loop_invariant.location in + let inv = loop_invariant.value in + let msgLoc: M.Location.t = CilLocation loc in + + match Locator.find_opt loop_locator loc with + | Some nodes -> + unassume_nodes_invariant ~loc ~nodes inv + | None -> + M.warn ~category:Witness ~loc:msgLoc "couldn't locate invariant: %s" inv + in + + let validate_invariant (invariant: YamlWitnessType.InvariantSet.Invariant.t) = + let target_type = YamlWitnessType.InvariantSet.InvariantType.invariant_type invariant.invariant_type in + match YamlWitness.invariant_type_enabled target_type, invariant.invariant_type with + | true, LocationInvariant x -> + unassume_location_invariant x + | true, LoopInvariant x -> + unassume_loop_invariant x + | false, (LocationInvariant _ | LoopInvariant _) -> + M.info_noloc ~category:Witness "disabled invariant of type %s" target_type + in + + List.iter validate_invariant invariant_set.content + in + match YamlWitness.entry_type_enabled target_type, entry.entry_type with | true, LocationInvariant x -> unassume_location_invariant x @@ -207,7 +247,9 @@ struct unassume_loop_invariant x | true, PreconditionLoopInvariant x -> unassume_precondition_loop_invariant x - | false, (LocationInvariant _ | LoopInvariant _ | PreconditionLoopInvariant _) -> + | true, InvariantSet x -> + unassume_invariant_set x + | false, (LocationInvariant _ | LoopInvariant _ | PreconditionLoopInvariant _ | InvariantSet _) -> M.info_noloc ~category:Witness "disabled entry of type %s" target_type | _ -> M.info_noloc ~category:Witness "cannot unassume entry of type %s" target_type From 90e962f53ebf4eb92ef88c5fcf8c6401f118299c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 15:15:10 +0200 Subject: [PATCH 465/628] Reverse YAML invariant_set content --- src/witness/yamlWitness.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index c66938961b..a580b319db 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -471,6 +471,7 @@ struct invariants in + let invariants = List.rev invariants in let entry = Entry.invariant_set ~task ~invariants in entry :: entries ) From ca84014548d7d585162b0afc9842dc78c2f72cef Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 7 Nov 2023 15:15:22 +0200 Subject: [PATCH 466/628] Fix YAML invariant_set parsing --- src/witness/yamlWitnessType.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/yamlWitnessType.ml b/src/witness/yamlWitnessType.ml index c68b1a45c9..f9bcf3235f 100644 --- a/src/witness/yamlWitnessType.ml +++ b/src/witness/yamlWitnessType.ml @@ -332,7 +332,7 @@ struct let of_yaml y = let open GobYaml in - let+ content = y |> list >>= list_map Invariant.of_yaml in + let+ content = y |> find "content" >>= list >>= list_map Invariant.of_yaml in {content} end From 421abcd41fa5084c3f07854b88a26a1382d253e1 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 7 Nov 2023 21:44:51 +0100 Subject: [PATCH 467/628] Warn whenever there's allocated heap memory that's unreachable from globals at program exit --- src/analyses/memLeak.ml | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index dbaa2d69fc..f7f555a70a 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -19,6 +19,22 @@ struct let context _ _ = () (* HELPER FUNCTIONS *) + let get_global_vars () = + (* Filtering by GVar seems to account for declarations, as well as definitions of global vars *) + List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + + let get_reachable_mem_from_globals (global_vars:varinfo list) ctx = + global_vars + |> List.map (fun v -> Lval (Var v, NoOffset)) + |> List.filter_map (fun exp -> + match ctx.ask (Queries.MayPointTo exp) with + | a when not (Queries.AD.is_top a) && Queries.AD.cardinal a = 1 -> + begin match List.hd @@ Queries.AD.elements a with + | Queries.AD.Addr.Addr (v, _) when (ctx.ask (Queries.IsHeapVar v)) && not (ctx.ask (Queries.IsMultiple v)) -> Some v + | _ -> None + end + | _ -> None) + let warn_for_multi_threaded ctx = if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( set_mem_safety_flag InvalidMemTrack; @@ -27,17 +43,25 @@ struct ) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = - let state = ctx.local in - if not @@ D.is_empty state then + let allocated_mem = ctx.local in + if not (D.is_empty allocated_mem) then + let reachable_mem = D.of_list (get_reachable_mem_from_globals (get_global_vars ()) ctx) in + (* Check and warn if there's unreachable allocated memory at program exit *) + let allocated_and_unreachable_mem = D.diff allocated_mem reachable_mem in + if not (D.is_empty allocated_and_unreachable_mem) then ( + set_mem_safety_flag InvalidMemTrack; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "There is unreachable allocated heap memory at program exit. A memory leak might occur for the alloc vars %a\n" (Pretty.d_list ", " CilType.Varinfo.pretty) (D.elements allocated_and_unreachable_mem) + ); + (* Check and warn if some of the allocated memory is not deallocated at program exit *) match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty allocated_mem | _ -> set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty allocated_mem (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = From 9f7224ed8d6ffeaeda226b62a71d40b1dbd247f5 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 7 Nov 2023 21:45:21 +0100 Subject: [PATCH 468/628] Add test cases for unreachable heap memory from globals --- .../regression/76-memleak/08-unreachable-mem.c | 12 ++++++++++++ .../76-memleak/09-unreachable-with-local-var.c | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/regression/76-memleak/08-unreachable-mem.c create mode 100644 tests/regression/76-memleak/09-unreachable-with-local-var.c diff --git a/tests/regression/76-memleak/08-unreachable-mem.c b/tests/regression/76-memleak/08-unreachable-mem.c new file mode 100644 index 0000000000..08e7b4e741 --- /dev/null +++ b/tests/regression/76-memleak/08-unreachable-mem.c @@ -0,0 +1,12 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +int *g; + +int main(int argc, char const *argv[]) { + g = malloc(sizeof(int)); + // Reference to g's heap contents is lost here + g = NULL; + + return 0; //WARN +} diff --git a/tests/regression/76-memleak/09-unreachable-with-local-var.c b/tests/regression/76-memleak/09-unreachable-with-local-var.c new file mode 100644 index 0000000000..1614b19132 --- /dev/null +++ b/tests/regression/76-memleak/09-unreachable-with-local-var.c @@ -0,0 +1,17 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +int *g; + +int main(int argc, char const *argv[]) { + g = malloc(sizeof(int)); + // Reference to g's heap contents is lost here + g = NULL; + // We get a false positive for p's memory being unreachable + // It's still leaked, but due to free() being commented out + // TODO: Should we only improve the error reporting for unreachable memory in this case? + int *p = malloc(sizeof(int)); + //free(p); + + return 0; //WARN +} From d5584ba06c517ec4fe2704398ae373c941032e4b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 11:11:58 +0100 Subject: [PATCH 469/628] Add `__VERIFIER_nondet_size_t` --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index f84fe1d4e3..7c376fe426 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -972,6 +972,7 @@ let svcomp_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__VERIFIER_atomic_end", special [] @@ Unlock verifier_atomic); ("__VERIFIER_nondet_loff_t", unknown []); (* cannot give it in sv-comp.c without including stdlib or similar *) ("__VERIFIER_nondet_int", unknown []); (* declare invalidate actions to prevent invalidating globals when extern in regression tests *) + ("__VERIFIER_nondet_size_t ", unknown []); (* cannot give it in sv-comp.c without including stdlib or similar *) ] let ncurses_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ From 9a06289988dc949f3b49a672678d0f059b966490 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 11:15:49 +0100 Subject: [PATCH 470/628] Add `__builtin_memcmp` --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 7c376fe426..448b621fe4 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -32,6 +32,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__builtin_strncat", special [__ "dest" [r; w]; __ "src" [r]; __ "n" []] @@ fun dest src n -> Strcat { dest; src; n = Some n; }); ("__builtin___strncat_chk", special [__ "dest" [r; w]; __ "src" [r]; __ "n" []; drop "os" []] @@ fun dest src n -> Strcat { dest; src; n = Some n; }); ("memcmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); + ("__builtin_memcmp", unknown [drop "s1" [r]; drop "s2" [r]; drop "n" []]); ("memchr", unknown [drop "s" [r]; drop "c" []; drop "n" []]); ("asctime", unknown ~attrs:[ThreadUnsafe] [drop "time_ptr" [r_deep]]); ("fclose", unknown [drop "stream" [r_deep; w_deep; f_deep]]); From 67c8d9b395e8a263f1b8a0461602d66921ddb0c4 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 11:17:10 +0100 Subject: [PATCH 471/628] Add `__builtin_strlen` --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 448b621fe4..c3726f6d95 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -63,6 +63,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("localeconv", unknown ~attrs:[ThreadUnsafe] []); ("localtime", unknown ~attrs:[ThreadUnsafe] [drop "time" [r]]); ("strlen", special [__ "s" [r]] @@ fun s -> Strlen s); + ("__builtin_strlen", special [__ "s" [r]] @@ fun s -> Strlen s); ("strstr", special [__ "haystack" [r]; __ "needle" [r]] @@ fun haystack needle -> Strstr { haystack; needle; }); ("strcmp", special [__ "s1" [r]; __ "s2" [r]] @@ fun s1 s2 -> Strcmp { s1; s2; n = None; }); ("strtok", unknown ~attrs:[ThreadUnsafe] [drop "str" [r; w]; drop "delim" [r]]); From 24aca6767df3e2f0cf4296009d761ae56749231e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 11:42:31 +0100 Subject: [PATCH 472/628] Add `__fread_unlocked_*` --- src/analyses/libraryFunctions.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index c3726f6d95..75392c2243 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -52,6 +52,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("putc", unknown [drop "ch" []; drop "stream" [r_deep; w_deep]]); ("fputs", unknown [drop "str" [r]; drop "stream" [r_deep; w_deep]]); ("fread", unknown [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); + ("fread_unlocked", unknown ~attrs:[ThreadUnsafe] [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fseek", unknown [drop "stream" [r_deep; w_deep]; drop "offset" []; drop "origin" []]); ("ftell", unknown [drop "stream" [r_deep]]); ("fwrite", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); @@ -578,6 +579,9 @@ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__fgets_chk", unknown [drop "__s" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_alias", unknown [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_chk", unknown [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); + ("__fread_unlocked_alias", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); + ("__fread_unlocked_chk", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); + ("__fread_unlocked_chk_warn", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__read_chk", unknown [drop "__fd" []; drop "__buf" [w]; drop "__nbytes" []; drop "__buflen" []]); ("__read_alias", unknown [drop "__fd" []; drop "__buf" [w]; drop "__nbytes" []]); ("__readlink_chk", unknown [drop "path" [r]; drop "buf" [w]; drop "len" []; drop "buflen" []]); From 8972bd853f3bb5b11b1c659147a34b6697d7e2cf Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 12:41:12 +0100 Subject: [PATCH 473/628] Fix typo Co-authored-by: Simmo Saan --- src/analyses/libraryFunctions.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 75392c2243..93c1cbaabe 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -978,7 +978,7 @@ let svcomp_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__VERIFIER_atomic_end", special [] @@ Unlock verifier_atomic); ("__VERIFIER_nondet_loff_t", unknown []); (* cannot give it in sv-comp.c without including stdlib or similar *) ("__VERIFIER_nondet_int", unknown []); (* declare invalidate actions to prevent invalidating globals when extern in regression tests *) - ("__VERIFIER_nondet_size_t ", unknown []); (* cannot give it in sv-comp.c without including stdlib or similar *) + ("__VERIFIER_nondet_size_t", unknown []); (* cannot give it in sv-comp.c without including stdlib or similar *) ] let ncurses_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ From b3ef0621077e46441516f91b73cd9f23ce56492e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 14:01:25 +0100 Subject: [PATCH 474/628] _Exit / _exit --- src/analyses/libraryFunctions.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 93c1cbaabe..c71c7a7f7e 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -149,6 +149,8 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atomic_flag_test_and_set_explicit", unknown [drop "obj" [r; w]; drop "order" []]); ("atomic_load", unknown [drop "obj" [r]]); ("atomic_store", unknown [drop "obj" [w]; drop "desired" []]); + ("_Exit", special [drop "status" []] @@ Abort); + ("_exit", special [drop "status" []] @@ Abort); ] (** C POSIX library functions. From 2fc622067b2a7a2754f6d67a4990ed4b05008d32 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 14:12:18 +0100 Subject: [PATCH 475/628] `__assert` --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index c71c7a7f7e..eeddfbb218 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -510,6 +510,7 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__builtin_unreachable", special' [] @@ fun () -> if get_bool "sem.builtin_unreachable.dead_code" then Abort else Unknown); (* https://github.com/sosy-lab/sv-benchmarks/issues/1296 *) ("__assert_rtn", special [drop "func" [r]; drop "file" [r]; drop "line" []; drop "exp" [r]] @@ Abort); (* MacOS's built-in assert *) ("__assert_fail", special [drop "assertion" [r]; drop "file" [r]; drop "line" []; drop "function" [r]] @@ Abort); (* gcc's built-in assert *) + ("__assert", special [drop "assertion" [r]; drop "file" [r]; drop "line" []] @@ Abort); (* header says: The following is not at all used here but needed for standard compliance. *) ("__builtin_return_address", unknown [drop "level" []]); ("__builtin___sprintf_chk", unknown (drop "s" [w] :: drop "flag" [] :: drop "os" [] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("__builtin_add_overflow", unknown [drop "a" []; drop "b" []; drop "c" [w]]); From c4353f9f2c46e1f9b6b6d0e9d3d7168ccdc8a577 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Nov 2023 14:15:02 +0100 Subject: [PATCH 476/628] Move `_exit` to C, as C usually takes precedence over posix for us --- src/analyses/libraryFunctions.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index eeddfbb218..7774e37ee2 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -340,7 +340,6 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("regexec", unknown [drop "preg" [r_deep]; drop "string" [r]; drop "nmatch" []; drop "pmatch" [w_deep]; drop "eflags" []]); ("regfree", unknown [drop "preg" [f_deep]]); ("ffs", unknown [drop "i" []]); - ("_exit", special [drop "status" []] Abort); ("execvp", unknown [drop "file" [r]; drop "argv" [r_deep]]); ("execl", unknown (drop "path" [r] :: drop "arg" [r] :: VarArgs (drop' [r]))); ("statvfs", unknown [drop "path" [r]; drop "buf" [w]]); From c056b32954f095f4ee4ab3a2fcab536eec35bdf2 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 8 Nov 2023 20:51:19 +0100 Subject: [PATCH 477/628] Remove //TODO comment from `76/09` --- tests/regression/76-memleak/09-unreachable-with-local-var.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/regression/76-memleak/09-unreachable-with-local-var.c b/tests/regression/76-memleak/09-unreachable-with-local-var.c index 1614b19132..bc71bb560e 100644 --- a/tests/regression/76-memleak/09-unreachable-with-local-var.c +++ b/tests/regression/76-memleak/09-unreachable-with-local-var.c @@ -7,11 +7,9 @@ int main(int argc, char const *argv[]) { g = malloc(sizeof(int)); // Reference to g's heap contents is lost here g = NULL; - // We get a false positive for p's memory being unreachable - // It's still leaked, but due to free() being commented out - // TODO: Should we only improve the error reporting for unreachable memory in this case? + + // According to `valid-memtrack`, the memory of p is unreachable and we don't have a false positive int *p = malloc(sizeof(int)); - //free(p); return 0; //WARN } From 175b003aa3fae00a07052e6ae58d3cf6a8173cac Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 8 Nov 2023 21:52:45 +0200 Subject: [PATCH 478/628] Don't set `InvalidMemTrack` flag a second time Co-authored-by: Michael Schwarz --- src/analyses/memLeak.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index f7f555a70a..865ecaffc4 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -55,7 +55,6 @@ struct (* Check and warn if some of the allocated memory is not deallocated at program exit *) match assert_exp_imprecise, exp with | true, Some exp -> - set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty allocated_mem | _ -> From 05e4892feac736b520c81c151ed5b2558187e1a0 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 8 Nov 2023 21:53:56 +0200 Subject: [PATCH 479/628] Don't set `InvalidMemTrack` flag a second time Co-authored-by: Michael Schwarz --- src/analyses/memLeak.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 865ecaffc4..fc015f458b 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -58,7 +58,6 @@ struct set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty allocated_mem | _ -> - set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty allocated_mem From f343d74efa850011f6ebebf1ce819f9bc1acefb9 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 8 Nov 2023 22:52:27 +0100 Subject: [PATCH 480/628] Add 3 regr. tests for trying out global struct variables --- .../76-memleak/10-global-struct-no-ptr.c | 16 ++++++++++++ .../76-memleak/11-global-struct-ptr.c | 19 ++++++++++++++ .../76-memleak/12-global-nested-struct-ptr.c | 25 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 tests/regression/76-memleak/10-global-struct-no-ptr.c create mode 100644 tests/regression/76-memleak/11-global-struct-ptr.c create mode 100644 tests/regression/76-memleak/12-global-nested-struct-ptr.c diff --git a/tests/regression/76-memleak/10-global-struct-no-ptr.c b/tests/regression/76-memleak/10-global-struct-no-ptr.c new file mode 100644 index 0000000000..490b2bb443 --- /dev/null +++ b/tests/regression/76-memleak/10-global-struct-no-ptr.c @@ -0,0 +1,16 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +typedef struct st { + int *a; + int b; +} st; + +st st_nonptr; + +int main(int argc, char const *argv[]) { + st_nonptr.a = malloc(sizeof(int)); + st_nonptr.a = NULL; + + return 0; //WARN +} diff --git a/tests/regression/76-memleak/11-global-struct-ptr.c b/tests/regression/76-memleak/11-global-struct-ptr.c new file mode 100644 index 0000000000..4ebe1c16b8 --- /dev/null +++ b/tests/regression/76-memleak/11-global-struct-ptr.c @@ -0,0 +1,19 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +typedef struct st { + int *a; + int b; +} st; + +st *st_ptr; + +int main(int argc, char const *argv[]) { + st_ptr = malloc(sizeof(st)); + st_ptr->a = malloc(sizeof(int)); + st_ptr->a = NULL; + free(st_ptr); + + // Only st_ptr->a is causing trouble here + return 0; //WARN +} diff --git a/tests/regression/76-memleak/12-global-nested-struct-ptr.c b/tests/regression/76-memleak/12-global-nested-struct-ptr.c new file mode 100644 index 0000000000..e0f5175064 --- /dev/null +++ b/tests/regression/76-memleak/12-global-nested-struct-ptr.c @@ -0,0 +1,25 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +typedef struct st { + int *a; + int b; +} st; + +typedef struct st2 { + st *st_ptr; +} st2; + +st2 *st_var; + +int main(int argc, char const *argv[]) { + st_var = malloc(sizeof(st2)); + st_var->st_ptr = malloc(sizeof(st)); + st_var->st_ptr->a = malloc(sizeof(int)); + st_var->st_ptr->a = NULL; + free(st_var->st_ptr); + free(st_var); + + // Only st_var->st_ptr->a is causing trouble here + return 0; //WARN +} From dd3de9e01ef9bce8d04369c7e698f973f25d00ea Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 9 Nov 2023 10:16:11 +0100 Subject: [PATCH 481/628] Move `_exit` back --- src/analyses/libraryFunctions.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 7774e37ee2..df3217e380 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -150,7 +150,6 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atomic_load", unknown [drop "obj" [r]]); ("atomic_store", unknown [drop "obj" [w]; drop "desired" []]); ("_Exit", special [drop "status" []] @@ Abort); - ("_exit", special [drop "status" []] @@ Abort); ] (** C POSIX library functions. @@ -340,6 +339,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("regexec", unknown [drop "preg" [r_deep]; drop "string" [r]; drop "nmatch" []; drop "pmatch" [w_deep]; drop "eflags" []]); ("regfree", unknown [drop "preg" [f_deep]]); ("ffs", unknown [drop "i" []]); + ("_exit", special [drop "status" []] @@ Abort); ("execvp", unknown [drop "file" [r]; drop "argv" [r_deep]]); ("execl", unknown (drop "path" [r] :: drop "arg" [r] :: VarArgs (drop' [r]))); ("statvfs", unknown [drop "path" [r]; drop "buf" [w]]); From 39a942752434625e0044f59158484d203752fb58 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 9 Nov 2023 10:18:15 +0100 Subject: [PATCH 482/628] Move `fread_unlocked` to glibc --- src/analyses/libraryFunctions.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index df3217e380..117dcbd236 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -52,7 +52,6 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("putc", unknown [drop "ch" []; drop "stream" [r_deep; w_deep]]); ("fputs", unknown [drop "str" [r]; drop "stream" [r_deep; w_deep]]); ("fread", unknown [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); - ("fread_unlocked", unknown ~attrs:[ThreadUnsafe] [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fseek", unknown [drop "stream" [r_deep; w_deep]; drop "offset" []; drop "origin" []]); ("ftell", unknown [drop "stream" [r_deep]]); ("fwrite", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); @@ -581,6 +580,7 @@ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__fgets_chk", unknown [drop "__s" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_alias", unknown [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_chk", unknown [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); + ("fread_unlocked", unknown ~attrs:[ThreadUnsafe] [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("__fread_unlocked_alias", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_unlocked_chk", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_unlocked_chk_warn", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); From f7c022fcfbf53f9b0673dcd78a69f9beb176643a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 9 Nov 2023 12:38:50 +0200 Subject: [PATCH 483/628] Account for invariant_set size when esitmating YAML witness buffer --- src/witness/yamlWitness.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index a580b319db..2c0340a997 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -143,12 +143,12 @@ struct } end -let yaml_entries_to_file yaml_entries file = +let yaml_entries_to_file ?(invariants=0) yaml_entries file = let yaml = `A yaml_entries in (* Yaml_unix.to_file_exn file yaml *) (* to_file/to_string uses a fixed-size buffer... *) (* estimate how big it should be + extra in case empty *) - let text = match Yaml.to_string ~len:(List.length yaml_entries * 4096 + 2048) yaml with + let text = match Yaml.to_string ~len:((List.length yaml_entries + invariants) * 4096 + 2048) yaml with | Ok text -> text | Error (`Msg m) -> failwith ("Yaml.to_string: " ^ m) in @@ -412,7 +412,7 @@ struct in (* Generate invariant set *) - let entries = + let (entries, invariants) = if entry_type_enabled YamlWitnessType.InvariantSet.entry_type then ( let invariants = [] in @@ -473,10 +473,10 @@ struct let invariants = List.rev invariants in let entry = Entry.invariant_set ~task ~invariants in - entry :: entries + (entry :: entries, List.length invariants) ) else - entries + (entries, 0) in let yaml_entries = List.rev_map YamlWitnessType.Entry.to_yaml entries in (* reverse to make entries in file in the same order as generation messages *) @@ -485,7 +485,7 @@ struct (Pretty.dprintf "total generation entries: %d" (List.length yaml_entries), None); ]; - yaml_entries_to_file yaml_entries (Fpath.v (GobConfig.get_string "witness.yaml.path")) + yaml_entries_to_file ~invariants yaml_entries (Fpath.v (GobConfig.get_string "witness.yaml.path")) let write () = Timing.wrap "yaml witness" write () From d884744ccb793eb4e0c21fdb507e876932efcc9f Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 9 Nov 2023 12:43:33 +0200 Subject: [PATCH 484/628] Add option witness.yaml.format-version --- src/common/util/options.schema.json | 10 ++++++++++ src/witness/yamlWitness.ml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index a51c5c59cf..5993c5b1e4 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2418,6 +2418,16 @@ "type": "boolean", "default": false }, + "format-version": { + "title": "witness.yaml.format-version", + "description": "YAML witness format version", + "type": "string", + "enum": [ + "0.1", + "2.0" + ], + "default": "0.1" + }, "entry-types": { "title": "witness.yaml.entry-types", "description": "YAML witness entry types to output/input.", diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 2c0340a997..019ee67813 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -25,7 +25,7 @@ struct let uuid = Uuidm.v4_gen uuid_random_state () in let creation_time = TimeUtil.iso8601_now () in { - format_version = "0.1"; + format_version = GobConfig.get_string "witness.yaml.format-version"; uuid = Uuidm.to_string uuid; creation_time; producer; From a933266b4a6fbf8a47937d657401dc6e14b378f6 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 9 Nov 2023 13:08:52 +0200 Subject: [PATCH 485/628] Fix invariant_set loop_invariant option check --- src/witness/yamlWitness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 019ee67813..f8532a1551 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -446,7 +446,7 @@ struct (* Generate loop invariants *) let invariants = - if entry_type_enabled YamlWitnessType.InvariantSet.LoopInvariant.invariant_type then ( + if invariant_type_enabled YamlWitnessType.InvariantSet.LoopInvariant.invariant_type then ( NH.fold (fun n local acc -> let loc = Node.location n in if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( From 7fc834308201ea8e7d2cd0d8c79bfe0c81833cae Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 9 Nov 2023 13:56:10 +0200 Subject: [PATCH 486/628] Fix relation read_globals_to_locals reading untracked variables --- src/analyses/apron/relationAnalysis.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 13f549fc44..0fa26781dd 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -70,7 +70,7 @@ struct let visitor = object inherit nopCilVisitor method! vlval = function - | (Var v, NoOffset) when v.vglob || ThreadEscape.has_escaped ask v -> + | (Var v, NoOffset) when (v.vglob || ThreadEscape.has_escaped ask v) && RD.Tracked.varinfo_tracked v -> let v_in = if VH.mem v_ins v then VH.find v_ins v From fbc66e32b897891d5a00dbe47ee719df7de75772 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 9 Nov 2023 15:18:59 +0200 Subject: [PATCH 487/628] Remove default Apron polyhedra in svcomp24-validate conf --- conf/svcomp24-validate.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/conf/svcomp24-validate.json b/conf/svcomp24-validate.json index 6479bd01b5..ce11af12f6 100644 --- a/conf/svcomp24-validate.json +++ b/conf/svcomp24-validate.json @@ -12,10 +12,6 @@ "float": { "interval": true }, - "apron": { - "domain": "polyhedra", - "strengthening": true - }, "activated": [ "base", "threadid", @@ -35,8 +31,7 @@ "region", "thread", "threadJoins", - "unassume", - "apron" + "unassume" ], "path_sens": [ "mutex", From fb92abc2904021e5ec3f7bf075b25bf305a97c14 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:24:20 +0100 Subject: [PATCH 488/628] Rename NonTerminating -> Termination --- scripts/update_suite.rb | 2 +- src/analyses/loopTermination.ml | 4 ++-- src/common/util/messageCategory.ml | 10 +++++----- src/common/util/options.schema.json | 6 +++--- src/framework/constraints.ml | 4 ++-- src/framework/control.ml | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index a7d60b5c21..bbf1a71a9d 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,7 +145,7 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning + if l =~ /\[Termination\]/ then warnings[-1] = "nonterm" end # Get Termination warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 077615ad10..f4db165795 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -49,7 +49,7 @@ struct let finalize () = (* Multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n" ) (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the @@ -64,7 +64,7 @@ struct ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( - M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:NonTerminating "The program might not terminate! (Loop analysis)" + M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:Termination "The program might not terminate! (Loop analysis)" ); () with Not_found -> diff --git a/src/common/util/messageCategory.ml b/src/common/util/messageCategory.ml index ba589db8d0..41c9bc08e1 100644 --- a/src/common/util/messageCategory.ml +++ b/src/common/util/messageCategory.ml @@ -46,7 +46,7 @@ type category = | Imprecise | Witness | Program - | NonTerminating + | Termination [@@deriving eq, ord, hash] type t = category [@@deriving eq, ord, hash] @@ -205,7 +205,7 @@ let should_warn e = | Imprecise -> "imprecise" | Witness -> "witness" | Program -> "program" - | NonTerminating -> "nonTerminating" + | Termination -> "termination" (* Don't forget to add option to schema! *) in get_bool ("warn." ^ (to_string e)) @@ -226,7 +226,7 @@ let path_show e = | Imprecise -> ["Imprecise"] | Witness -> ["Witness"] | Program -> ["Program"] - | NonTerminating -> ["NonTerminating"] + | Termination -> ["Termination"] let show x = String.concat " > " (path_show x) @@ -266,7 +266,7 @@ let categoryName = function | Overflow -> "Overflow"; | DivByZero -> "DivByZero") | Float -> "Float" - | NonTerminating -> "NonTerminating" + | Termination -> "Termination" let from_string_list (s: string list) = @@ -287,7 +287,7 @@ let from_string_list (s: string list) = | "imprecise" -> Imprecise | "witness" -> Witness | "program" -> Program - | "nonTerminating" -> NonTerminating + | "termination" -> Termination | _ -> Unknown let to_yojson x = `List (List.map (fun x -> `String x) (path_show x)) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index c6e00d3da3..0b6f8b649f 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2105,9 +2105,9 @@ "type": "boolean", "default": true }, - "nonTerminating": { - "title": "warn.nonTerminating", - "description": "Non Termination warning", + "termination": { + "title": "warn.termination", + "description": "Non-Termination warning", "type": "boolean", "default": true }, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6ba31488de..b1bbc73660 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1689,7 +1689,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( AnalysisState.svcomp_may_not_terminate := true; - M.warn ~category:NonTerminating "The program might not terminate! (Longjmp)" + M.warn ~category:Termination "The program might not terminate! (Longjmp)" ); S.D.bot () | _ -> S.special conv_ctx lv f args @@ -1774,7 +1774,7 @@ struct AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let loc = M.Location.CilLocation fundec.svar.vdecl in - M.warn ~loc ~category:NonTerminating "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) + M.warn ~loc ~category:Termination "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in diff --git a/src/framework/control.ml b/src/framework/control.ml index ae1cb3e2b3..a78f125eae 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -146,7 +146,7 @@ struct let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( AnalysisState.svcomp_may_not_terminate := true; - M.warn ~loc:(M.Location.CilLocation l) ~category:NonTerminating "The program might not terminate! (Upjumping Goto)"); + M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)"); ) (!live_lines)) (!Cilfacade.upjumping_gotos); From aad465cf1803bc9ee0d10373e90397e4f0809321 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:33:35 +0100 Subject: [PATCH 489/628] Autotune for Termination --- src/autoTune.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 8300241bac..c756b17eb2 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -243,7 +243,14 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | Termination -> () + | Termination -> + let terminationAnas = ["termination"; "isEverMultiThreaded"; "apron"] in + print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; + enableAnalyses terminationAnas; + set_string "sem.int.signed_overflow" "assume_none"; + set_bool "ana.int.interval" true; + set_string "ana.apron.domain" "polyhedra"; (* TODO: Needed? *) + () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true From 2ff979bb14dd41896e1ad3f2c3dff6f1af574241 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:54:35 +0100 Subject: [PATCH 490/628] Simplify variable names --- src/util/terminationPreprocessing.ml | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 32a9468233..8070438943 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,22 +2,16 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let extract_file_name s = (*There still may be a need to filter more chars*) - let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) - let ls = List.rev ls in - let s' = List.nth ls 0 in - let ls = String.split_on_char '.' s' in - let s' = List.nth ls 0 in - let without_spaces = String.split_on_char ' ' s' in - let s' = String.concat "" without_spaces in - s' - -let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file - class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor + (* Counter of variables inserted for termination *) + val mutable vcounter = ref 0 + + method! vfunc _ = + vcounter := 0; + DoChildren + method! vstmt s = let specialFunction name = @@ -36,9 +30,9 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in + incr vcounter; + let v = Cil.makeLocalVar fd vname Cil.intType in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in From b49356c2451d2576b73d2d42813aad01c37c5eaa Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:02:52 +0100 Subject: [PATCH 491/628] Deduplicate preprocessing --- src/analyses/loopTermination.ml | 2 +- src/common/util/cilfacade.ml | 16 +--------------- src/util/cilCfg.ml | 6 ++---- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index f4db165795..312bcfd9b9 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -99,5 +99,5 @@ struct end let () = - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters); + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor loop_counters); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 47cf6d6210..d645fd949d 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -74,27 +74,13 @@ let print (fileAST: file) = let rmTemps fileAST = RmUnused.removeUnused fileAST - let visitors = ref [] let register_preprocess name visitor_fun = visitors := !visitors @ [name, visitor_fun] let do_preprocess ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) - -let visitors_cil = ref [] -(* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) -let register_preprocess_cil name visitor_fun = - visitors_cil := !visitors_cil @ [name, visitor_fun] - -let do_preprocess_cil ast = (* this has to be done here, since the settings aren't available when register_preprocess is called *) - let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors_cil in + let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors in let f fd visitor_fun = ignore @@ visitCilFunction (visitor_fun fd) fd in if active_visitors <> [] then iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) active_visitors | _ -> ()) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 72143e97d7..923cf7600b 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -42,6 +42,7 @@ let loopCount file = let createCFG (fileAST: file) = + Cilfacade.do_preprocess fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -50,7 +51,6 @@ let createCFG (fileAST: file) = (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) (* the preprocessing must be done here, to add the changes of CIL to the CFG*) - Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; (* We used to renumber vids but CIL already generates them fresh, so no need. @@ -68,6 +68,4 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); - - Cilfacade.do_preprocess fileAST + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); \ No newline at end of file From 490203df2dcf64cb8a9ccfcbd8286bc50f85e37a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:21:51 +0100 Subject: [PATCH 492/628] Move `everMultiThreaded` to `threadflag` --- src/analyses/everMultiThreaded.ml | 47 ------------------------------- src/analyses/threadFlag.ml | 4 +++ src/autoTune.ml | 4 +-- src/framework/analyses.ml | 6 ++++ src/maingoblint.ml | 4 +-- 5 files changed, 14 insertions(+), 51 deletions(-) delete mode 100644 src/analyses/everMultiThreaded.ml diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml deleted file mode 100644 index 2ab203887c..0000000000 --- a/src/analyses/everMultiThreaded.ml +++ /dev/null @@ -1,47 +0,0 @@ -(** Analysis to register whether any additional thread has ever been spawned ([evermultithreaded]). *) - -open Analyses - -module UnitV = -struct - include Printable.Unit - include StdV -end - -module Spec : Analyses.MCPSpec = -struct - - (** Provides some default implementations *) - include Analyses.IdentitySpec - - let name () = "evermultithreaded" - - module D = Lattice.Unit - module C = D - module V = UnitV - module G = BoolDomain.MayBool - - let startstate _ = () - let exitstate = startstate - - (** Sets the global invariant to true when a thread is spawned *) - let threadspawn ctx ~multiple lval f args fctx = - ctx.sideg () true; - () - - let query ctx (type a) (q: a Queries.t) : a Queries.result = - match q with - | Queries.IsEverMultiThreaded -> - (match ctx.global () with - (* I don't know why this wrapping in a match construct is necessary. - * Without it, the compiler throws an error. *) - true -> true - | false -> false) - | _ -> - Queries.Result.top q - -end - -let () = - (* Register this analysis within the master control program *) - MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/threadFlag.ml b/src/analyses/threadFlag.ml index 6bd466caef..a751ae074a 100644 --- a/src/analyses/threadFlag.ml +++ b/src/analyses/threadFlag.ml @@ -21,6 +21,8 @@ struct module D = Flag module C = Flag module P = IdentityP (D) + module V = UnitV + module G = BoolDomain.MayBool let name () = "threadflag" @@ -44,6 +46,7 @@ struct match x with | Queries.MustBeSingleThreaded _ -> not (Flag.is_multi ctx.local) (* If this analysis can tell, it is the case since the start *) | Queries.MustBeUniqueThread -> not (Flag.is_not_main ctx.local) + | Queries.IsEverMultiThreaded -> (ctx.global () : bool) (* requires annotation to compile *) (* This used to be in base but also commented out. *) (* | Queries.MayBePublic _ -> Flag.is_multi ctx.local *) | _ -> Queries.Result.top x @@ -64,6 +67,7 @@ struct [create_tid f] let threadspawn ctx ~multiple lval f args fctx = + ctx.sideg () true; if not (has_ever_been_multi (Analyses.ask_of_ctx ctx)) then ctx.emit Events.EnterMultiThreaded; D.join ctx.local (Flag.get_main ()) diff --git a/src/autoTune.ml b/src/autoTune.ml index c756b17eb2..51e4ea412e 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -180,7 +180,7 @@ let enableAnalyses anas = List.iter (GobConfig.set_auto "ana.activated[+]") anas (*If only one thread is used in the program, we can disable most thread analyses*) -(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> isEverMultiThreaded *) +(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> threadflag *) (*escape is also still enabled, because otherwise we get a warning*) (*does not consider dynamic calls!*) @@ -244,7 +244,7 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; | Termination -> - let terminationAnas = ["termination"; "isEverMultiThreaded"; "apron"] 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/framework/analyses.ml b/src/framework/analyses.ml index 5fb09546cb..a37a3043c2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -612,6 +612,12 @@ struct let is_write_only _ = false end +module UnitV = +struct + include Printable.Unit + include StdV +end + module VarinfoV = struct include CilType.Varinfo (* TODO: or Basetype.Variables? *) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index b9cc6c7e47..937c646d47 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,9 +162,9 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( - set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); + set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); set_string "sem.int.signed_overflow" "assume_none"; - warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" + warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" From e25b708198ab19972677c3a4f7f4de5ca0243209 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:40:24 +0100 Subject: [PATCH 493/628] Simplify `loopTermination` --- src/analyses/loopTermination.ml | 40 ++++++++------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 312bcfd9b9..e24b321d05 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,10 +4,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -(** Stores the result of the query whether the program is single threaded or not - since finalize does not have access to ctx. *) -let single_thread : bool ref = ref false - (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -35,23 +31,12 @@ struct module D = Lattice.Unit module C = D - module V = - struct - include Printable.Unit - let is_write_only _ = true - end + module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () let exitstate = startstate - (** Warnings for detected possible non-termination *) - let finalize () = - (* Multithreaded *) - if not (!single_thread) then ( - M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n" - ) - (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -72,28 +57,21 @@ struct | _ -> () else () - (* Checks whether the program always remains single-threaded. - If the program does not remain single-threaded, we assume non-termination (see query function). *) - let must_always_be_single_threaded ctx = - let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in - single_thread := single_threaded; - single_threaded - let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_always_be_single_threaded ctx + let multithreaded = ctx.ask Queries.IsEverMultiThreaded in + (not multithreaded) && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) | Queries.MustTermAllLoops -> - let always_single_threaded = must_always_be_single_threaded ctx in - (* Must be the first to be evaluated! This has the side effect that - * single_thread is set. In case of another order and due to lazy - * evaluation, the correct value of single_thread can not be guaranteed! - * Therefore, we use a let-in clause here. *) - always_single_threaded - && G.for_all (fun _ term_info -> term_info) (ctx.global ()) + let multithreaded = ctx.ask Queries.IsEverMultiThreaded in + if multithreaded then ( + M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n"; + false) + else + G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end From d4ab699b1717ba1b52d86ef609c6f8800f552e13 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:46:37 +0100 Subject: [PATCH 494/628] Fail when `termination` is active and incremental analysis is enabled --- src/maingoblint.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 937c646d47..878e68dcf5 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,6 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( + if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); set_string "sem.int.signed_overflow" "assume_none"; warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" From 47d0f5d258c493a8ee05691a29cdcee5dce55c32 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:55:07 +0100 Subject: [PATCH 495/628] Termination: set `is_write_only` --- src/analyses/loopTermination.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index e24b321d05..7cde0cb9c6 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -31,7 +31,10 @@ struct module D = Lattice.Unit module C = D - module V = UnitV + module V = struct + include UnitV + let is_write_only _ = true + end module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () From 4417b9c8f02fb349184e27342e1a8b981f01cb18 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 21:01:26 +0100 Subject: [PATCH 496/628] Reset `upjumping_gotos` --- src/common/util/cilfacade.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index d645fd949d..8b55c0a1ba 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -667,6 +667,10 @@ let find_stmt_sid sid = with Not_found -> IntH.find (ResettableLazy.force stmt_sids) sid +(** Contains the locations of the upjumping gotos and the respective functions + * they are being called in. *) +let upjumping_gotos : (location * fundec) list ref = ref [] + let reset_lazy () = StmtH.clear pseudo_return_to_fun; ResettableLazy.reset stmt_fundecs; @@ -674,7 +678,8 @@ let reset_lazy () = ResettableLazy.reset name_fundecs; ResettableLazy.reset varinfo_roles; ResettableLazy.reset original_names; - ResettableLazy.reset stmt_sids + ResettableLazy.reset stmt_sids; + upjumping_gotos := [] let stmt_pretty_short () x = @@ -699,8 +704,4 @@ let add_function_declarations (file: Cil.file): unit = in let fun_decls = List.filter_map declaration_from_GFun functions in let globals = upto_last_type @ fun_decls @ non_types @ functions in - file.globals <- globals - -(** Contains the locations of the upjumping gotos and the respective functions - * they are being called in. *) -let upjumping_gotos : (location * fundec) list ref = ref [] + file.globals <- globals \ No newline at end of file From de416eeb01e12df4874679da3437358e11405a74 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 22:09:47 +0100 Subject: [PATCH 497/628] Cleanup upjumping_gotos --- src/common/util/cilfacade.ml | 10 +++++---- src/framework/control.ml | 32 ++++++++++++++++------------ src/maingoblint.ml | 2 +- src/util/terminationPreprocessing.ml | 12 ++++++++--- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 8b55c0a1ba..26a2f082a4 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -666,20 +666,22 @@ let find_stmt_sid sid = try IntH.find pseudo_return_stmt_sids sid with Not_found -> IntH.find (ResettableLazy.force stmt_sids) sid +module FunLocH = Hashtbl.Make(CilType.Fundec) +module LocSet = Hashtbl.Make(CilType.Location) (** Contains the locations of the upjumping gotos and the respective functions * they are being called in. *) -let upjumping_gotos : (location * fundec) list ref = ref [] +let funs_with_upjumping_gotos: unit LocSet.t FunLocH.t = FunLocH.create 13 -let reset_lazy () = +let reset_lazy ?(keepupjumpinggotos=false) () = StmtH.clear pseudo_return_to_fun; + if not keepupjumpinggotos then FunLocH.clear funs_with_upjumping_gotos; ResettableLazy.reset stmt_fundecs; ResettableLazy.reset varinfo_fundecs; ResettableLazy.reset name_fundecs; ResettableLazy.reset varinfo_roles; ResettableLazy.reset original_names; - ResettableLazy.reset stmt_sids; - upjumping_gotos := [] + ResettableLazy.reset stmt_sids let stmt_pretty_short () x = diff --git a/src/framework/control.ml b/src/framework/control.ml index a78f125eae..0c9b61739b 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -105,6 +105,8 @@ struct let module StringMap = BatMap.Make (String) in let live_lines = ref StringMap.empty in let dead_lines = ref StringMap.empty in + let module FunSet = Hashtbl.Make (CilType.Fundec) in + let live_funs: unit FunSet.t = FunSet.create 13 in let add_one n v = match n with | Statement s when Cilfacade.(StmtH.mem pseudo_return_to_fun s) -> @@ -115,6 +117,7 @@ struct See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *) let l = UpdateCil.getLoc n in let f = Node.find_fundec n in + FunSet.replace live_funs f (); let add_fun = BatISet.add l.line in let add_file = StringMap.modify_def BatISet.empty f.svar.vname add_fun in let is_dead = LT.for_all (fun (_,x,f) -> Spec.D.is_bot x) v in @@ -136,20 +139,21 @@ struct try StringMap.find fn (StringMap.find file !live_lines) with Not_found -> BatISet.empty in - (*check if we have upjumping gotos*) - List.iter - (fun x -> - let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) - let fname = fd.svar.vname in - StringMap.iter - (fun fi _ -> - let fundec_live = live fi fname in - if ( not (BatISet.is_empty fundec_live)) then ( - AnalysisState.svcomp_may_not_terminate := true; - M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)"); - ) - (!live_lines)) - (!Cilfacade.upjumping_gotos); + if List.mem "termination" @@ get_string_list "ana.activated" then ( + (* check if we have upjumping gotos *) + let open Cilfacade in + let warn_for_upjumps fundec gotos = + if FunSet.mem live_funs fundec then ( + (* set nortermiantion flag *) + AnalysisState.svcomp_may_not_terminate := true; + (* iterate through locations to produce warnings *) + LocSet.iter (fun l _ -> + M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)" + ) gotos + ) + in + FunLocH.iter warn_for_upjumps funs_with_upjumping_gotos + ); dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 878e68dcf5..c44a6d9360 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -493,7 +493,7 @@ let merge_parsed parsed = Cilfacade.current_file := merged_AST; (* Set before createCFG, so Cilfacade maps can be computed for loop unrolling. *) CilCfg.createCFG merged_AST; (* Create CIL CFG from CIL AST. *) - Cilfacade.reset_lazy (); (* Reset Cilfacade maps, which need to be recomputer after loop unrolling. *) + Cilfacade.reset_lazy ~keepupjumpinggotos:true (); (* Reset Cilfacade maps, which need to be recomputer after loop unrolling but keep gotos. *) merged_AST let preprocess_parse_merge () = diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 8070438943..4674a0ca10 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -50,9 +50,15 @@ class loopCounterVisitor lc (fd : fundec) = object(self) | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in let loc_stmt = Cil.get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - Cilfacade.upjumping_gotos := List.append !Cilfacade.upjumping_gotos ([(l, fd)] : (location * fundec) list); (*problem: the program might not terminate!*) + if CilType.Location.compare l loc_stmt >= 0 then ( + (* is pos if first loc is greater -> below the second loc *) + (* problem: the program might not terminate! *) + let open Cilfacade in + let current = FunLocH.find_opt funs_with_upjumping_gotos fd in + let current = BatOption.default (LocSet.create 13) current in + LocSet.replace current l (); + FunLocH.replace funs_with_upjumping_gotos fd current; + ); s | _ -> s in ChangeDoChildrenPost (s, action); From e66cf56afc8473c3bc76494a8f104ced4aa1c0ee Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 9 Nov 2023 18:12:21 +0100 Subject: [PATCH 498/628] Make type of variables used for loop termination analysis more easily exchangable. --- src/util/terminationPreprocessing.ml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4674a0ca10..a0065caabc 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,6 +2,11 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +let counter_ikind = IInt +let counter_typ = TInt (counter_ikind, []) +let min_int_exp = Const(CInt(Cilint.zero_cilint, counter_ikind, None)) +let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor @@ -15,7 +20,7 @@ class loopCounterVisitor lc (fd : fundec) = object(self) method! vstmt s = let specialFunction name = - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", counter_typ, [])], false,[])); smaxid = 0; slocals = []; sformals = []; @@ -24,7 +29,12 @@ class loopCounterVisitor lc (fd : fundec) = object(self) sallstmts = []; } in - let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + + let increment_expression lval = + let et = typeOf lval in + let bop = PlusA in + let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in + constFold false (BinOp(bop, lval, one, et)) in let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in @@ -32,11 +42,12 @@ class loopCounterVisitor lc (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in incr vcounter; - let v = Cil.makeLocalVar fd vname Cil.intType in (*Not tested for incremental mode*) + let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) + let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; From e02801a1dd0c33aa12917a7ec3380cd01b4ef866 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 10 Nov 2023 10:58:41 +0100 Subject: [PATCH 499/628] Remove redundant code for setting todo variable --- scripts/update_suite.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index bbf1a71a9d..258626422e 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -331,20 +331,14 @@ def parse_tests (lines) end end case lines[0] - when /TODO/ - case lines[0] - when /NONTERM/ - tests[-1] = "nonterm" - todo << -1 - when /TERM/ - tests[-1] = "term" - todo << -1 - end when /NONTERM/ tests[-1] = "nonterm" when /TERM/ tests[-1] = "term" end + if lines[0] =~ /TODO/ then + todo << -1 + end Tests.new(self, tests, tests_line, todo) end From 3d3c06956f787ba0f8f98278d33a647749b3da68 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:14:45 +0100 Subject: [PATCH 500/628] Add define min_int_exp depending on the signedness of the counter variable introduced. Also remove custom definition for incrementing expression by one. --- src/util/terminationPreprocessing.ml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index a0065caabc..9605484af3 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -4,8 +4,12 @@ module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter va let counter_ikind = IInt let counter_typ = TInt (counter_ikind, []) -let min_int_exp = Const(CInt(Cilint.zero_cilint, counter_ikind, None)) -let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) +let min_int_exp = + (* Currently only tested for IInt type, which is signed *) + if Cil.isSigned counter_ikind then + Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + else + Const(CInt(Cilint.zero_cilint, counter_ikind, None)) class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor @@ -29,13 +33,6 @@ class loopCounterVisitor lc (fd : fundec) = object(self) sallstmts = []; } in - - let increment_expression lval = - let et = typeOf lval in - let bop = PlusA in - let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in - constFold false (BinOp(bop, lval, one, et)) in - let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in let action s = match s.skind with @@ -45,8 +42,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) From 46b0f672b2dc1a28a1c3eff6001de0b71a4f52ca Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:48:18 +0100 Subject: [PATCH 501/628] Change indentation in update_suite.rb back to reduce number of lines changed. --- scripts/update_suite.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 258626422e..ab2aeea53f 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -151,25 +151,25 @@ def collect_warnings ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /(Upjumping Goto)/ then "goto" + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /(Loop analysis)/ then "loop" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" end oldwarn = warnings[i] From 21d405db4814cff6eafbdc059412282530f87377 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:49:49 +0100 Subject: [PATCH 502/628] Change indentatation back. --- scripts/update_suite.rb | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index ab2aeea53f..8817ef599a 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -150,27 +150,27 @@ def collect_warnings obj,i = $1,$2.to_i ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] - thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" + thiswarn = case obj + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" end oldwarn = warnings[i] if oldwarn.nil? then From bc126fabf558024b61fd7eee6bb5613daaab9818 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:50:46 +0100 Subject: [PATCH 503/628] Fix indentation of line. --- scripts/update_suite.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 8817ef599a..2722b3ddb5 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -171,7 +171,7 @@ def collect_warnings when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" - end + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn From 0e0986a974c9ae86f7af188b5d604d7c264fb593 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 13:24:04 +0100 Subject: [PATCH 504/628] Use Z instead of Cilint --- src/util/terminationPreprocessing.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 9605484af3..4e25f232e3 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,4 +1,5 @@ open GoblintCil +(* module Z = Big_int_Z *) module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) @@ -7,9 +8,9 @@ let counter_typ = TInt (counter_ikind, []) let min_int_exp = (* Currently only tested for IInt type, which is signed *) if Cil.isSigned counter_ikind then - Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + Const(CInt(Z.shift_left Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) else - Const(CInt(Cilint.zero_cilint, counter_ikind, None)) + Const(CInt(Z.zero, counter_ikind, None)) class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor From f18fe581d6d06e674106eaec9c6c26d136aa68eb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 13:51:31 +0100 Subject: [PATCH 505/628] Change - to _ in name of variable introduced in terminationPreprocessing. - is not a legal part of a variable. --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4e25f232e3..919de3e5d9 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -38,7 +38,7 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> - let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in + let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "_id" ^ (string_of_int !vcounter) in incr vcounter; let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in From aef46ce9c6ea20e5f50b9725abe92dd7f4a0d84e Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 14:39:08 +0100 Subject: [PATCH 506/628] Add LoopTermination and TerminationPreprocessing to goblint_lib --- src/goblint_lib.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index e1087f8fc9..e06f5fd245 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -124,6 +124,7 @@ module RelationPriv = RelationPriv module ThreadEscape = ThreadEscape module PthreadSignals = PthreadSignals module ExtractPthread = ExtractPthread +module LoopTermination = LoopTermination (** {2 Longjmp} @@ -338,6 +339,7 @@ module Tracing = Tracing module Preprocessor = Preprocessor module CompilationDatabase = CompilationDatabase module MakefileUtil = MakefileUtil +module TerminationPreprocessing = TerminationPreprocessing (** {2 Witnesses} From 72c14e208fab17f89fa325cb704317929bd8e739 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 15:33:12 +0100 Subject: [PATCH 507/628] Extract function find_loop, given a loop_counter. --- src/analyses/loopTermination.ml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 7cde0cb9c6..5fac2e9e1a 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -31,7 +31,7 @@ struct module D = Lattice.Unit module C = D - module V = struct + module V = struct include UnitV let is_write_only _ = true end @@ -40,6 +40,9 @@ struct let startstate _ = () let exitstate = startstate + let find_loop ~loop_counter = + VarToStmt.find loop_counter !loop_counters + (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -47,7 +50,7 @@ struct match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> (try - let loop_statement = VarToStmt.find x !loop_counters in + let loop_statement = find_loop ~loop_counter:x in let is_bounded = check_bounded ctx x in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) @@ -70,7 +73,7 @@ struct | None -> false) | Queries.MustTermAllLoops -> let multithreaded = ctx.ask Queries.IsEverMultiThreaded in - if multithreaded then ( + if multithreaded then ( M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n"; false) else From ddfcaea7430c74b08103b243f19ec07305a1d422 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 15:34:34 +0100 Subject: [PATCH 508/628] Rename x to loop_counter. --- src/analyses/loopTermination.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 5fac2e9e1a..10e0f5c5f4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -48,10 +48,10 @@ struct let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with - "__goblint_bounded", [Lval (Var x, NoOffset)] -> + "__goblint_bounded", [Lval (Var loop_counter, NoOffset)] -> (try - let loop_statement = find_loop ~loop_counter:x in - let is_bounded = check_bounded ctx x in + let loop_statement = find_loop ~loop_counter in + let is_bounded = check_bounded ctx loop_counter in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( From 72413249dd0cfb5c72d052d4f44110f20f4a2af3 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 16:34:17 +0100 Subject: [PATCH 509/628] Use increment_expression that takes the ikind of the counter variable into account. --- src/util/terminationPreprocessing.ml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 919de3e5d9..b6ffc12c14 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,6 +36,14 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + (* Yields increment expression e + 1 where the added "1" that has the same type as the expression [e]. + Using Cil.increm instead does not work for non-[IInt] ikinds. *) + let increment_expression e = + let et = typeOf e in + let bop = PlusA in + let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in + constFold false (BinOp(bop, e, one, et)) in + let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "_id" ^ (string_of_int !vcounter) in @@ -43,8 +51,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) From 76751d4947cc013c5c439e9b79b9733b9676fc19 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 17:59:28 +0100 Subject: [PATCH 510/628] Termination analysis: Insert only one increment statement, do not set assume no overflow. --- src/maingoblint.ml | 3 +-- src/util/terminationPreprocessing.ml | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index c44a6d9360..3d9959ba6c 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -164,8 +164,7 @@ let check_arguments () = if List.mem "termination" @@ get_string_list "ana.activated" then ( if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); - set_string "sem.int.signed_overflow" "assume_none"; - warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" + warn "termination analysis implicitly activates threadflag analysis." ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index b6ffc12c14..eb950b1dbb 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -52,14 +52,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- exit_stmt :: inc_stmt :: ss; - ); + b.bstmts <- exit_stmt :: inc_stmt :: b.bstmts; lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; From 5d5482726f5464605e59a5ac2263830a03358002 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 18:01:02 +0100 Subject: [PATCH 511/628] Set regresion tests to todo that are now imprecise. --- tests/regression/78-termination/03-nested-loop-terminating.c | 2 +- .../regression/78-termination/07-nested-for-loop-terminating.c | 2 +- .../regression/78-termination/25-leave-loop-goto-terminating.c | 2 +- .../78-termination/30-goto-out-of-inner-loop-terminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/78-termination/03-nested-loop-terminating.c b/tests/regression/78-termination/03-nested-loop-terminating.c index fd1ee14f39..6b31204567 100644 --- a/tests/regression/78-termination/03-nested-loop-terminating.c +++ b/tests/regression/78-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/07-nested-for-loop-terminating.c b/tests/regression/78-termination/07-nested-for-loop-terminating.c index f1dde17dc5..3293a1fa2c 100644 --- a/tests/regression/78-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/78-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/25-leave-loop-goto-terminating.c b/tests/regression/78-termination/25-leave-loop-goto-terminating.c index 61c8b8f58d..b882759bff 100644 --- a/tests/regression/78-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/78-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c index 999ee6d3fd..c07b558d07 100644 --- a/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From f81ca2c0346716ada6abfc51f09dbf9143dc34c1 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 23:15:40 +0100 Subject: [PATCH 512/628] Termination: Use unsigned long long for counter variables; reactivate assume no overflow when termination analysis is activated. --- lib/goblint/runtime/include/goblint.h | 2 +- lib/goblint/runtime/src/goblint.c | 4 ++-- src/maingoblint.ml | 3 ++- src/util/terminationPreprocessing.ml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/goblint/runtime/include/goblint.h b/lib/goblint/runtime/include/goblint.h index 3c1abae838..af87035d33 100644 --- a/lib/goblint/runtime/include/goblint.h +++ b/lib/goblint/runtime/include/goblint.h @@ -7,4 +7,4 @@ void __goblint_assume_join(/* pthread_t thread */); // undeclared argument to av void __goblint_split_begin(int exp); void __goblint_split_end(int exp); -void __goblint_bounded(int exp); \ No newline at end of file +void __goblint_bounded(unsigned long long exp); \ No newline at end of file diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index 7929fcf37a..cbcb7cf505 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -29,6 +29,6 @@ void __goblint_split_end(int exp) { } -void __goblint_bounded(int exp) { - +void __goblint_bounded(unsigned long long exp) { + } \ No newline at end of file diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 3d9959ba6c..82a19aa4ae 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -164,7 +164,8 @@ let check_arguments () = if List.mem "termination" @@ get_string_list "ana.activated" then ( if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); - warn "termination analysis implicitly activates threadflag analysis." + set_string "sem.int.signed_overflow" "assume_none"; + warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none"; ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index eb950b1dbb..9023a68f8a 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,7 +3,7 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let counter_ikind = IInt +let counter_ikind = IULongLong let counter_typ = TInt (counter_ikind, []) let min_int_exp = (* Currently only tested for IInt type, which is signed *) From 2728c2a56c87808e367b1b18841bed6a7e5744c3 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 14 Nov 2023 10:19:58 +0100 Subject: [PATCH 513/628] Termination: Update verdict to TODO for 78/35. Case can no longer be handled when no longer using signed integers and assuming no-overflow. --- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 0554a0bc25..4c738e1173 100644 --- a/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() From 8934a2133c009059738063f0851ed483f74d6276 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 14 Nov 2023 14:10:00 +0100 Subject: [PATCH 514/628] Autotuner: Activate termination analysis in autotuner. --- conf/svcomp23.json | 3 ++- src/autoTune.ml | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/conf/svcomp23.json b/conf/svcomp23.json index af584f1593..f46ae13e86 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -70,7 +70,8 @@ "congruence", "octagon", "wideningThresholds", - "loopUnrollHeuristic" + "loopUnrollHeuristic", + "termination" ] } }, diff --git a/src/autoTune.ml b/src/autoTune.ml index 51e4ea412e..672d71b7ba 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -243,7 +243,7 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | Termination -> + | Termination -> let terminationAnas = ["termination"; "threadflag"; "apron"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; @@ -466,6 +466,11 @@ let wideningOption factors file = print_endline "Enabled widening thresholds"; } +let activateTerminationAnalysis () = + enableAnalyses ["termination"; "apron"]; + set_string "sem.int.signed_overflow" "assume_none"; + set_string "ana.apron.domain" "polyhedra"; + set_bool "ana.int.interval_threshold_widening" true let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in @@ -495,6 +500,8 @@ let chooseFromOptions costTarget options = let isActivated a = get_bool "ana.autotune.enabled" && List.mem a @@ get_string_list "ana.autotune.activated" +let isTerminationTask () = List.mem Svcomp.Specification.Termination (Svcomp.Specification.of_option ()) + let chooseConfig file = let factors = collectFactors visitCilFileSameGlobals file in let fileCompplexity = estimateComplexity factors file in @@ -528,10 +535,14 @@ let chooseConfig file = let options = [] in let options = if isActivated "congruence" then (congruenceOption factors file)::options else options in - let options = if isActivated "octagon" then (apronOctagonOption factors file)::options else options in + + (* Termination analysis uses apron in a different configuration. *) + let options = if isActivated "octagon" && not (isTerminationTask ()) then (apronOctagonOption factors file)::options else options in let options = if isActivated "wideningThresholds" then (wideningOption factors file)::options else options in - List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options + List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options; + if isActivated "termination" && isTerminationTask () then + activateTerminationAnalysis () let reset_lazy () = ResettableLazy.reset functionCallMaps From d5662c5455290e166d5023724d843f0b3a92ef07 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 13:13:12 +0100 Subject: [PATCH 515/628] Indicate that termination analysis is activated. --- src/autoTune.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index 672d71b7ba..c1e982aace 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -467,6 +467,7 @@ let wideningOption factors file = } let activateTerminationAnalysis () = + print_endline "Enabling termination analysis"; enableAnalyses ["termination"; "apron"]; set_string "sem.int.signed_overflow" "assume_none"; set_string "ana.apron.domain" "polyhedra"; From 245b438a5c9e313d78391fae6be93579b8b4a5bb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:19:20 +0100 Subject: [PATCH 516/628] Change wording from enabling to enabled for consistency. --- src/autoTune.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index c1e982aace..645fcfcf84 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -467,11 +467,11 @@ let wideningOption factors file = } let activateTerminationAnalysis () = - print_endline "Enabling termination analysis"; enableAnalyses ["termination"; "apron"]; set_string "sem.int.signed_overflow" "assume_none"; set_string "ana.apron.domain" "polyhedra"; - set_bool "ana.int.interval_threshold_widening" true + set_bool "ana.int.interval_threshold_widening" true; + print_endline "Enabled termination analysis" let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in From cbe4ad0cb57f57b19e6f009c30c033cc9f5b0eb8 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:21:39 +0100 Subject: [PATCH 517/628] Add termination to autotune for svcomp.json, but remove it from svcomp23.json. --- conf/svcomp.json | 3 ++- conf/svcomp23.json | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 73f99500b9..107c59994c 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -71,7 +71,8 @@ "octagon", "wideningThresholds", "loopUnrollHeuristic", - "memsafetySpecification" + "memsafetySpecification", + "termination" ] } }, diff --git a/conf/svcomp23.json b/conf/svcomp23.json index f46ae13e86..af584f1593 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -70,8 +70,7 @@ "congruence", "octagon", "wideningThresholds", - "loopUnrollHeuristic", - "termination" + "loopUnrollHeuristic" ] } }, From a466650aa752cd83655dded84cd56c52e8b1d0a0 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:26:44 +0100 Subject: [PATCH 518/628] Move LoopTermination in Goblint_lib to analyses/other section. --- src/goblint_lib.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index e06f5fd245..cb18ad0dd7 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -124,7 +124,6 @@ module RelationPriv = RelationPriv module ThreadEscape = ThreadEscape module PthreadSignals = PthreadSignals module ExtractPthread = ExtractPthread -module LoopTermination = LoopTermination (** {2 Longjmp} @@ -149,6 +148,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse +module LoopTermination = LoopTermination module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace From b57b9e4589dccfba5810f841728355a4f72c205b Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:54:14 +0100 Subject: [PATCH 519/628] Extract some loops into functions; this reduces runtime of analysis. --- .../15-complex-loop-combination-terminating.c | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/tests/regression/78-termination/15-complex-loop-combination-terminating.c b/tests/regression/78-termination/15-complex-loop-combination-terminating.c index 1365611410..9b97d4051b 100644 --- a/tests/regression/78-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/78-termination/15-complex-loop-combination-terminating.c @@ -2,6 +2,49 @@ // Apron is not precise enough for some nested loops #include +int nested_while_loop_with_break(){ + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + return 0; +} + +int nested_loop_with_conditions(){ + // Loop with nested conditions + for (int v = 1; v <= 10; v++) + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } +} + int main() { // Non-nested loops @@ -67,44 +110,9 @@ int main() p++; } while (p <= 5); - // Additional loops - int m; - - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; - } - - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - } + // Additional nested loops + nested_while_loop_with_break(); + nested_loop_with_conditions(); return 0; } From 70ef2d293a647b8ddcd477789054e87e18eeff4f Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 18:11:08 +0100 Subject: [PATCH 520/628] RelationalAnalysis: Assert type-bounds also for signed types when no-overflow is assumed. --- src/analyses/apron/relationAnalysis.apron.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 13f549fc44..8ac55ca323 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -196,7 +196,7 @@ struct let assert_type_bounds ask rel x = assert (RD.Tracked.varinfo_tracked x); match Cilfacade.get_ikind x.vtype with - | ik when not (IntDomain.should_ignore_overflow ik) -> (* don't add type bounds for signed when assume_none *) + | ik -> (* don't add type bounds for signed when assume_none *) let (type_min, type_max) = IntDomain.Size.range ik in (* TODO: don't go through CIL exp? *) let e1 = BinOp (Le, Lval (Cil.var x), (Cil.kintegerCilint ik type_max), intType) in @@ -204,7 +204,6 @@ struct let rel = RD.assert_inv rel e1 false (no_overflow ask e1) in (* TODO: how can be overflow when asserting type bounds? *) let rel = RD.assert_inv rel e2 false (no_overflow ask e2) in rel - | _ | exception Invalid_argument _ -> rel From 6decbddb2503a7633c73b3151df40e158417ede8 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 15 Nov 2023 23:20:11 +0100 Subject: [PATCH 521/628] Improve the detection of reachable memory through global struct vars --- src/analyses/memLeak.ml | 89 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index fc015f458b..4d7e864c06 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -23,6 +23,14 @@ struct (* Filtering by GVar seems to account for declarations, as well as definitions of global vars *) List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + let get_global_struct_ptr_vars () = + List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + |> List.filter (fun v -> match v.vtype with TPtr (TComp _, _) | TPtr ((TNamed ({ttype = TComp _; _}, _)), _) -> true | _ -> false) + + let get_global_struct_non_ptr_vars () = + List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + |> List.filter (fun v -> match v.vtype with TComp (_, _) | (TNamed ({ttype = TComp _; _}, _)) -> true | _ -> false) + let get_reachable_mem_from_globals (global_vars:varinfo list) ctx = global_vars |> List.map (fun v -> Lval (Var v, NoOffset)) @@ -35,6 +43,81 @@ struct end | _ -> None) + let rec get_reachable_mem_from_str_ptr_globals (global_struct_ptr_vars:varinfo list) ctx = + let eval_value_of_heap_var heap_var = + match ctx.ask (Queries.EvalValue (Lval (Var heap_var, NoOffset))) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Struct s -> + List.fold_left (fun acc f -> + if isPointerType f.ftype then + begin match ValueDomain.Structs.get s f with + | Queries.VD.Address a -> + let reachable_from_addr_set = + List.fold_left (fun acc addr -> + match addr with + | Queries.AD.Addr.Addr (v, _) -> List.append acc (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) + | _ -> acc + ) [] (Queries.AD.elements a) + in List.append acc reachable_from_addr_set + | _ -> acc + end + else acc + ) [] (ValueDomain.Structs.keys s) + | _ -> [] + end + | _ -> [] + in + let get_pts_of_non_heap_ptr_var var = + match ctx.ask (Queries.MayPointTo (Lval (Var var, NoOffset))) with + | a when not (Queries.AD.is_top a) && Queries.AD.cardinal a = 1 -> + begin match List.hd @@ Queries.AD.elements a with + | Queries.AD.Addr.Addr (v, _) when (ctx.ask (Queries.IsHeapVar v)) && not (ctx.ask (Queries.IsMultiple v)) -> v :: (eval_value_of_heap_var v) + | Queries.AD.Addr.Addr (v, _) when not (ctx.ask (Queries.IsAllocVar v)) && isPointerType v.vtype -> get_reachable_mem_from_str_ptr_globals [v] ctx + | _ -> [] + end + | _ -> [] + in + global_struct_ptr_vars + |> List.fold_left (fun acc var -> + if ctx.ask (Queries.IsHeapVar var) then eval_value_of_heap_var var + else if not (ctx.ask (Queries.IsAllocVar var)) && isPointerType var.vtype then get_pts_of_non_heap_ptr_var var + else acc + ) [] + + let get_reachable_mem_from_str_non_ptr_globals (global_struct_non_ptr_vars:varinfo list) ctx = + global_struct_non_ptr_vars + (* Filter out global struct vars that don't have pointer fields *) + |> List.filter_map (fun v -> + match ctx.ask (Queries.EvalValue (Lval (Var v, NoOffset))) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Queries.VD.Struct s -> + let struct_fields = ValueDomain.Structs.keys s in + let ptr_struct_fields = List.filter (fun f -> isPointerType f.ftype) struct_fields in + if List.length ptr_struct_fields = 0 then None else Some (s, ptr_struct_fields) + | _ -> None + end + | _ -> None + ) + |> List.fold_left (fun acc_struct (s, fields) -> + let reachable_from_fields = + List.fold_left (fun acc_field field -> + match ValueDomain.Structs.get s field with + | Queries.VD.Address a -> + let reachable_from_addr_set = + List.fold_left (fun acc_addr addr -> + match addr with + | Queries.AD.Addr.Addr (v, _) -> List.append acc_addr (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) + | _ -> acc_addr + ) [] (Queries.AD.elements a) + in List.append acc_field reachable_from_addr_set + | _ -> acc_field + ) [] fields + in + List.append acc_struct reachable_from_fields + ) [] + let warn_for_multi_threaded ctx = if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( set_mem_safety_flag InvalidMemTrack; @@ -45,7 +128,11 @@ struct let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let allocated_mem = ctx.local in if not (D.is_empty allocated_mem) then - let reachable_mem = D.of_list (get_reachable_mem_from_globals (get_global_vars ()) ctx) in + let reachable_mem_from_non_struct_globals = D.of_list (get_reachable_mem_from_globals (get_global_vars ()) ctx) in + let reachable_mem_from_struct_ptr_globals = D.of_list (get_reachable_mem_from_str_ptr_globals (get_global_struct_ptr_vars ()) ctx) in + let reachable_mem_from_struct_non_ptr_globals = D.of_list (get_reachable_mem_from_str_non_ptr_globals (get_global_struct_non_ptr_vars ()) ctx) in + let reachable_mem_from_struct_globals = D.join reachable_mem_from_struct_ptr_globals reachable_mem_from_struct_non_ptr_globals in + let reachable_mem = D.join reachable_mem_from_non_struct_globals reachable_mem_from_struct_globals in (* Check and warn if there's unreachable allocated memory at program exit *) let allocated_and_unreachable_mem = D.diff allocated_mem reachable_mem in if not (D.is_empty allocated_and_unreachable_mem) then ( From c3804260bf8bc43ea90e76ea9f2cf0f7ebb7186f Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 15 Nov 2023 23:20:53 +0100 Subject: [PATCH 522/628] Add regr. tests for reachable memory through global struct vars --- .../13-global-nested-struct-ptr-reachable.c | 29 +++++++++++++++++++ ...4-global-nested-struct-non-ptr-reachable.c | 25 ++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/regression/76-memleak/13-global-nested-struct-ptr-reachable.c create mode 100644 tests/regression/76-memleak/14-global-nested-struct-non-ptr-reachable.c diff --git a/tests/regression/76-memleak/13-global-nested-struct-ptr-reachable.c b/tests/regression/76-memleak/13-global-nested-struct-ptr-reachable.c new file mode 100644 index 0000000000..1726625a59 --- /dev/null +++ b/tests/regression/76-memleak/13-global-nested-struct-ptr-reachable.c @@ -0,0 +1,29 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +typedef struct st { + int *a; + int b; +} st; + +typedef struct st2 { + st *st_ptr; +} st2; + +st2 *st_var; + +int main(int argc, char const *argv[]) { + st_var = malloc(sizeof(st2)); + st_var->st_ptr = malloc(sizeof(st)); + int *local_ptr = malloc(sizeof(int)); + st_var->st_ptr->a = local_ptr; + local_ptr = NULL; + + free(st_var->st_ptr); + free(st_var); + + // local_ptr's memory is reachable through st_var->st_ptr->a + // It's leaked, because we don't call free() on it + // Hence, there should be a single warning for a memory leak, but not for unreachable memory + return 0; //WARN +} diff --git a/tests/regression/76-memleak/14-global-nested-struct-non-ptr-reachable.c b/tests/regression/76-memleak/14-global-nested-struct-non-ptr-reachable.c new file mode 100644 index 0000000000..1153bd81e0 --- /dev/null +++ b/tests/regression/76-memleak/14-global-nested-struct-non-ptr-reachable.c @@ -0,0 +1,25 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include + +typedef struct st { + int *a; + int b; +} st; + +typedef struct st2 { + st *st_ptr; +} st2; + +st2 st_var; + +int main(int argc, char const *argv[]) { + st_var.st_ptr = malloc(sizeof(st)); + int *local_ptr = malloc(sizeof(int)); + st_var.st_ptr->a = local_ptr; + local_ptr = NULL; + free(st_var.st_ptr); + + // local_ptr's memory is reachable through st_var.st_ptr->a, but it's not freed + // Hence, there should be only a single warning for a memory leak, but not for unreachable memory + return 0; //WARN +} From 845910410bbda2f9964ccd727d63a6e7b811ac7f Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Wed, 15 Nov 2023 23:33:58 +0100 Subject: [PATCH 523/628] Fix semgrep warning for using `List.length` for an emptiness check --- src/analyses/memLeak.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index a5d357d9c8..51a5a2ff75 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -96,7 +96,7 @@ struct | Queries.VD.Struct s -> let struct_fields = ValueDomain.Structs.keys s in let ptr_struct_fields = List.filter (fun f -> isPointerType f.ftype) struct_fields in - if List.length ptr_struct_fields = 0 then None else Some (s, ptr_struct_fields) + if ptr_struct_fields = [] then None else Some (s, ptr_struct_fields) | _ -> None end | _ -> None From f209afdae5be755eeded7bb0080473fe15571b7d Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 16 Nov 2023 07:52:56 +0100 Subject: [PATCH 524/628] First attempt to improve precision for multi-threaded valid-memcleanup --- src/analyses/memLeak.ml | 72 +++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 9c09c05cf6..c64bb95697 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -6,30 +6,50 @@ open MessageCategory open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) - +module WasMallocCalled = BoolDomain.MustBool module Spec : Analyses.MCPSpec = struct include Analyses.IdentitySpec let name () = "memLeak" - module D = ToppedVarInfoSet + (* module D = ToppedVarInfoSet *) + module D = Lattice.Prod(ToppedVarInfoSet)(WasMallocCalled) module C = D module P = IdentityP (D) + module G = ToppedVarInfoSet + module V = + struct + include ThreadIdDomain.Thread + include StdV + end let context _ d = d (* HELPER FUNCTIONS *) - let warn_for_multi_threaded ctx = - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( + let warn_for_multi_threaded_due_to_abort ctx = + let state = ctx.local in + if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) && snd state then ( set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program aborted while running in multi-threaded mode. A memory leak might occur" + ) + + (* If [is_return] is set to [true], then a thread return occurred, else a thread join *) + let warn_for_thread_return_or_exit current_thread ctx is_return = + let global_state = ctx.global current_thread in + if not (G.is_empty global_state) then ( + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s" (if is_return then "return" else "join") ) + (* if not (ToppedVarInfoSet.is_empty (fst state)) && snd state then ( + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s" (if is_return then "return" else "join") + ) *) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in - if not @@ D.is_empty state then + if not (ToppedVarInfoSet.is_empty (fst state)) then match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; @@ -42,6 +62,12 @@ struct (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = + (* Check for a valid-memcleanup violation in a multi-threaded setting *) + if (ctx.ask (Queries.MayBeThreadReturn)) then ( + match ctx.ask (Queries.CurrentThreadId) with + | `Lifted tid -> warn_for_thread_return_or_exit tid ctx true + | _ -> () + ); (* Returning from "main" is one possible program exit => need to check for memory leaks *) if f.svar.vname = "main" then check_for_mem_leak ctx; ctx.local @@ -53,25 +79,39 @@ struct | Malloc _ | Calloc _ | Realloc _ -> - (* Warn about multi-threaded programs as soon as we encounter a dynamic memory allocation function *) - warn_for_multi_threaded ctx; begin match ctx.ask (Queries.AllocVar {on_stack = false}) with - | `Lifted var -> D.add var state - | _ -> state + | `Lifted var -> + begin match ctx.ask (Queries.CurrentThreadId) with + | `Lifted tid -> + let current_globals = ctx.global tid in + let globals_to_side_effect = G.add var current_globals in + ctx.sideg tid globals_to_side_effect; + | _ -> () + end; + (ToppedVarInfoSet.add var (fst state), true) + | _ -> (fst state, true) end | Free ptr -> begin match ctx.ask (Queries.MayPointTo ptr) with | ad when not (Queries.AD.is_top ad) && Queries.AD.cardinal ad = 1 -> (* Note: Need to always set "ana.malloc.unique_address_count" to a value > 0 *) begin match Queries.AD.choose ad with - | Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> D.remove v state (* Unique pointed to heap vars *) + | Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> + begin match ctx.ask (Queries.CurrentThreadId) with + | `Lifted tid -> + let current_globals = ctx.global tid in + let globals_to_side_effect = G.remove v current_globals in + ctx.sideg tid globals_to_side_effect + | _ -> () + end; + (ToppedVarInfoSet.remove v (fst state), snd state) (* Unique pointed to heap vars *) | _ -> state end | _ -> state end | Abort -> - (* An "Abort" special function indicates program exit => need to check for memory leaks *) - check_for_mem_leak ctx; + (* Upon a call to the "Abort" special function, we give up and conservatively warn *) + warn_for_multi_threaded_due_to_abort ctx; state | Assert { exp; _ } -> let warn_for_assert_exp = @@ -89,6 +129,12 @@ struct in warn_for_assert_exp; state + | ThreadExit _ -> + begin match ctx.ask (Queries.CurrentThreadId) with + | `Lifted tid -> warn_for_thread_return_or_exit tid ctx false + | _ -> () + end; + state | _ -> state let startstate v = D.bot () From c0fe89e93352f530317cf1a7836684de65b216f3 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Thu, 16 Nov 2023 07:53:21 +0100 Subject: [PATCH 525/628] Add regr. test cases for multi-threaded valid-memcleanup --- .../08-invalid-memcleanup-multi-threaded.c | 33 +++++++++++++++++++ ...-invalid-memcleanup-multi-threaded-abort.c | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c create mode 100644 tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c diff --git a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c new file mode 100644 index 0000000000..50b17fa65d --- /dev/null +++ b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c @@ -0,0 +1,33 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include +#include + +int *g; +int *m1; +int *m2; + +void *f1(void *arg) { + m1 = malloc(sizeof(int)); + // Thread t1 leaks m1 here + pthread_exit(NULL); //WARN +} + +void *f2(void *arg) { + m2 = malloc(sizeof(int)); + free(m2); // No leak for thread t2, since it calls free before exiting + pthread_exit(NULL); //NOWARN +} + +int main(int argc, char const *argv[]) { + g = malloc(sizeof(int)); + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + free(g); + + // main thread is not leaking anything + return 0; //NOWARN +} diff --git a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c new file mode 100644 index 0000000000..9aef45198e --- /dev/null +++ b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c @@ -0,0 +1,33 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include +#include + +int *g; +int *m1; +int *m2; + +void *f1(void *arg) { + m1 = malloc(sizeof(int)); + // Thread t1 leaks m1 here + exit(2); //WARN +} + +void *f2(void *arg) { + m2 = malloc(sizeof(int)); + free(m2); // No leak for thread t2, since it calls free before exiting + pthread_exit(NULL); //NOWARN +} + +int main(int argc, char const *argv[]) { + g = malloc(sizeof(int)); + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + free(g); + + // main thread is not leaking anything + return 0; //NOWARN +} From 9420a089fcc1134f289d61f5eb8e45571ca47d23 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:13:29 +0100 Subject: [PATCH 526/628] add sqrt handling in float domain --- src/analyses/base.ml | 1 + src/analyses/libraryDesc.ml | 4 +++- src/analyses/libraryFunctions.ml | 6 +++--- src/cdomains/floatDomain.ml | 14 ++++++++++++++ src/cdomains/floatDomain.mli | 3 +++ src/cdomains/floatOps/floatOps.ml | 3 +++ src/cdomains/floatOps/floatOps.mli | 1 + src/cdomains/floatOps/stubs.c | 14 ++++++++++++++ 8 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index a8ad9af95b..86951ab4a5 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2356,6 +2356,7 @@ struct | Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y)) | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) + | Sqrt (fk, x) -> Float (apply_unary fk FD.sqrt x) end in begin match lv with diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 72a4261cb5..5403612fae 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -38,7 +38,8 @@ type math = | Atan2 of (CilType.Fkind.t * Basetype.CilExp.t * Basetype.CilExp.t) | Cos of (CilType.Fkind.t * Basetype.CilExp.t) | Sin of (CilType.Fkind.t * Basetype.CilExp.t) - | Tan of (CilType.Fkind.t * Basetype.CilExp.t) [@@deriving eq, ord, hash] + | Tan of (CilType.Fkind.t * Basetype.CilExp.t) + | Sqrt of (CilType.Fkind.t * Basetype.CilExp.t) [@@deriving eq, ord, hash] (** Type of special function, or {!Unknown}. *) (* Use inline record if not single {!Cil.exp} argument. *) @@ -170,6 +171,7 @@ module MathPrintable = struct | Cos (fk, exp) -> Pretty.dprintf "(%a )cos(%a)" d_fkind fk d_exp exp | Sin (fk, exp) -> Pretty.dprintf "(%a )sin(%a)" d_fkind fk d_exp exp | Tan (fk, exp) -> Pretty.dprintf "(%a )tan(%a)" d_fkind fk d_exp exp + | Sqrt (fk, exp) -> Pretty.dprintf "(%a )sqrt(%a)" d_fkind fk d_exp exp include Printable.SimplePretty ( struct diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 117dcbd236..8f8a43cb29 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -944,9 +944,9 @@ let math_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("scalbln", unknown [drop "arg" []; drop "exp" []]); ("scalblnf", unknown [drop "arg" []; drop "exp" []]); ("scalblnl", unknown [drop "arg" []; drop "exp" []]); - ("sqrt", unknown [drop "x" []]); - ("sqrtf", unknown [drop "x" []]); - ("sqrtl", unknown [drop "x" []]); + ("sqrt", special [__ "x" []] @@ fun x -> Math { fun_args = (Sqrt (FDouble, x)) }); + ("sqrtf", special [__ "x" []] @@ fun x -> Math { fun_args = (Sqrt (FFloat, x)) }); + ("sqrtl", special [__ "x" []] @@ fun x -> Math { fun_args = (Sqrt (FLongDouble, x)) }); ("tgamma", unknown [drop "x" []]); ("tgammaf", unknown [drop "x" []]); ("tgammal", unknown [drop "x" []]); diff --git a/src/cdomains/floatDomain.ml b/src/cdomains/floatDomain.ml index f52c849111..39d3744401 100644 --- a/src/cdomains/floatDomain.ml +++ b/src/cdomains/floatDomain.ml @@ -40,6 +40,8 @@ module type FloatArith = sig (** sin(x) *) val tan : t -> t (** tan(x) *) + val sqrt : t -> t + (** sqrt(x) *) (** {inversions of unary functions}*) val inv_ceil : ?asPreciseAsConcrete:bool -> t -> t @@ -670,6 +672,14 @@ module FloatIntervalImpl(Float_t : CFloatType) = struct | (l, h) when l = h && l = Float_t.zero -> of_const 0. (*tan(0) = 0*) | _ -> top () (**could be exact for intervals where l=h, or even for some intervals *) + let eval_sqrt = function + | (l, h) when l = Float_t.zero && h = Float_t.zero -> of_const 0. + | (l, h) when l >= Float_t.zero -> + let low = Float_t.sqrt Down l in + let high = Float_t.sqrt Up h in + Interval (low, high) + | _ -> top () + let eval_inv_ceil ?(asPreciseAsConcrete=false) = function | (l, h) -> if (Float_t.sub Up (Float_t.ceil l) (Float_t.sub Down (Float_t.ceil l) (Float_t.of_float Nearest 1.0)) = (Float_t.of_float Nearest 1.0)) then ( @@ -784,6 +794,7 @@ module FloatIntervalImpl(Float_t : CFloatType) = struct let cos = eval_unop eval_cos let sin = eval_unop eval_sin let tan = eval_unop eval_tan + let sqrt = eval_unop eval_sqrt let inv_ceil ?(asPreciseAsConcrete=false) = eval_unop ~warn:false (eval_inv_ceil ~asPreciseAsConcrete:asPreciseAsConcrete) let inv_floor ?(asPreciseAsConcrete=false) = eval_unop ~warn:false (eval_inv_floor ~asPreciseAsConcrete:asPreciseAsConcrete) @@ -899,6 +910,7 @@ module FloatIntervalImplLifted = struct let cos = lift (F1.cos, F2.cos) let sin = lift (F1.sin, F2.sin) let tan = lift (F1.tan, F2.tan) + let sqrt = lift (F1.sqrt, F2.sqrt) let inv_ceil ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) = function | F32 a -> F32 (F1.inv_ceil ~asPreciseAsConcrete:true a) @@ -1159,6 +1171,8 @@ module FloatDomTupleImpl = struct map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.sin); } let tan = map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.tan); } + let sqrt = + map { f1= (fun (type a) (module F : FloatDomain with type t = a) -> F.sqrt); } (*"asPreciseAsConcrete" has no meaning here*) let inv_ceil ?(asPreciseAsConcrete=BoolDomain.MustBool.top ()) = diff --git a/src/cdomains/floatDomain.mli b/src/cdomains/floatDomain.mli index 06bca69aca..d958e1ee81 100644 --- a/src/cdomains/floatDomain.mli +++ b/src/cdomains/floatDomain.mli @@ -57,6 +57,9 @@ module type FloatArith = sig val tan : t -> t (** tan(x) *) + val sqrt : t -> t + (** sqrt(x) *) + (** {inversions of unary functions}*) val inv_ceil : ?asPreciseAsConcrete:bool -> t -> t (** (inv_ceil z -> x) if (z = ceil(x)) *) diff --git a/src/cdomains/floatOps/floatOps.ml b/src/cdomains/floatOps/floatOps.ml index a951ec08fe..a4e39d930e 100644 --- a/src/cdomains/floatOps/floatOps.ml +++ b/src/cdomains/floatOps/floatOps.ml @@ -35,6 +35,7 @@ module type CFloatType = sig val sub: round_mode -> t -> t -> t val mul: round_mode -> t -> t -> t val div: round_mode -> t -> t -> t + val sqrt: round_mode -> t -> t val atof: round_mode -> string -> t end @@ -74,6 +75,7 @@ module CDouble = struct external sub: round_mode -> t -> t -> t = "sub_double" external mul: round_mode -> t -> t -> t = "mul_double" external div: round_mode -> t -> t -> t = "div_double" + external sqrt: round_mode -> t -> t = "sqrt_double" external atof: round_mode -> string -> t = "atof_double" end @@ -107,6 +109,7 @@ module CFloat = struct external sub: round_mode -> t -> t -> t = "sub_float" external mul: round_mode -> t -> t -> t = "mul_float" external div: round_mode -> t -> t -> t = "div_float" + external sqrt: round_mode -> t -> t = "sqrt_float" external atof: round_mode -> string -> t = "atof_float" diff --git a/src/cdomains/floatOps/floatOps.mli b/src/cdomains/floatOps/floatOps.mli index 05bf363872..cf24f75ed5 100644 --- a/src/cdomains/floatOps/floatOps.mli +++ b/src/cdomains/floatOps/floatOps.mli @@ -38,6 +38,7 @@ module type CFloatType = sig val sub: round_mode -> t -> t -> t val mul: round_mode -> t -> t -> t val div: round_mode -> t -> t -> t + val sqrt: round_mode -> t -> t val atof: round_mode -> string -> t end diff --git a/src/cdomains/floatOps/stubs.c b/src/cdomains/floatOps/stubs.c index e0485883dd..50e4a2fb31 100644 --- a/src/cdomains/floatOps/stubs.c +++ b/src/cdomains/floatOps/stubs.c @@ -36,6 +36,20 @@ static void change_round_mode(int mode) } } +#define UNARY_OP(name, type, op) \ + CAMLprim value name##_##type(value mode, value x) \ + { \ + int old_roundingmode = fegetround(); \ + change_round_mode(Int_val(mode)); \ + volatile type r, x1 = Double_val(x); \ + r = op(x1); \ + fesetround(old_roundingmode); \ + return caml_copy_double(r); \ + } + +UNARY_OP(sqrt, double, sqrt); +UNARY_OP(sqrt, float, sqrtf); + #define BINARY_OP(name, type, op) \ CAMLprim value name##_##type(value mode, value x, value y) \ { \ From 8141869487223039bddcfce8e9215632a9db60bb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:44:58 +0100 Subject: [PATCH 527/628] Termination distribute loops into multiple functions to make analysis terminate faster. --- .../09-complex-for-loop-terminating.c | 15 ++- .../10-complex-loop-terminating.c | 98 ++++++++++++++++- .../15-complex-loop-combination-terminating.c | 100 ++++++++++-------- 3 files changed, 163 insertions(+), 50 deletions(-) diff --git a/tests/regression/78-termination/09-complex-for-loop-terminating.c b/tests/regression/78-termination/09-complex-for-loop-terminating.c index fb2acaf569..74ee41eae8 100644 --- a/tests/regression/78-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/78-termination/09-complex-for-loop-terminating.c @@ -2,8 +2,7 @@ // Apron is not precise enough for some nested loops #include -int main() -{ +int loops0(){ int i, j, k; // Outer loop @@ -33,6 +32,11 @@ int main() } printf("\n"); } + return 0; +} + +int loops1(){ + int i, j, k; // Loop with conditions for (i = 1; i <= 10; i++) @@ -82,6 +86,13 @@ int main() { printf("%d %d %d\n", a, b, c); } + return 0; +} + +int main() +{ + loops0(); + loops1(); return 0; } diff --git a/tests/regression/78-termination/10-complex-loop-terminating.c b/tests/regression/78-termination/10-complex-loop-terminating.c index 738fe78683..96253c445f 100644 --- a/tests/regression/78-termination/10-complex-loop-terminating.c +++ b/tests/regression/78-termination/10-complex-loop-terminating.c @@ -2,7 +2,87 @@ // Apron is not precise enough for some nested loops #include -int main() +int loops0(){ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) + { + // Inner while loop 1 + while (j <= i) + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) + { + j = i; + while (j >= 1) + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + return 0; +} + +int loops1() { int i = 1; int j = 1; @@ -61,6 +141,14 @@ int main() i++; } + return 0; +} + +int loops2(){ + int i = 1; + int j = 1; + int k = 5; + // Loop with nested conditions i = 1; while (i <= 10) @@ -119,6 +207,12 @@ int main() b += 2; c += 3; } - return 0; } + +int main(){ + loops0(); + loops1(); + loops2(); + return 0; +} \ No newline at end of file diff --git a/tests/regression/78-termination/15-complex-loop-combination-terminating.c b/tests/regression/78-termination/15-complex-loop-combination-terminating.c index 9b97d4051b..4912bbb1f2 100644 --- a/tests/regression/78-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/78-termination/15-complex-loop-combination-terminating.c @@ -2,51 +2,7 @@ // Apron is not precise enough for some nested loops #include -int nested_while_loop_with_break(){ - int m; - - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; - } - return 0; -} - -int nested_loop_with_conditions(){ - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - } -} - -int main() -{ +int non_nested_loops(){ // Non-nested loops int i; @@ -71,8 +27,11 @@ int main() printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); + return 0; +} - // Nested loops +int nested_loops(){ + // Nested loops int a, b; // Nested for and while loop @@ -109,7 +68,56 @@ int main() } p++; } while (p <= 5); + return 0; +} + +int nested_while_loop_with_break(){ + int m; + // Nested while loop with a break statement + int n = 1; + while (n <= 5) + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + return 0; +} + +int nested_loop_with_conditions(){ + // Loop with nested conditions + for (int v = 1; v <= 10; v++) + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } +} + +int main() +{ + non_nested_loops(); + nested_loops(); // Additional nested loops nested_while_loop_with_break(); nested_loop_with_conditions(); From 1ef011c6b675d78b25f4928cbbac64b07edee740 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:48:19 +0100 Subject: [PATCH 528/628] Add test case that did not work when not asserting the type bounds for signed types when sem.int.signed_overflow was set to assume_none. --- .../78-termination/50-decreasing-signed-int.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/regression/78-termination/50-decreasing-signed-int.c diff --git a/tests/regression/78-termination/50-decreasing-signed-int.c b/tests/regression/78-termination/50-decreasing-signed-int.c new file mode 100644 index 0000000000..01daa5ee21 --- /dev/null +++ b/tests/regression/78-termination/50-decreasing-signed-int.c @@ -0,0 +1,13 @@ +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon +int main() +{ + int x; + + if(x <= 0){ + return 0; + } + while (x > 0) { + x = x - 1; + } + return 0; +} From d9f39105b35e4c65ac01b457cdb19ab82ac17c87 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:49:31 +0100 Subject: [PATCH 529/628] Remove outdated comment. --- src/analyses/apron/relationAnalysis.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 8ac55ca323..8b128eb271 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -196,7 +196,7 @@ struct let assert_type_bounds ask rel x = assert (RD.Tracked.varinfo_tracked x); match Cilfacade.get_ikind x.vtype with - | ik -> (* don't add type bounds for signed when assume_none *) + | ik -> let (type_min, type_max) = IntDomain.Size.range ik in (* TODO: don't go through CIL exp? *) let e1 = BinOp (Le, Lval (Cil.var x), (Cil.kintegerCilint ik type_max), intType) in From 92023855b6872e71c8893d8e56b243032eefab01 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 11:03:58 +0200 Subject: [PATCH 530/628] Add unsound 09-regsion/41-per-thread-array-init-race --- .../41-per-thread-array-init-race.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/regression/09-regions/41-per-thread-array-init-race.c diff --git a/tests/regression/09-regions/41-per-thread-array-init-race.c b/tests/regression/09-regions/41-per-thread-array-init-race.c new file mode 100644 index 0000000000..f6d267495e --- /dev/null +++ b/tests/regression/09-regions/41-per-thread-array-init-race.c @@ -0,0 +1,40 @@ +// PARAM: --set ana.activated[+] region --enable ana.sv-comp.functions +// Per-thread array pointers passed via argument but initialized before thread create. +// Extracted from silver searcher. +#include +#include +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort();} +} +extern int __VERIFIER_nondet_int(); + +void *thread(void *arg) { + int *p = arg; + int i = *p; // RACE! + return NULL; +} + +int main() { + int threads_total = __VERIFIER_nondet_int(); + assume_abort_if_not(threads_total >= 0); + + pthread_t *tids = malloc(threads_total * sizeof(pthread_t)); + int *is = calloc(threads_total, sizeof(int)); + + // create threads + for (int i = 0; i < threads_total; i++) { + pthread_create(&tids[i], NULL, &thread, &is[i]); // may fail but doesn't matter + is[i] = i; // RACE! + } + + // join threads + for (int i = 0; i < threads_total; i++) { + pthread_join(tids[i], NULL); + } + + free(tids); + free(is); + + return 0; +} From 0740491dcc290a8e41e693f0b8534af9540ebb37 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Thu, 16 Nov 2023 20:09:24 +0100 Subject: [PATCH 531/628] implement abs function for integers --- src/analyses/base.ml | 18 ++++++++++++++++++ src/analyses/libraryDesc.ml | 2 ++ src/analyses/libraryFunctions.ml | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 86951ab4a5..bca3cb6588 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2328,6 +2328,23 @@ struct | _ -> failwith ("non-floating-point argument in call to function "^f.vname) end in + let apply_abs ik x = + let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in + begin match eval_x with + | Int int_x -> + let xcast = ID.cast_to ik int_x in + (* TODO cover case where x is the MIN value -> undefined *) + (match ID.le xcast (ID.of_int ik Z.zero) with + | d when d = ID.of_int ik Z.zero -> xcast (* x positive *) + | d when d = ID.of_int ik Z.one -> ID.neg xcast (* x negative *) + | _ -> (* both possible *) + let x1 = ID.neg (ID.meet (ID.ending ik Z.zero) xcast) in + let x2 = ID.meet (ID.starting ik Z.zero) xcast in + ID.join x1 x2 + ) + | _ -> failwith ("non-integer argument in call to function "^f.vname) + end + in let result:value = begin match fun_args with | Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk) @@ -2357,6 +2374,7 @@ struct | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) | Sqrt (fk, x) -> Float (apply_unary fk FD.sqrt x) + | Abs x -> Int (ID.cast_to IInt (apply_abs IInt x)) end in begin match lv with diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 5403612fae..8cd3dfa1ba 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -27,6 +27,7 @@ type math = | Islessequal of (Basetype.CilExp.t * Basetype.CilExp.t) | Islessgreater of (Basetype.CilExp.t * Basetype.CilExp.t) | Isunordered of (Basetype.CilExp.t * Basetype.CilExp.t) + | Abs of Basetype.CilExp.t | Ceil of (CilType.Fkind.t * Basetype.CilExp.t) | Floor of (CilType.Fkind.t * Basetype.CilExp.t) | Fabs of (CilType.Fkind.t * Basetype.CilExp.t) @@ -159,6 +160,7 @@ module MathPrintable = struct | Islessequal (exp1, exp2) -> Pretty.dprintf "isLessEqual(%a, %a)" d_exp exp1 d_exp exp2 | Islessgreater (exp1, exp2) -> Pretty.dprintf "isLessGreater(%a, %a)" d_exp exp1 d_exp exp2 | Isunordered (exp1, exp2) -> Pretty.dprintf "isUnordered(%a, %a)" d_exp exp1 d_exp exp2 + | Abs exp -> Pretty.dprintf "abs(%a)" d_exp exp | Ceil (fk, exp) -> Pretty.dprintf "(%a )ceil(%a)" d_fkind fk d_exp exp | Floor (fk, exp) -> Pretty.dprintf "(%a )floor(%a)" d_fkind fk d_exp exp | Fabs (fk, exp) -> Pretty.dprintf "(%a )fabs(%a)" d_fkind fk d_exp exp diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 8f8a43cb29..ae33f57f70 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -130,7 +130,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("wcstombs", unknown ~attrs:[ThreadUnsafe] [drop "dst" [w]; drop "src" [r]; drop "size" []]); ("wcsrtombs", unknown ~attrs:[ThreadUnsafe] [drop "dst" [w]; drop "src" [r_deep; w]; drop "size" []; drop "ps" [r_deep; w_deep]]); ("mbstowcs", unknown [drop "dest" [w]; drop "src" [r]; drop "n" []]); - ("abs", unknown [drop "j" []]); + ("abs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs j) }); ("localtime_r", unknown [drop "timep" [r]; drop "result" [w]]); ("strpbrk", unknown [drop "s" [r]; drop "accept" [r]]); ("_setjmp", special [__ "env" [w]] @@ fun env -> Setjmp { env }); (* only has one underscore *) From 73bf6fee56c6f4fe0114b677efa80369ee80654c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 12:07:43 +0200 Subject: [PATCH 532/628] Fix region bullet escaping (issue #107) --- src/analyses/region.ml | 10 +++++++- src/cdomains/regionDomain.ml | 23 +++++++++++++++++-- .../regression/09-regions/38-escape_malloc.c | 4 ++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/analyses/region.ml b/src/analyses/region.ml index 652526543c..5b10586aba 100644 --- a/src/analyses/region.ml +++ b/src/analyses/region.ml @@ -177,7 +177,15 @@ struct let threadenter ctx ~multiple lval f args = [`Lifted (RegMap.bot ())] - let threadspawn ctx ~multiple lval f args fctx = ctx.local + let threadspawn ctx ~multiple lval f args fctx = + match ctx.local with + | `Lifted reg -> + let old_regpart = ctx.global () in + let regpart, reg = List.fold_right Reg.assign_escape args (old_regpart, reg) in + if not (RegPart.leq regpart old_regpart) then + ctx.sideg () regpart; + `Lifted reg + | x -> x let exitstate v = `Lifted (RegMap.bot ()) diff --git a/src/cdomains/regionDomain.ml b/src/cdomains/regionDomain.ml index b577e3499f..681eb79007 100644 --- a/src/cdomains/regionDomain.ml +++ b/src/cdomains/regionDomain.ml @@ -157,13 +157,13 @@ struct (* This is the main logic for dealing with the bullet and finding it an * owner... *) - let add_set (s:set) llist (p,m:t): t = + let add_set ?(escape=false) (s:set) llist (p,m:t): t = if RS.has_bullet s then let f key value (ys, x) = if RS.has_bullet value then key::ys, RS.join value x else ys,x in let ys,x = RegMap.fold f m (llist, RS.remove_bullet s) in let x = RS.remove_bullet x in - if RS.is_empty x then + if not escape && RS.is_empty x then p, RegMap.add_list_set llist RS.single_bullet m else RegPart.add x p, RegMap.add_list_set ys x m @@ -215,6 +215,25 @@ struct | Some (_,x,_) -> p, RegMap.add x RS.single_bullet m | _ -> p,m + (* Copied & modified from assign. *) + let assign_escape (rval: exp) (st: t): t = + (* let _ = printf "%a = %a\n" (printLval plainCilPrinter) lval (printExp plainCilPrinter) rval in *) + let t = Cilfacade.typeOf rval in + if isPointerType t then begin (* TODO: this currently allows function pointers, e.g. in iowarrior, but should it? *) + match eval_exp rval with + (* TODO: should offs_x matter? *) + | Some (deref_y,y,offs_y) -> + let (p,m) = st in begin + match is_global y with + | true -> + add_set ~escape:true (RS.single_vf y) [] st + | false -> + add_set ~escape:true (RegMap.find y m) [y] st + end + | _ -> st + end else + st + let related_globals (deref_vfd: eval_t) (p,m: t): elt list = let add_o o2 (v,o) = (v, F.add_offset o o2) in match deref_vfd with diff --git a/tests/regression/09-regions/38-escape_malloc.c b/tests/regression/09-regions/38-escape_malloc.c index 9f5b44531e..c849d5bbe3 100644 --- a/tests/regression/09-regions/38-escape_malloc.c +++ b/tests/regression/09-regions/38-escape_malloc.c @@ -9,7 +9,7 @@ pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; void *t_fun(void *arg) { int *p = (int *) arg; pthread_mutex_lock(&mutex1); - (*p)++; // TODO RACE! + (*p)++; // RACE! pthread_mutex_unlock(&mutex1); return NULL; } @@ -20,7 +20,7 @@ int main(void) { // TODO: q escapes as region owner pthread_create(&id, NULL, t_fun, (void *) q); pthread_mutex_lock(&mutex2); - (*q)++; // TODO RACE! + (*q)++; // RACE! pthread_mutex_unlock(&mutex2); pthread_join (id, NULL); return 0; From b9ede51e83b64db87b6a2e0322d3c348c114c07c Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Fri, 17 Nov 2023 11:11:14 +0100 Subject: [PATCH 533/628] implement special case for most-negative value --- src/analyses/base.ml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index bca3cb6588..f25f0a9693 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2333,14 +2333,19 @@ struct begin match eval_x with | Int int_x -> let xcast = ID.cast_to ik int_x in - (* TODO cover case where x is the MIN value -> undefined *) - (match ID.le xcast (ID.of_int ik Z.zero) with - | d when d = ID.of_int ik Z.zero -> xcast (* x positive *) - | d when d = ID.of_int ik Z.one -> ID.neg xcast (* x negative *) - | _ -> (* both possible *) - let x1 = ID.neg (ID.meet (ID.ending ik Z.zero) xcast) in - let x2 = ID.meet (ID.starting ik Z.zero) xcast in - ID.join x1 x2 + (* the absolute value of the most-negative value is out of range for 2'complement types *) + (match (ID.minimal xcast), (ID.minimal (ID.top_of ik)) with + | _, None + | None, _ -> ID.top_of ik + | Some mx, Some mm when Z.equal mx mm -> ID.top_of ik + | _, _ -> + match ID.le xcast (ID.of_int ik Z.zero) with + | d when d = ID.of_int ik Z.zero -> xcast (* x positive *) + | d when d = ID.of_int ik Z.one -> ID.neg xcast (* x negative *) + | _ -> (* both possible *) + let x1 = ID.neg (ID.meet (ID.ending ik Z.zero) xcast) in + let x2 = ID.meet (ID.starting ik Z.zero) xcast in + ID.join x1 x2 ) | _ -> failwith ("non-integer argument in call to function "^f.vname) end From 6f549915ebd3c319422e36acab66eb90c614eea5 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 12:57:05 +0200 Subject: [PATCH 534/628] Fix YAML witness invariants for unrolled loops (closes #1225) --- src/witness/yamlWitness.ml | 96 +++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 9e8ebeff51..dc4890753d 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -145,6 +145,16 @@ struct module FCMap = BatHashtbl.Make (Printable.Prod (CilType.Fundec) (Spec.C)) type con_inv = {node: Node.t; context: Spec.C.t; invariant: Invariant.t; state: Spec.D.t} + (* TODO: fix location hack *) + module LH = BatHashtbl.Make (CilType.Location) + let location2nodes: Node.t list LH.t Lazy.t = lazy ( + let lh = LH.create 113 in + NH.iter (fun n _ -> + LH.modify_def [] (Node.location n) (List.cons n) lh + ) (Lazy.force nh); + lh + ) + let write () = let input_files = GobConfig.get_string_list "files" in let data_model = match GobConfig.get_string "exp.architecture" with @@ -208,26 +218,32 @@ struct (* Generate location invariants (without precondition) *) let entries = if entry_type_enabled YamlWitnessType.LocationInvariant.entry_type then ( - NH.fold (fun n local acc -> - let loc = Node.location n in - if is_invariant_node n then ( - let lvals = local_lvals n local in - match R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals}) with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Node.find_fundec n).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = Entry.invariant (CilType.Exp.show inv) in - let entry = Entry.location_invariant ~task ~location ~invariant in - entry :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) - acc - ) - else + LH.fold (fun loc ns acc -> + let fundec = ref None in + let inv = List.fold_left (fun acc n -> + if is_invariant_node n then ( + fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) + let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in + let lvals = local_lvals n local in + Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) + ) + else + acc + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = Entry.invariant (CilType.Exp.show inv) in + let entry = Entry.location_invariant ~task ~location ~invariant in + entry :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) acc - ) (Lazy.force nh) entries + ) (Lazy.force location2nodes) entries ) else entries @@ -236,25 +252,31 @@ struct (* Generate loop invariants (without precondition) *) let entries = if entry_type_enabled YamlWitnessType.LoopInvariant.entry_type then ( - NH.fold (fun n local acc -> - let loc = Node.location n in - if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( - match R.ask_local_node n ~local (Invariant Invariant.default_context) with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Node.find_fundec n).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = Entry.invariant (CilType.Exp.show inv) in - let entry = Entry.loop_invariant ~task ~location ~invariant in - entry :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) - acc - ) - else + LH.fold (fun loc ns acc -> + let fundec = ref None in + let inv = List.fold_left (fun acc n -> + if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( + fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) + let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in + Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) + ) + else + acc + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = Entry.invariant (CilType.Exp.show inv) in + let entry = Entry.loop_invariant ~task ~location ~invariant in + entry :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) acc - ) (Lazy.force nh) entries + ) (Lazy.force location2nodes) entries ) else entries From 952b90dbfcfd2c8ef4750abf4daca6cd5da6d8bd Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 13:19:09 +0200 Subject: [PATCH 535/628] Fix bisect_ppx build --- src/witness/yamlWitness.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 023212fa42..22800c07dc 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -251,7 +251,7 @@ struct fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in - Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) + Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) else acc @@ -284,7 +284,7 @@ struct if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in - Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) + Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) else acc @@ -448,7 +448,7 @@ struct fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in - Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) + Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) else acc @@ -481,7 +481,7 @@ struct if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in - Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) + Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) else acc From 4ae355695675d2030b00c5df991666b8952d6357 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 15:11:36 +0200 Subject: [PATCH 536/628] Fix missing unrolled iterations in YAML witness invariants Unrolled loop heads are different nodes, which aren't actually loop heads. For sound invariants, they must also be included if at a location if at least one is. --- src/witness/yamlWitness.ml | 152 ++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 22800c07dc..1f83c8625e 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -245,29 +245,29 @@ struct let entries = if entry_type_enabled YamlWitnessType.LocationInvariant.entry_type then ( LH.fold (fun loc ns acc -> - let fundec = ref None in - let inv = List.fold_left (fun acc n -> - if is_invariant_node n then ( + if List.exists is_invariant_node ns then ( + let fundec = ref None in + let inv = List.fold_left (fun acc n -> fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) - ) - else - acc - ) (Invariant.bot ()) ns - in - match inv with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = Entry.invariant (CilType.Exp.show inv) in - let entry = Entry.location_invariant ~task ~location ~invariant in - entry :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = Entry.invariant (CilType.Exp.show inv) in + let entry = Entry.location_invariant ~task ~location ~invariant in + entry :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else acc ) (Lazy.force location2nodes) entries ) @@ -279,28 +279,28 @@ struct let entries = if entry_type_enabled YamlWitnessType.LoopInvariant.entry_type then ( LH.fold (fun loc ns acc -> - let fundec = ref None in - let inv = List.fold_left (fun acc n -> - if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( + if WitnessInvariant.emit_loop_head && List.exists (WitnessUtil.NH.mem WitnessInvariant.loop_heads) ns then ( + let fundec = ref None in + let inv = List.fold_left (fun acc n -> fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) - ) - else - acc - ) (Invariant.bot ()) ns - in - match inv with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = Entry.invariant (CilType.Exp.show inv) in - let entry = Entry.loop_invariant ~task ~location ~invariant in - entry :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = Entry.invariant (CilType.Exp.show inv) in + let entry = Entry.loop_invariant ~task ~location ~invariant in + entry :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else acc ) (Lazy.force location2nodes) entries ) @@ -442,29 +442,29 @@ struct let invariants = if invariant_type_enabled YamlWitnessType.InvariantSet.LocationInvariant.invariant_type then ( LH.fold (fun loc ns acc -> - let fundec = ref None in - let inv = List.fold_left (fun acc n -> - if is_invariant_node n then ( + if List.exists is_invariant_node ns then ( + let fundec = ref None in + let inv = List.fold_left (fun acc n -> fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) - ) - else - acc - ) (Invariant.bot ()) ns - in - match inv with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = CilType.Exp.show inv in - let invariant = Entry.location_invariant' ~location ~invariant in - invariant :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = CilType.Exp.show inv in + let invariant = Entry.location_invariant' ~location ~invariant in + invariant :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else acc ) (Lazy.force location2nodes) invariants ) @@ -476,28 +476,28 @@ struct let invariants = if invariant_type_enabled YamlWitnessType.InvariantSet.LoopInvariant.invariant_type then ( LH.fold (fun loc ns acc -> - let fundec = ref None in - let inv = List.fold_left (fun acc n -> - if WitnessInvariant.emit_loop_head && WitnessUtil.NH.mem WitnessInvariant.loop_heads n then ( + if WitnessInvariant.emit_loop_head && List.exists (WitnessUtil.NH.mem WitnessInvariant.loop_heads) ns then ( + let fundec = ref None in + let inv = List.fold_left (fun acc n -> fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) - ) - else - acc - ) (Invariant.bot ()) ns - in - match inv with - | `Lifted inv -> - let invs = WitnessUtil.InvariantExp.process_exp inv in - List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in - let invariant = CilType.Exp.show inv in - let invariant = Entry.loop_invariant' ~location ~invariant in - invariant :: acc - ) acc invs - | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + ) (Invariant.bot ()) ns + in + match inv with + | `Lifted inv -> + let invs = WitnessUtil.InvariantExp.process_exp inv in + List.fold_left (fun acc inv -> + let location_function = (Option.get !fundec).svar.vname in + let location = Entry.location ~location:loc ~location_function in + let invariant = CilType.Exp.show inv in + let invariant = Entry.loop_invariant' ~location ~invariant in + invariant :: acc + ) acc invs + | `Bot | `Top -> (* TODO: 0 for bot (dead code)? *) + acc + ) + else acc ) (Lazy.force location2nodes) invariants ) From 0fb479f506c99e1e415c08d157ae09a8a768fa4c Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 15:16:48 +0200 Subject: [PATCH 537/628] Refactor YAML witness fundec lookup --- src/witness/yamlWitness.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 1f83c8625e..1f106c936e 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -246,9 +246,7 @@ struct if entry_type_enabled YamlWitnessType.LocationInvariant.entry_type then ( LH.fold (fun loc ns acc -> if List.exists is_invariant_node ns then ( - let fundec = ref None in let inv = List.fold_left (fun acc n -> - fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) @@ -256,10 +254,11 @@ struct in match inv with | `Lifted inv -> + let fundec = Node.find_fundec (List.hd ns) in (* TODO: fix location hack *) + let location_function = fundec.svar.vname in + let location = Entry.location ~location:loc ~location_function in let invs = WitnessUtil.InvariantExp.process_exp inv in List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in let invariant = Entry.invariant (CilType.Exp.show inv) in let entry = Entry.location_invariant ~task ~location ~invariant in entry :: acc @@ -280,19 +279,18 @@ struct if entry_type_enabled YamlWitnessType.LoopInvariant.entry_type then ( LH.fold (fun loc ns acc -> if WitnessInvariant.emit_loop_head && List.exists (WitnessUtil.NH.mem WitnessInvariant.loop_heads) ns then ( - let fundec = ref None in let inv = List.fold_left (fun acc n -> - fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) (Invariant.bot ()) ns in match inv with | `Lifted inv -> + let fundec = Node.find_fundec (List.hd ns) in (* TODO: fix location hack *) + let location_function = fundec.svar.vname in + let location = Entry.location ~location:loc ~location_function in let invs = WitnessUtil.InvariantExp.process_exp inv in List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in let invariant = Entry.invariant (CilType.Exp.show inv) in let entry = Entry.loop_invariant ~task ~location ~invariant in entry :: acc @@ -443,9 +441,7 @@ struct if invariant_type_enabled YamlWitnessType.InvariantSet.LocationInvariant.invariant_type then ( LH.fold (fun loc ns acc -> if List.exists is_invariant_node ns then ( - let fundec = ref None in let inv = List.fold_left (fun acc n -> - fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) @@ -453,10 +449,11 @@ struct in match inv with | `Lifted inv -> + let fundec = Node.find_fundec (List.hd ns) in (* TODO: fix location hack *) + let location_function = fundec.svar.vname in + let location = Entry.location ~location:loc ~location_function in let invs = WitnessUtil.InvariantExp.process_exp inv in List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in let invariant = CilType.Exp.show inv in let invariant = Entry.location_invariant' ~location ~invariant in invariant :: acc @@ -477,19 +474,18 @@ struct if invariant_type_enabled YamlWitnessType.InvariantSet.LoopInvariant.invariant_type then ( LH.fold (fun loc ns acc -> if WitnessInvariant.emit_loop_head && List.exists (WitnessUtil.NH.mem WitnessInvariant.loop_heads) ns then ( - let fundec = ref None in let inv = List.fold_left (fun acc n -> - fundec := Some (Node.find_fundec n); (* TODO: fix location hack *) let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in Invariant.(acc || R.ask_local_node n ~local (Invariant Invariant.default_context)) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) ) (Invariant.bot ()) ns in match inv with | `Lifted inv -> + let fundec = Node.find_fundec (List.hd ns) in (* TODO: fix location hack *) + let location_function = fundec.svar.vname in + let location = Entry.location ~location:loc ~location_function in let invs = WitnessUtil.InvariantExp.process_exp inv in List.fold_left (fun acc inv -> - let location_function = (Option.get !fundec).svar.vname in - let location = Entry.location ~location:loc ~location_function in let invariant = CilType.Exp.show inv in let invariant = Entry.loop_invariant' ~location ~invariant in invariant :: acc From 3c89ece9f7630beda3a057b1705a28ea0496dc65 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 15:32:41 +0200 Subject: [PATCH 538/628] Fix YamlWitness indentation --- src/witness/yamlWitness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index 1f106c936e..ee370f2b6a 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -445,7 +445,7 @@ struct let local = try NH.find (Lazy.force nh) n with Not_found -> Spec.D.bot () in let lvals = local_lvals n local in Invariant.(acc || R.ask_local_node n ~local (Invariant {Invariant.default_context with lvals})) [@coverage off] (* bisect_ppx cannot handle redefined (||) *) - ) (Invariant.bot ()) ns + ) (Invariant.bot ()) ns in match inv with | `Lifted inv -> From 9966b873a5d07f5a2c094245312a914ba2130c9d Mon Sep 17 00:00:00 2001 From: oliver Date: Fri, 17 Nov 2023 14:49:33 +0100 Subject: [PATCH 539/628] update dune-project and documentation --- docs/developer-guide/debugging.md | 5 +++-- dune-project | 4 +++- goblint.opam.locked | 12 ++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/developer-guide/debugging.md b/docs/developer-guide/debugging.md index 7875a9b01e..5c1db12227 100644 --- a/docs/developer-guide/debugging.md +++ b/docs/developer-guide/debugging.md @@ -85,7 +85,7 @@ The configuration file has to be named `launch.json` and must reside in the `./. "configurations": [ { "name": "Goblint", - "type": "ocamlearlybird", + "type": "ocaml.earlybird", "request": "launch", "program": "${workspaceFolder}/goblint.byte", "arguments": [ @@ -97,7 +97,8 @@ The configuration file has to be named `launch.json` and must reside in the `./. ] } ``` -Note that the individual arguments to Goblint should be passed here as separate strings that do not contain spaces. +Note that the individual arguments to Goblint should be passed here as separate strings that do not contain spaces. Finally, to enable breakpoints uncomment `(map_workspace_root false)` in the dune-project file. + ### Running Goblint in the VS Code Debugger diff --git a/dune-project b/dune-project index 4a9cd8e3c1..05c7d9418c 100644 --- a/dune-project +++ b/dune-project @@ -1,4 +1,4 @@ -(lang dune 3.6) +(lang dune 3.7) (using dune_site 0.1) (cram enable) (name goblint) @@ -64,3 +64,5 @@ (share lib) (share conf)) ) + +; (map_workspace_root false) ;uncomment to enable breakpoints diff --git a/goblint.opam.locked b/goblint.opam.locked index 2744d2fe92..0abe989955 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -50,12 +50,12 @@ depends: [ "cpu" {= "2.0.0"} "csexp" {= "1.5.1"} "ctypes" {= "0.20.1"} - "dune" {= "3.6.1"} - "dune-build-info" {= "3.6.1"} - "dune-configurator" {= "3.6.1"} - "dune-private-libs" {= "3.6.1"} - "dune-site" {= "3.6.1"} - "dyn" {= "3.6.1"} + "dune" {= "3.7.1"} + "dune-build-info" {= "3.7.1"} + "dune-configurator" {= "3.7.1"} + "dune-private-libs" {= "3.7.1"} + "dune-site" {= "3.7.1"} + "dyn" {= "3.7.1"} "fileutils" {= "0.6.4"} "fmt" {= "0.9.0"} "fpath" {= "0.7.3"} From b57e80d2f4a82102af284c6c6f3a26eba35d24b5 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 15:54:27 +0200 Subject: [PATCH 540/628] Bump YAML entry size for large unrolled invariants --- src/witness/yamlWitness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index ee370f2b6a..c80611c83f 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -148,7 +148,7 @@ let yaml_entries_to_file ?(invariants=0) yaml_entries file = (* Yaml_unix.to_file_exn file yaml *) (* to_file/to_string uses a fixed-size buffer... *) (* estimate how big it should be + extra in case empty *) - let text = match Yaml.to_string ~len:((List.length yaml_entries + invariants) * 4096 + 2048) yaml with + let text = match Yaml.to_string ~len:((List.length yaml_entries + invariants) * 8192 + 2048) yaml with | Ok text -> text | Error (`Msg m) -> failwith ("Yaml.to_string: " ^ m) in From f70948296572a81d36f734522c1441db3fec19bb Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 17 Nov 2023 16:07:37 +0200 Subject: [PATCH 541/628] Make YAML output buffer sizing exponential --- src/util/std/gobYaml.ml | 11 +++++++++++ src/witness/yamlWitness.ml | 13 ++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/util/std/gobYaml.ml b/src/util/std/gobYaml.ml index a4f3e597aa..131daaaebb 100644 --- a/src/util/std/gobYaml.ml +++ b/src/util/std/gobYaml.ml @@ -1,3 +1,14 @@ +let to_string' ?(len=65535 * 4) ?encoding ?scalar_style ?layout_style v = + assert (len >= 1); + let rec aux len = + match Yaml.to_string ~len ?encoding ?scalar_style ?layout_style v with + | Ok _ as o -> o + | Error (`Msg ("scalar failed" | "doc_end failed")) when len < Sys.max_string_length / 2 -> + aux (len * 2) + | Error (`Msg _) as e -> e + in + aux len + include Yaml.Util include GobResult.Syntax diff --git a/src/witness/yamlWitness.ml b/src/witness/yamlWitness.ml index c80611c83f..635ba4ad72 100644 --- a/src/witness/yamlWitness.ml +++ b/src/witness/yamlWitness.ml @@ -143,12 +143,11 @@ struct } end -let yaml_entries_to_file ?(invariants=0) yaml_entries file = +let yaml_entries_to_file yaml_entries file = let yaml = `A yaml_entries in (* Yaml_unix.to_file_exn file yaml *) (* to_file/to_string uses a fixed-size buffer... *) - (* estimate how big it should be + extra in case empty *) - let text = match Yaml.to_string ~len:((List.length yaml_entries + invariants) * 8192 + 2048) yaml with + let text = match GobYaml.to_string' yaml with | Ok text -> text | Error (`Msg m) -> failwith ("Yaml.to_string: " ^ m) in @@ -432,7 +431,7 @@ struct in (* Generate invariant set *) - let (entries, invariants) = + let entries = if entry_type_enabled YamlWitnessType.InvariantSet.entry_type then ( let invariants = [] in @@ -503,10 +502,10 @@ struct let invariants = List.rev invariants in let entry = Entry.invariant_set ~task ~invariants in - (entry :: entries, List.length invariants) + entry :: entries ) else - (entries, 0) + entries in let yaml_entries = List.rev_map YamlWitnessType.Entry.to_yaml entries in (* reverse to make entries in file in the same order as generation messages *) @@ -515,7 +514,7 @@ struct (Pretty.dprintf "total generation entries: %d" (List.length yaml_entries), None); ]; - yaml_entries_to_file ~invariants yaml_entries (Fpath.v (GobConfig.get_string "witness.yaml.path")) + yaml_entries_to_file yaml_entries (Fpath.v (GobConfig.get_string "witness.yaml.path")) let write () = Timing.wrap "yaml witness" write () From 26d8012e63f2c161a21146ce6e22480d1e4e930b Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 15:18:32 +0100 Subject: [PATCH 542/628] Autotuner: Remove activateTerminationAnalysis, as there is already other code for it. --- src/autoTune.ml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 645fcfcf84..cc1af59940 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -466,13 +466,6 @@ let wideningOption factors file = print_endline "Enabled widening thresholds"; } -let activateTerminationAnalysis () = - enableAnalyses ["termination"; "apron"]; - set_string "sem.int.signed_overflow" "assume_none"; - set_string "ana.apron.domain" "polyhedra"; - set_bool "ana.int.interval_threshold_widening" true; - print_endline "Enabled termination analysis" - let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in let operationEstimate = factors.instructions + (factors.expressions / 60) in @@ -536,14 +529,10 @@ let chooseConfig file = let options = [] in let options = if isActivated "congruence" then (congruenceOption factors file)::options else options in - (* Termination analysis uses apron in a different configuration. *) let options = if isActivated "octagon" && not (isTerminationTask ()) then (apronOctagonOption factors file)::options else options in let options = if isActivated "wideningThresholds" then (wideningOption factors file)::options else options in - List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options; - - if isActivated "termination" && isTerminationTask () then - activateTerminationAnalysis () + List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options let reset_lazy () = ResettableLazy.reset functionCallMaps From c8c49a56b60cc90de5f3a0fbed97ed2de8832db1 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 17 Nov 2023 15:35:41 +0100 Subject: [PATCH 543/628] Be more precise for `<<` of Intervals --- src/cdomains/intDomain.ml | 20 +++++++++++++++- .../39-signed-overflows/06-shiftleft.c | 23 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/regression/39-signed-overflows/06-shiftleft.c diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 3bc84ae676..49065b9cc5 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -610,6 +610,11 @@ module IntervalArith(Ints_t : IntOps.IntOps) = struct let x2y2 = (Ints_t.mul x2 y2) in (min4 x1y1 x1y2 x2y1 x2y2, max4 x1y1 x1y2 x2y1 x2y2) + let shiftleft (x1,x2) (y1,y2) = + let y1p = Ints_t.shift_left Ints_t.one y1 in + let y2p = Ints_t.shift_left Ints_t.one y2 in + mul (x1, x2) (y1p, y2p) + let div (x1, x2) (y1, y2) = let x1y1n = (Ints_t.div x1 y1) in let x1y2n = (Ints_t.div x1 y2) in @@ -851,7 +856,6 @@ struct let bitnot = bit1 (fun _ik -> Ints_t.bitnot) let shift_right = bitcomp (fun _ik x y -> Ints_t.shift_right x (Ints_t.to_int y)) - let shift_left = bitcomp (fun _ik x y -> Ints_t.shift_left x (Ints_t.to_int y)) let neg ?no_ov ik = function None -> (None,{underflow=false; overflow=false}) | Some x -> norm ik @@ Some (IArith.neg x) @@ -864,6 +868,20 @@ struct let mul ?no_ov = binary_op_with_norm IArith.mul let sub ?no_ov = binary_op_with_norm IArith.sub + let shift_left ik a b = + match is_bot a, is_bot b with + | true, true -> (bot_of ik,{underflow=false; overflow=false}) + | true, _ + | _ , true -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (show a) (show b))) + | _ -> + match a, maximal b, minimal b with + | Some a, Some bl, Some bu when (Ints_t.compare bl Ints_t.zero >= 0) -> + (try + let r = IArith.shiftleft a (Ints_t.to_int bl, Ints_t.to_int bu) in + norm ik @@ Some r + with Z.Overflow -> (top_of ik,{underflow=false; overflow=true})) + | _ -> (top_of ik,{underflow=true; overflow=true}) + let rem ik x y = match x, y with | None, None -> None | None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (show x) (show y))) diff --git a/tests/regression/39-signed-overflows/06-shiftleft.c b/tests/regression/39-signed-overflows/06-shiftleft.c new file mode 100644 index 0000000000..987775c6f7 --- /dev/null +++ b/tests/regression/39-signed-overflows/06-shiftleft.c @@ -0,0 +1,23 @@ +// PARAM: --enable ana.int.interval +#include +int main() +{ + int r; + int zero_or_one = 0; + int top; + char c; + r = c << 1U; //NOWARN + + r = c << 128U; //WARN + r = r << 1U; //WARN + r = 8 << -2; //WARN + + if(top) { zero_or_one = 1; } + + r = 8 << zero_or_one; + + __goblint_check(r >= 8); + __goblint_check(r <= 16); + + return 0; +} From 566348216fff4b119559d907df9b8e2e005fa023 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:14:36 +0100 Subject: [PATCH 544/628] improve values of parameters in abs call --- src/analyses/baseInvariant.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 72e00efbb1..73a41bcea1 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -726,6 +726,8 @@ struct | `Lifted (Isless (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st | `Lifted (Islessequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Le, xFloat, yFloat, (typeOf xFloat))) st | `Lifted (Islessgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (LOr, (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))), (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))), (TInt (IBool, [])))) st + | `Lifted (Abs xInt) -> + inv_exp (Int (ID.of_bool ik tv)) (BinOp (LAnd, (BinOp (Le, xInt, Lval x, TInt (IInt,[]))), (BinOp (Le, (UnOp (Neg, Lval x, (typeOf xInt))), xInt, TInt (IInt,[]))), (TInt (IInt, [])))) st | _ -> update_lval c x c' ID.pretty end | None -> update_lval c x c' ID.pretty From 28dca49ca7256db0af6415df2dfcf7345f502ef0 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 17:46:03 +0100 Subject: [PATCH 545/628] Add specification to activated settings for autotuner. --- conf/svcomp.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 107c59994c..cc6d1e303a 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -72,7 +72,8 @@ "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", - "termination" + "termination", + "specification" ] } }, From a4adabd819b4e116a220976223efba85296fb833 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 17:52:31 +0100 Subject: [PATCH 546/628] Call Autotune.focusOnSpecification before preprocessing, as terminatino analysis needs to be activated before preprocessing to work. --- src/autoTune.ml | 7 +++++-- src/goblint.ml | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index cc1af59940..4b959749a7 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -496,6 +496,9 @@ let isActivated a = get_bool "ana.autotune.enabled" && List.mem a @@ get_string_ let isTerminationTask () = List.mem Svcomp.Specification.Termination (Svcomp.Specification.of_option ()) +let specificationIsActivated () = + isActivated "specification" && get_string "ana.specification" <> "" + let chooseConfig file = let factors = collectFactors visitCilFileSameGlobals file in let fileCompplexity = estimateComplexity factors file in @@ -515,8 +518,8 @@ let chooseConfig file = if isActivated "mallocWrappers" then findMallocWrappers (); - if isActivated "specification" && get_string "ana.specification" <> "" then - focusOnSpecification (); + (* if specificationIsActivated () then + focusOnSpecification (); *) if isActivated "enums" && hasEnums file then set_bool "ana.int.enums" true; diff --git a/src/goblint.ml b/src/goblint.ml index 4ea3a3d242..6c5a2df33d 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -38,6 +38,8 @@ let main () = print_endline (GobUnix.localtime ()); print_endline GobSys.command_line; ); + (* When analyzing a termination specification, activate the termination analysis before pre-processing. *) + if get_bool "ana.autotune.enabled" && AutoTune.specificationIsActivated () then AutoTune.focusOnSpecification (); let file = lazy (Fun.protect ~finally:GoblintDir.finalize preprocess_parse_merge) in if get_bool "server.enabled" then ( let file = From 41ee060fc81f1719b7834f53cf6213c85df358ef Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 18:37:45 +0100 Subject: [PATCH 547/628] Do loop unrolling for loops with boundedness check. --- src/util/loopUnrolling.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/loopUnrolling.ml b/src/util/loopUnrolling.ml index 4ce8fc06b4..e1a8ad542b 100644 --- a/src/util/loopUnrolling.ml +++ b/src/util/loopUnrolling.ml @@ -320,6 +320,7 @@ class loopUnrollingCallVisitor = object | Unlock _ | ThreadCreate _ | Assert _ + | Bounded _ | ThreadJoin _ -> raise Found; | _ -> From 688cff1c28936295f3c084dd5d60f36e70dbd5a1 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Sat, 18 Nov 2023 11:26:38 +0100 Subject: [PATCH 548/628] trying to fix that value is not improved for parameter of abs call --- src/analyses/baseInvariant.ml | 71 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 73a41bcea1..b82ab88806 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -562,7 +562,7 @@ struct | TFloat (fk, _) -> fk | _ -> failwith "value which was expected to be a float is of different type?!" in - let rec inv_exp c_typed exp (st:D.t): D.t = + let rec inv_exp ?(query_special=true) c_typed exp (st:D.t) : D.t = (* trying to improve variables in an expression so it is bottom means dead code *) if VD.is_bot_value c_typed then contra st else @@ -578,12 +578,12 @@ struct | Some false -> ID.of_bool ikind false | _ -> ID.top_of ikind in - inv_exp (Int c') e st - | UnOp (Neg, e, _), Float c -> inv_exp (Float (unop_FD Neg c)) e st - | UnOp ((BNot|Neg) as op, e, _), Int c -> inv_exp (Int (unop_ID op c)) e st + inv_exp ~query_special (Int c') e st + | UnOp (Neg, e, _), Float c -> inv_exp ~query_special (Float (unop_FD Neg c)) e st + | UnOp ((BNot|Neg) as op, e, _), Int c -> inv_exp ~query_special (Int (unop_ID op c)) e st (* no equivalent for Float, as VD.is_safe_cast fails for all float types anyways *) | BinOp((Eq | Ne) as op, CastE (t1, e1), CastE (t2, e2), t), Int c when typeSig (Cilfacade.typeOf e1) = typeSig (Cilfacade.typeOf e2) && VD.is_safe_cast t1 (Cilfacade.typeOf e1) && VD.is_safe_cast t2 (Cilfacade.typeOf e2) -> - inv_exp (Int c) (BinOp (op, e1, e2, t)) st + inv_exp ~query_special (Int c) (BinOp (op, e1, e2, t)) st | BinOp (LOr, arg1, arg2, typ) as exp, Int c -> (* copied & modified from eval_rv_base... *) let (let*) = Option.bind in @@ -631,7 +631,7 @@ struct in let definite_ad = to_definite_ad vs in let c' = VD.Address definite_ad in - Some (inv_exp c' e st) + Some (inv_exp ~query_special c' e st) | Int i -> let ik = ID.ikind i in let module BISet = IntDomain.BISet in @@ -648,20 +648,20 @@ struct in let int_id = to_int_id vs in let c' = VD.Int int_id in - Some (inv_exp c' e st) + Some (inv_exp ~query_special c' e st) | _ -> None in begin match eqs_st with | Some st -> st | None when ID.to_bool c = Some true -> - begin match inv_exp (Int c) arg1 st with + begin match inv_exp ~query_special (Int c) arg1 st with | st1 -> - begin match inv_exp (Int c) arg2 st with + begin match inv_exp ~query_special (Int c) arg2 st with | st2 -> D.join st1 st2 | exception Analyses.Deadcode -> st1 end - | exception Analyses.Deadcode -> inv_exp (Int c) arg2 st (* Deadcode falls through *) + | exception Analyses.Deadcode -> inv_exp ~query_special (Int c) arg2 st (* Deadcode falls through *) end | None -> st (* TODO: not bothering to fall back, no other case can refine LOr anyway *) @@ -676,15 +676,15 @@ struct let ikres = Cilfacade.get_ikind_exp e in (* might be different from argument types, e.g. for LT, GT, EQ, ... *) let a', b' = inv_bin_int (a, b) ikind (c_int ikres) op in if M.tracing then M.tracel "inv" "binop: %a, c: %a, a': %a, b': %a\n" d_exp e ID.pretty (c_int ikind) ID.pretty a' ID.pretty b'; - let st' = inv_exp (Int a') e1 st in - let st'' = inv_exp (Int b') e2 st' in + let st' = inv_exp ~query_special (Int a') e1 st in + let st'' = inv_exp ~query_special (Int b') e2 st' in st'' | Float a, Float b -> let fkind = Cilfacade.get_fkind_exp e1 in (* both operands have the same type *) let a', b' = inv_bin_float (a, b) (c_float fkind) op in if M.tracing then M.tracel "inv" "binop: %a, c: %a, a': %a, b': %a\n" d_exp e FD.pretty (c_float fkind) FD.pretty a' FD.pretty b'; - let st' = inv_exp (Float a') e1 st in - let st'' = inv_exp (Float b') e2 st' in + let st' = inv_exp ~query_special (Float a') e1 st in + let st'' = inv_exp ~query_special (Float b') e2 st' in st'' (* Mixed Float and Int cases should never happen, as there are no binary operators with one float and one int parameter ?!*) | Int _, Float _ | Float _, Int _ -> failwith "ill-typed program"; @@ -712,22 +712,22 @@ struct begin match t with | TInt (ik, _) -> begin match x with - | ((Var v), offs) -> + | ((Var v), offs) when query_special -> if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs))); let tv_opt = ID.to_bool c in begin match tv_opt with | Some tv -> begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with - | `Lifted (Isfinite xFloat) when tv -> inv_exp (Float (FD.finite (unroll_fk_of_exp xFloat))) xFloat st - | `Lifted (Isnan xFloat) when tv -> inv_exp (Float (FD.nan_of (unroll_fk_of_exp xFloat))) xFloat st + | `Lifted (Isfinite xFloat) when tv -> inv_exp ~query_special:false (Float (FD.finite (unroll_fk_of_exp xFloat))) xFloat st + | `Lifted (Isnan xFloat) when tv -> inv_exp ~query_special:false (Float (FD.nan_of (unroll_fk_of_exp xFloat))) xFloat st (* should be correct according to C99 standard*) - | `Lifted (Isgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Isgreaterequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Ge, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Isless (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Islessequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Le, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Islessgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (LOr, (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))), (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))), (TInt (IBool, [])))) st + | `Lifted (Isgreater (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Isgreaterequal (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Ge, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Isless (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Islessequal (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Le, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Islessgreater (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (LOr, (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))), (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))), (TInt (IBool, [])))) st | `Lifted (Abs xInt) -> - inv_exp (Int (ID.of_bool ik tv)) (BinOp (LAnd, (BinOp (Le, xInt, Lval x, TInt (IInt,[]))), (BinOp (Le, (UnOp (Neg, Lval x, (typeOf xInt))), xInt, TInt (IInt,[]))), (TInt (IInt, [])))) st + inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (LAnd, (BinOp (Le, xInt, Lval x, TInt (IInt,[]))), (BinOp (Le, (UnOp (Neg, Lval x, (typeOf xInt))), xInt, TInt (IInt,[]))), (TInt (IInt, [])))) st | _ -> update_lval c x c' ID.pretty end | None -> update_lval c x c' ID.pretty @@ -749,17 +749,17 @@ struct begin match t with | TFloat (fk, _) -> begin match x with - | ((Var v), offs) -> + | ((Var v), offs) when query_special -> if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs))); begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with - | `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st - | `Lifted (Floor (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st + | `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp ~query_special:false (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st + | `Lifted (Floor (ret_fk, xFloat)) -> inv_exp ~query_special:false (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st | `Lifted (Fabs (ret_fk, xFloat)) -> let inv = FD.inv_fabs (FD.cast_to ret_fk c) in if FD.is_bot inv then raise Analyses.Deadcode else - inv_exp (Float inv) xFloat st + inv_exp ~query_special:false (Float inv) xFloat st | _ -> update_lval c x c' FD.pretty end | _ -> update_lval c x c' FD.pretty @@ -779,7 +779,7 @@ struct | TFloat (FLongDouble as fk, _), FDouble | TFloat (fk, _), FLongDouble | TFloat (FDouble as fk, _), FDouble - | TFloat (FFloat as fk, _), FFloat -> inv_exp (Float (FD.cast_to fk c)) e st + | TFloat (FFloat as fk, _), FFloat -> inv_exp ~query_special (Float (FD.cast_to fk c)) e st | _ -> fallback ("CastE: incompatible types") st) | CastE ((TInt (ik, _)) as t, e), Int c | CastE ((TEnum ({ekind = ik; _ }, _)) as t, e), Int c -> (* Can only meet the t part of an Lval in e with c (unless we meet with all overflow possibilities)! Since there is no good way to do this, we only continue if e has no values outside of t. *) @@ -792,7 +792,20 @@ struct (* let c' = ID.cast_to ik_e c in *) let c' = ID.cast_to ik_e (ID.meet c (ID.cast_to ik (ID.top_of ik_e))) in (* TODO: cast without overflow, is this right for normal invariant? *) if M.tracing then M.tracel "inv" "cast: %a from %a to %a: i = %a; cast c = %a to %a = %a\n" d_exp e d_ikind ik_e d_ikind ik ID.pretty i ID.pretty c d_ikind ik_e ID.pretty c'; - inv_exp (Int c') e st + inv_exp ~query_special (Int c') e st + | x -> fallback (GobPretty.sprintf "CastE: e did evaluate to Int, but the type did not match %a" CilType.Typ.pretty t) st + else + fallback (GobPretty.sprintf "CastE: %a evaluates to %a which is bigger than the type it is cast to which is %a" d_plainexp e ID.pretty i CilType.Typ.pretty t) st + | Float i -> + let i = FD.to_int ik i in + if ID.leq i (ID.cast_to ik i) then + match unrollType (Cilfacade.typeOf e) with + | TInt(ik_e, _) + | TEnum ({ekind = ik_e; _ }, _) -> + (* let c' = ID.cast_to ik_e c in *) + let c' = ID.cast_to ik_e (ID.meet c (ID.cast_to ik (ID.top_of ik_e))) in (* TODO: cast without overflow, is this right for normal invariant? *) + if M.tracing then M.tracel "inv" "cast: %a from %a to %a: i = %a; cast c = %a to %a = %a\n" d_exp e d_ikind ik_e d_ikind ik ID.pretty i ID.pretty c d_ikind ik_e ID.pretty c'; + inv_exp ~query_special (Int c') e st | x -> fallback (GobPretty.sprintf "CastE: e did evaluate to Int, but the type did not match %a" CilType.Typ.pretty t) st else fallback (GobPretty.sprintf "CastE: %a evaluates to %a which is bigger than the type it is cast to which is %a" d_plainexp e ID.pretty i CilType.Typ.pretty t) st From 88957a8005c2eff0d51c8bd1402c9d91e2e2a84e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 11:32:52 +0100 Subject: [PATCH 549/628] Add test which can be run in isolation --- tests/regression/39-signed-overflows/06-abs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/regression/39-signed-overflows/06-abs.c diff --git a/tests/regression/39-signed-overflows/06-abs.c b/tests/regression/39-signed-overflows/06-abs.c new file mode 100644 index 0000000000..b08a0f2209 --- /dev/null +++ b/tests/regression/39-signed-overflows/06-abs.c @@ -0,0 +1,15 @@ +//PARAM: --enable ana.int.interval --set ana.activated[+] tmpSpecial +#include +int main() { + int data; + if (data > (-0x7fffffff - 1)) + { + if (abs(data) < 100) + { + int result = data * data; + } + + int result = data * data; + } + return 8; +} \ No newline at end of file From 2ea8db4b64f1a55e25b2ae226d5d82815766a80c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 12:21:30 +0100 Subject: [PATCH 550/628] Wir sind alle Pfuscher vor dem HERRN --- src/analyses/base.ml | 46 +++++++++++++++---- src/analyses/baseInvariant.ml | 6 +-- tests/regression/39-signed-overflows/06-abs.c | 2 - .../39-signed-overflows/07-abs-sqrt.c | 10 ++++ 4 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 tests/regression/39-signed-overflows/07-abs-sqrt.c diff --git a/src/analyses/base.ml b/src/analyses/base.ml index f25f0a9693..8b9b232913 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1753,15 +1753,43 @@ struct let branch ctx (exp:exp) (tv:bool) : store = let valu = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in let refine () = - let res = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp tv in - if M.tracing then M.tracec "branch" "EqualSet result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.EqualSet exp)); - if M.tracing then M.tracec "branch" "CondVars result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.CondVars exp)); - if M.tracing then M.traceu "branch" "Invariant enforced!\n"; - match ctx.ask (Queries.CondVars exp) with - | s when Queries.ES.cardinal s = 1 -> - let e = Queries.ES.choose s in - invariant ctx (Analyses.ask_of_ctx ctx) ctx.global res e tv - | _ -> res + let refine0 = + let res = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp tv in + if M.tracing then M.tracec "branch" "EqualSet result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.EqualSet exp)); + if M.tracing then M.tracec "branch" "CondVars result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.CondVars exp)); + if M.tracing then M.traceu "branch" "Invariant enforced!\n"; + match ctx.ask (Queries.CondVars exp) with + | s when Queries.ES.cardinal s = 1 -> + let e = Queries.ES.choose s in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global res e tv + | _ -> res + in + match exp with + | BinOp (Lt, CastE(t,Lval (Var v, NoOffset)), e,_) when tv -> + (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> + (* e.g. |arg| < 40 *) + let v = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local e in + (* arg <= e (arg <= 40) *) + let le = BinOp (Le, CastE(t,arg), e, intType) in + (* arg >= -e (arg >= -40) *) + let gt = BinOp(Ge, CastE(t,arg), UnOp (Neg, e, Cilfacade.typeOf e), intType) in + let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + | _ -> refine0) + | BinOp (Lt, Lval (Var v, NoOffset), e, _) when tv -> + (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> + (* e.g. |arg| < 40 *) + let v = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local e in + (* arg <= e (arg <= 40) *) + let le = BinOp (Le, arg, e, intType) in + (* arg >= -e (arg >= -40) *) + let gt = BinOp(Ge, arg, UnOp (Neg, e, Cilfacade.typeOf e), intType) in + let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + | _ -> refine0) + | _ -> refine0 in if M.tracing then M.traceli "branch" ~subsys:["invariant"] "Evaluating branch for expression %a with value %a\n" d_exp exp VD.pretty valu; (* First we want to see, if we can determine a dead branch: *) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index b82ab88806..397bd1623e 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -712,7 +712,7 @@ struct begin match t with | TInt (ik, _) -> begin match x with - | ((Var v), offs) when query_special -> + | ((Var v), offs) -> if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs))); let tv_opt = ID.to_bool c in begin match tv_opt with @@ -730,7 +730,7 @@ struct inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (LAnd, (BinOp (Le, xInt, Lval x, TInt (IInt,[]))), (BinOp (Le, (UnOp (Neg, Lval x, (typeOf xInt))), xInt, TInt (IInt,[]))), (TInt (IInt, [])))) st | _ -> update_lval c x c' ID.pretty end - | None -> update_lval c x c' ID.pretty + | _ -> update_lval c x c' ID.pretty end | _ -> update_lval c x c' ID.pretty end @@ -749,7 +749,7 @@ struct begin match t with | TFloat (fk, _) -> begin match x with - | ((Var v), offs) when query_special -> + | ((Var v), offs) -> if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs))); begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with | `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp ~query_special:false (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st diff --git a/tests/regression/39-signed-overflows/06-abs.c b/tests/regression/39-signed-overflows/06-abs.c index b08a0f2209..e87e25d9fe 100644 --- a/tests/regression/39-signed-overflows/06-abs.c +++ b/tests/regression/39-signed-overflows/06-abs.c @@ -8,8 +8,6 @@ int main() { { int result = data * data; } - - int result = data * data; } return 8; } \ No newline at end of file diff --git a/tests/regression/39-signed-overflows/07-abs-sqrt.c b/tests/regression/39-signed-overflows/07-abs-sqrt.c new file mode 100644 index 0000000000..0f8ce396f2 --- /dev/null +++ b/tests/regression/39-signed-overflows/07-abs-sqrt.c @@ -0,0 +1,10 @@ +//PARAM: --enable ana.int.interval --enable ana.float.interval --set ana.activated[+] tmpSpecial +#include +int main() { + int data; + if (data > (-0x7fffffff - 1) && abs(data) < (long)sqrt((double)0x7fffffff)) + { + int result = data * data; + } + return 8; +} \ No newline at end of file From 379733825fce688cec97a63a2fa32c951e7d2c10 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 12:28:22 +0100 Subject: [PATCH 551/628] Reset baseInvariant to master --- src/analyses/baseInvariant.ml | 69 ++++++++++++++--------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 397bd1623e..72e00efbb1 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -562,7 +562,7 @@ struct | TFloat (fk, _) -> fk | _ -> failwith "value which was expected to be a float is of different type?!" in - let rec inv_exp ?(query_special=true) c_typed exp (st:D.t) : D.t = + let rec inv_exp c_typed exp (st:D.t): D.t = (* trying to improve variables in an expression so it is bottom means dead code *) if VD.is_bot_value c_typed then contra st else @@ -578,12 +578,12 @@ struct | Some false -> ID.of_bool ikind false | _ -> ID.top_of ikind in - inv_exp ~query_special (Int c') e st - | UnOp (Neg, e, _), Float c -> inv_exp ~query_special (Float (unop_FD Neg c)) e st - | UnOp ((BNot|Neg) as op, e, _), Int c -> inv_exp ~query_special (Int (unop_ID op c)) e st + inv_exp (Int c') e st + | UnOp (Neg, e, _), Float c -> inv_exp (Float (unop_FD Neg c)) e st + | UnOp ((BNot|Neg) as op, e, _), Int c -> inv_exp (Int (unop_ID op c)) e st (* no equivalent for Float, as VD.is_safe_cast fails for all float types anyways *) | BinOp((Eq | Ne) as op, CastE (t1, e1), CastE (t2, e2), t), Int c when typeSig (Cilfacade.typeOf e1) = typeSig (Cilfacade.typeOf e2) && VD.is_safe_cast t1 (Cilfacade.typeOf e1) && VD.is_safe_cast t2 (Cilfacade.typeOf e2) -> - inv_exp ~query_special (Int c) (BinOp (op, e1, e2, t)) st + inv_exp (Int c) (BinOp (op, e1, e2, t)) st | BinOp (LOr, arg1, arg2, typ) as exp, Int c -> (* copied & modified from eval_rv_base... *) let (let*) = Option.bind in @@ -631,7 +631,7 @@ struct in let definite_ad = to_definite_ad vs in let c' = VD.Address definite_ad in - Some (inv_exp ~query_special c' e st) + Some (inv_exp c' e st) | Int i -> let ik = ID.ikind i in let module BISet = IntDomain.BISet in @@ -648,20 +648,20 @@ struct in let int_id = to_int_id vs in let c' = VD.Int int_id in - Some (inv_exp ~query_special c' e st) + Some (inv_exp c' e st) | _ -> None in begin match eqs_st with | Some st -> st | None when ID.to_bool c = Some true -> - begin match inv_exp ~query_special (Int c) arg1 st with + begin match inv_exp (Int c) arg1 st with | st1 -> - begin match inv_exp ~query_special (Int c) arg2 st with + begin match inv_exp (Int c) arg2 st with | st2 -> D.join st1 st2 | exception Analyses.Deadcode -> st1 end - | exception Analyses.Deadcode -> inv_exp ~query_special (Int c) arg2 st (* Deadcode falls through *) + | exception Analyses.Deadcode -> inv_exp (Int c) arg2 st (* Deadcode falls through *) end | None -> st (* TODO: not bothering to fall back, no other case can refine LOr anyway *) @@ -676,15 +676,15 @@ struct let ikres = Cilfacade.get_ikind_exp e in (* might be different from argument types, e.g. for LT, GT, EQ, ... *) let a', b' = inv_bin_int (a, b) ikind (c_int ikres) op in if M.tracing then M.tracel "inv" "binop: %a, c: %a, a': %a, b': %a\n" d_exp e ID.pretty (c_int ikind) ID.pretty a' ID.pretty b'; - let st' = inv_exp ~query_special (Int a') e1 st in - let st'' = inv_exp ~query_special (Int b') e2 st' in + let st' = inv_exp (Int a') e1 st in + let st'' = inv_exp (Int b') e2 st' in st'' | Float a, Float b -> let fkind = Cilfacade.get_fkind_exp e1 in (* both operands have the same type *) let a', b' = inv_bin_float (a, b) (c_float fkind) op in if M.tracing then M.tracel "inv" "binop: %a, c: %a, a': %a, b': %a\n" d_exp e FD.pretty (c_float fkind) FD.pretty a' FD.pretty b'; - let st' = inv_exp ~query_special (Float a') e1 st in - let st'' = inv_exp ~query_special (Float b') e2 st' in + let st' = inv_exp (Float a') e1 st in + let st'' = inv_exp (Float b') e2 st' in st'' (* Mixed Float and Int cases should never happen, as there are no binary operators with one float and one int parameter ?!*) | Int _, Float _ | Float _, Int _ -> failwith "ill-typed program"; @@ -718,19 +718,17 @@ struct begin match tv_opt with | Some tv -> begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with - | `Lifted (Isfinite xFloat) when tv -> inv_exp ~query_special:false (Float (FD.finite (unroll_fk_of_exp xFloat))) xFloat st - | `Lifted (Isnan xFloat) when tv -> inv_exp ~query_special:false (Float (FD.nan_of (unroll_fk_of_exp xFloat))) xFloat st + | `Lifted (Isfinite xFloat) when tv -> inv_exp (Float (FD.finite (unroll_fk_of_exp xFloat))) xFloat st + | `Lifted (Isnan xFloat) when tv -> inv_exp (Float (FD.nan_of (unroll_fk_of_exp xFloat))) xFloat st (* should be correct according to C99 standard*) - | `Lifted (Isgreater (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Isgreaterequal (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Ge, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Isless (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Islessequal (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (Le, xFloat, yFloat, (typeOf xFloat))) st - | `Lifted (Islessgreater (xFloat, yFloat)) -> inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (LOr, (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))), (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))), (TInt (IBool, [])))) st - | `Lifted (Abs xInt) -> - inv_exp ~query_special:false (Int (ID.of_bool ik tv)) (BinOp (LAnd, (BinOp (Le, xInt, Lval x, TInt (IInt,[]))), (BinOp (Le, (UnOp (Neg, Lval x, (typeOf xInt))), xInt, TInt (IInt,[]))), (TInt (IInt, [])))) st + | `Lifted (Isgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Isgreaterequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Ge, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Isless (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Islessequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Le, xFloat, yFloat, (typeOf xFloat))) st + | `Lifted (Islessgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (LOr, (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))), (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))), (TInt (IBool, [])))) st | _ -> update_lval c x c' ID.pretty end - | _ -> update_lval c x c' ID.pretty + | None -> update_lval c x c' ID.pretty end | _ -> update_lval c x c' ID.pretty end @@ -752,14 +750,14 @@ struct | ((Var v), offs) -> if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs))); begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with - | `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp ~query_special:false (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st - | `Lifted (Floor (ret_fk, xFloat)) -> inv_exp ~query_special:false (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st + | `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st + | `Lifted (Floor (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st | `Lifted (Fabs (ret_fk, xFloat)) -> let inv = FD.inv_fabs (FD.cast_to ret_fk c) in if FD.is_bot inv then raise Analyses.Deadcode else - inv_exp ~query_special:false (Float inv) xFloat st + inv_exp (Float inv) xFloat st | _ -> update_lval c x c' FD.pretty end | _ -> update_lval c x c' FD.pretty @@ -779,7 +777,7 @@ struct | TFloat (FLongDouble as fk, _), FDouble | TFloat (fk, _), FLongDouble | TFloat (FDouble as fk, _), FDouble - | TFloat (FFloat as fk, _), FFloat -> inv_exp ~query_special (Float (FD.cast_to fk c)) e st + | TFloat (FFloat as fk, _), FFloat -> inv_exp (Float (FD.cast_to fk c)) e st | _ -> fallback ("CastE: incompatible types") st) | CastE ((TInt (ik, _)) as t, e), Int c | CastE ((TEnum ({ekind = ik; _ }, _)) as t, e), Int c -> (* Can only meet the t part of an Lval in e with c (unless we meet with all overflow possibilities)! Since there is no good way to do this, we only continue if e has no values outside of t. *) @@ -792,20 +790,7 @@ struct (* let c' = ID.cast_to ik_e c in *) let c' = ID.cast_to ik_e (ID.meet c (ID.cast_to ik (ID.top_of ik_e))) in (* TODO: cast without overflow, is this right for normal invariant? *) if M.tracing then M.tracel "inv" "cast: %a from %a to %a: i = %a; cast c = %a to %a = %a\n" d_exp e d_ikind ik_e d_ikind ik ID.pretty i ID.pretty c d_ikind ik_e ID.pretty c'; - inv_exp ~query_special (Int c') e st - | x -> fallback (GobPretty.sprintf "CastE: e did evaluate to Int, but the type did not match %a" CilType.Typ.pretty t) st - else - fallback (GobPretty.sprintf "CastE: %a evaluates to %a which is bigger than the type it is cast to which is %a" d_plainexp e ID.pretty i CilType.Typ.pretty t) st - | Float i -> - let i = FD.to_int ik i in - if ID.leq i (ID.cast_to ik i) then - match unrollType (Cilfacade.typeOf e) with - | TInt(ik_e, _) - | TEnum ({ekind = ik_e; _ }, _) -> - (* let c' = ID.cast_to ik_e c in *) - let c' = ID.cast_to ik_e (ID.meet c (ID.cast_to ik (ID.top_of ik_e))) in (* TODO: cast without overflow, is this right for normal invariant? *) - if M.tracing then M.tracel "inv" "cast: %a from %a to %a: i = %a; cast c = %a to %a = %a\n" d_exp e d_ikind ik_e d_ikind ik ID.pretty i ID.pretty c d_ikind ik_e ID.pretty c'; - inv_exp ~query_special (Int c') e st + inv_exp (Int c') e st | x -> fallback (GobPretty.sprintf "CastE: e did evaluate to Int, but the type did not match %a" CilType.Typ.pretty t) st else fallback (GobPretty.sprintf "CastE: %a evaluates to %a which is bigger than the type it is cast to which is %a" d_plainexp e ID.pretty i CilType.Typ.pretty t) st From 6895ac0cf305747f617d8b4c42f191484f6bc072 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 12:41:37 +0100 Subject: [PATCH 552/628] Make bodge a bit nicer --- src/analyses/base.ml | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 8b9b232913..8497f38615 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1764,30 +1764,26 @@ struct invariant ctx (Analyses.ask_of_ctx ctx) ctx.global res e tv | _ -> res in + (* bodge for abs(...); To be removed once we have a clean solution *) + let refineAbs absargexp valexp = + (* e.g. |arg| < 40 *) + (* arg <= e (arg <= 40) *) + let le = BinOp (Le, absargexp, valexp, intType) in + (* arg >= -e (arg >= -40) *) + let gt = BinOp(Ge, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in + let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + in match exp with - | BinOp (Lt, CastE(t,Lval (Var v, NoOffset)), e,_) when tv -> + | BinOp (Lt, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with | `Lifted (Abs arg) -> - (* e.g. |arg| < 40 *) - let v = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local e in - (* arg <= e (arg <= 40) *) - let le = BinOp (Le, CastE(t,arg), e, intType) in - (* arg >= -e (arg >= -40) *) - let gt = BinOp(Ge, CastE(t,arg), UnOp (Neg, e, Cilfacade.typeOf e), intType) in - let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in - invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + refineAbs (CastE (t, arg)) e | _ -> refine0) | BinOp (Lt, Lval (Var v, NoOffset), e, _) when tv -> (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with | `Lifted (Abs arg) -> - (* e.g. |arg| < 40 *) - let v = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local e in - (* arg <= e (arg <= 40) *) - let le = BinOp (Le, arg, e, intType) in - (* arg >= -e (arg >= -40) *) - let gt = BinOp(Ge, arg, UnOp (Neg, e, Cilfacade.typeOf e), intType) in - let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in - invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + refineAbs arg e | _ -> refine0) | _ -> refine0 in From ba6726a4515ca4873c1abb87b58f7d9a7f535da8 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 12:50:57 +0100 Subject: [PATCH 553/628] Handle <= as well --- src/analyses/base.ml | 17 +++++++++-------- tests/regression/39-signed-overflows/06-abs.c | 11 ++++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 8497f38615..4911b0d033 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1765,25 +1765,26 @@ struct | _ -> res in (* bodge for abs(...); To be removed once we have a clean solution *) - let refineAbs absargexp valexp = - (* e.g. |arg| < 40 *) + let refineAbs op absargexp valexp = + let flip op = match op with | Le -> Ge | Lt -> Gt | _ -> failwith "impossible" in + (* e.g. |arg| <= 40 *) (* arg <= e (arg <= 40) *) - let le = BinOp (Le, absargexp, valexp, intType) in + let le = BinOp (op, absargexp, valexp, intType) in (* arg >= -e (arg >= -40) *) - let gt = BinOp(Ge, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in + let gt = BinOp(flip op, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv in match exp with - | BinOp (Lt, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> + | BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with | `Lifted (Abs arg) -> - refineAbs (CastE (t, arg)) e + refineAbs op (CastE (t, arg)) e | _ -> refine0) - | BinOp (Lt, Lval (Var v, NoOffset), e, _) when tv -> + | BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv -> (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with | `Lifted (Abs arg) -> - refineAbs arg e + refineAbs op arg e | _ -> refine0) | _ -> refine0 in diff --git a/tests/regression/39-signed-overflows/06-abs.c b/tests/regression/39-signed-overflows/06-abs.c index e87e25d9fe..e56cc9ff7d 100644 --- a/tests/regression/39-signed-overflows/06-abs.c +++ b/tests/regression/39-signed-overflows/06-abs.c @@ -6,7 +6,16 @@ int main() { { if (abs(data) < 100) { - int result = data * data; + __goblint_check(data < 100); + __goblint_check(-100 < data); + int result = data * data; //NOWARN + } + + if(abs(data) <= 100) + { + __goblint_check(data <= 100); + __goblint_check(-100 <= data); + int result = data * data; //NOWARN } } return 8; From 8ea9ffa726f13f0d764cf2dbd7ee6a1d18270573 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 18 Nov 2023 12:51:32 +0100 Subject: [PATCH 554/628] 39/07: Add NOWARN annotation --- tests/regression/39-signed-overflows/07-abs-sqrt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/39-signed-overflows/07-abs-sqrt.c b/tests/regression/39-signed-overflows/07-abs-sqrt.c index 0f8ce396f2..13ed863e51 100644 --- a/tests/regression/39-signed-overflows/07-abs-sqrt.c +++ b/tests/regression/39-signed-overflows/07-abs-sqrt.c @@ -4,7 +4,7 @@ int main() { int data; if (data > (-0x7fffffff - 1) && abs(data) < (long)sqrt((double)0x7fffffff)) { - int result = data * data; + int result = data * data; //NOWARN } return 8; } \ No newline at end of file From 7289ec341760ab06ce518c7520b076ca50688bb3 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 18 Nov 2023 14:38:13 +0100 Subject: [PATCH 555/628] Use solely local state for multi-threaded valid-memcleanup --- src/analyses/memLeak.ml | 61 ++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index c64bb95697..64fe7ab957 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -6,6 +6,7 @@ open MessageCategory open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) +module ThreadsToHeapVarsMap = MapDomain.MapBot(ThreadIdDomain.Thread)(ToppedVarInfoSet) module WasMallocCalled = BoolDomain.MustBool module Spec : Analyses.MCPSpec = struct @@ -13,16 +14,9 @@ struct let name () = "memLeak" - (* module D = ToppedVarInfoSet *) - module D = Lattice.Prod(ToppedVarInfoSet)(WasMallocCalled) + module D = Lattice.Prod(ThreadsToHeapVarsMap)(WasMallocCalled) module C = D module P = IdentityP (D) - module G = ToppedVarInfoSet - module V = - struct - include ThreadIdDomain.Thread - include StdV - end let context _ d = d @@ -35,21 +29,18 @@ struct M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program aborted while running in multi-threaded mode. A memory leak might occur" ) - (* If [is_return] is set to [true], then a thread return occurred, else a thread join *) + (* If [is_return] is set to [true], then a thread return occurred, else a thread exit *) let warn_for_thread_return_or_exit current_thread ctx is_return = - let global_state = ctx.global current_thread in - if not (G.is_empty global_state) then ( + let state = ctx.local in + let heap_vars_of_curr_tid = ThreadsToHeapVarsMap.find current_thread (fst state) in + if not (ToppedVarInfoSet.is_empty heap_vars_of_curr_tid) then ( set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s" (if is_return then "return" else "join") + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s for thread %a" (if is_return then "return" else "exit") ThreadIdDomain.Thread.pretty current_thread ) - (* if not (ToppedVarInfoSet.is_empty (fst state)) && snd state then ( - set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s" (if is_return then "return" else "join") - ) *) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in - if not (ToppedVarInfoSet.is_empty (fst state)) then + if not (ThreadsToHeapVarsMap.for_all (fun tid heap_vars -> ToppedVarInfoSet.is_empty heap_vars) (fst state)) then match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; @@ -58,14 +49,15 @@ struct | _ -> set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables" (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = (* Check for a valid-memcleanup violation in a multi-threaded setting *) if (ctx.ask (Queries.MayBeThreadReturn)) then ( match ctx.ask (Queries.CurrentThreadId) with - | `Lifted tid -> warn_for_thread_return_or_exit tid ctx true + | `Lifted tid -> + warn_for_thread_return_or_exit tid ctx true | _ -> () ); (* Returning from "main" is one possible program exit => need to check for memory leaks *) @@ -83,34 +75,34 @@ struct | `Lifted var -> begin match ctx.ask (Queries.CurrentThreadId) with | `Lifted tid -> - let current_globals = ctx.global tid in - let globals_to_side_effect = G.add var current_globals in - ctx.sideg tid globals_to_side_effect; - | _ -> () - end; - (ToppedVarInfoSet.add var (fst state), true) + ((ThreadsToHeapVarsMap.add tid (ToppedVarInfoSet.singleton var) (fst state)), true) + | _ -> (fst state, true) + end | _ -> (fst state, true) end | Free ptr -> begin match ctx.ask (Queries.MayPointTo ptr) with - | ad when not (Queries.AD.is_top ad) && Queries.AD.cardinal ad = 1 -> + (* TODO: The cardinality of 1 seems to lead to the situation where only free() calls in main() are detected here (affects 76/08 and 76/09) *) + (* | ad when not (Queries.AD.is_top ad) && Queries.AD.cardinal ad = 1 -> *) + | ad when not (Queries.AD.is_top ad) -> (* Note: Need to always set "ana.malloc.unique_address_count" to a value > 0 *) begin match Queries.AD.choose ad with | Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> begin match ctx.ask (Queries.CurrentThreadId) with | `Lifted tid -> - let current_globals = ctx.global tid in - let globals_to_side_effect = G.remove v current_globals in - ctx.sideg tid globals_to_side_effect - | _ -> () - end; - (ToppedVarInfoSet.remove v (fst state), snd state) (* Unique pointed to heap vars *) + let heap_vars_of_tid = ThreadsToHeapVarsMap.find tid (fst state) in + let heap_vars_of_tid_without_v = ToppedVarInfoSet.remove v heap_vars_of_tid in + let new_fst_state = ThreadsToHeapVarsMap.add tid heap_vars_of_tid_without_v (fst state) in + (new_fst_state, snd state) + | _ -> state + end | _ -> state end | _ -> state end | Abort -> - (* Upon a call to the "Abort" special function, we give up and conservatively warn *) + check_for_mem_leak ctx; + (* Upon a call to the "Abort" special function in the multi-threaded case, we give up and conservatively warn *) warn_for_multi_threaded_due_to_abort ctx; state | Assert { exp; _ } -> @@ -131,7 +123,8 @@ struct state | ThreadExit _ -> begin match ctx.ask (Queries.CurrentThreadId) with - | `Lifted tid -> warn_for_thread_return_or_exit tid ctx false + | `Lifted tid -> + warn_for_thread_return_or_exit tid ctx false | _ -> () end; state From 6cc01b5177b6bc31899c290b6ae65660bf4aa805 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 18 Nov 2023 15:22:47 +0100 Subject: [PATCH 556/628] Use `unrollType` and `GVarDecl` for global vars Also use `Queries.AD.fold` where applicable and prepend to accumulators --- src/analyses/memLeak.ml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 51a5a2ff75..c09db2d44f 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -21,15 +21,20 @@ struct (* HELPER FUNCTIONS *) let get_global_vars () = - (* Filtering by GVar seems to account for declarations, as well as definitions of global vars *) - List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + List.filter_map (function GVar (v, _, _) | GVarDecl (v, _) -> Some v | _ -> None) !Cilfacade.current_file.globals let get_global_struct_ptr_vars () = - List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals - |> List.filter (fun v -> match v.vtype with TPtr (TComp _, _) | TPtr ((TNamed ({ttype = TComp _; _}, _)), _) -> true | _ -> false) + get_global_vars () + |> List.filter (fun v -> + match unrollType v.vtype with + | TPtr (TComp _, _) + | TPtr ((TNamed ({ttype = TComp _; _}, _)), _) -> true + | TComp (_, _) + | (TNamed ({ttype = TComp _; _}, _)) -> false + | _ -> false) let get_global_struct_non_ptr_vars () = - List.filter_map (function GVar (v, _, _) -> Some v | _ -> None) !Cilfacade.current_file.globals + get_global_vars () |> List.filter (fun v -> match v.vtype with TComp (_, _) | (TNamed ({ttype = TComp _; _}, _)) -> true | _ -> false) let get_reachable_mem_from_globals (global_vars:varinfo list) ctx = @@ -55,12 +60,13 @@ struct begin match ValueDomain.Structs.get s f with | Queries.VD.Address a -> let reachable_from_addr_set = - List.fold_left (fun acc addr -> + Queries.AD.fold (fun addr acc -> match addr with - | Queries.AD.Addr.Addr (v, _) -> List.append acc (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) + | Queries.AD.Addr.Addr (v, _) -> (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) @ acc | _ -> acc - ) [] (Queries.AD.elements a) - in List.append acc reachable_from_addr_set + ) a [] + in + reachable_from_addr_set @ acc | _ -> acc end else acc @@ -109,14 +115,14 @@ struct let reachable_from_addr_set = List.fold_left (fun acc_addr addr -> match addr with - | Queries.AD.Addr.Addr (v, _) -> List.append acc_addr (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) + | Queries.AD.Addr.Addr (v, _) -> (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) @ acc_addr | _ -> acc_addr ) [] (Queries.AD.elements a) - in List.append acc_field reachable_from_addr_set + in reachable_from_addr_set @ acc_field | _ -> acc_field ) [] fields in - List.append acc_struct reachable_from_fields + reachable_from_fields @ acc_struct ) [] let warn_for_multi_threaded ctx = From 80492ccd1dcad21e49a949a989d1cee42bbb6585 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sat, 18 Nov 2023 15:26:40 +0100 Subject: [PATCH 557/628] Check that addresses in struct fields are singletons and not top --- src/analyses/memLeak.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index c09db2d44f..7e77d62a4e 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -58,7 +58,7 @@ struct List.fold_left (fun acc f -> if isPointerType f.ftype then begin match ValueDomain.Structs.get s f with - | Queries.VD.Address a -> + | Queries.VD.Address a when not (Queries.AD.is_top a) && Queries.AD.cardinal a = 1 -> let reachable_from_addr_set = Queries.AD.fold (fun addr acc -> match addr with From 1f4d8be9e8fed3fe55b1561e0fac4cfc1923db25 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 01:30:44 +0100 Subject: [PATCH 558/628] Avoid creating unneeded Task module which may not be set in `is_error_function'` --- src/witness/svcomp.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 404626bb07..6d22a51166 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -17,7 +17,6 @@ let task: (module Task) option ref = ref None let is_error_function' f spec = - let module Task = (val (Option.get !task)) in List.exists (function | Specification.UnreachCall f_spec -> f.vname = f_spec | _ -> false From 116916a5e48b2e56331da426664bd94246ddfa4b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 16:13:56 +0100 Subject: [PATCH 559/628] unlocked: Only test termination in config with Apron (References #1093) --- .github/workflows/unlocked.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/unlocked.yml b/.github/workflows/unlocked.yml index 22e1417ea4..990b7cfb49 100644 --- a/.github/workflows/unlocked.yml +++ b/.github/workflows/unlocked.yml @@ -93,6 +93,7 @@ jobs: run: ruby scripts/update_suite.rb group apron-mukherjee -s - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + if: ${{ matrix.apron }} run: ruby scripts/update_suite.rb group termination -s - name: Test regression cram From 065221367db8e46f59f33bd18b07f8802af283e2 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Sun, 19 Nov 2023 16:47:03 +0100 Subject: [PATCH 560/628] Autotune termination spec before preprocessing, but not others. --- src/autoTune.ml | 21 ++++++++++++++------- src/goblint.ml | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 5e0034e6eb..70f61d5172 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -237,12 +237,8 @@ let focusOnMemSafetySpecification (spec: Svcomp.Specification.t) = let focusOnMemSafetySpecification () = List.iter focusOnMemSafetySpecification (Svcomp.Specification.of_option ()) -let focusOnSpecification (spec: Svcomp.Specification.t) = +let focusOnTermination (spec: Svcomp.Specification.t) = match spec with - | UnreachCall s -> () - | NoDataRace -> (*enable all thread analyses*) - print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; - enableAnalyses notNeccessaryThreadAnalyses; | Termination -> let terminationAnas = ["termination"; "threadflag"; "apron"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; @@ -251,6 +247,17 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = set_bool "ana.int.interval" true; set_string "ana.apron.domain" "polyhedra"; (* TODO: Needed? *) () + | _ -> () + +let focusOnTermination () = + List.iter focusOnTermination (Svcomp.Specification.of_option ()) + +let focusOnSpecification (spec: Svcomp.Specification.t) = + match spec with + | UnreachCall s -> () + | NoDataRace -> (*enable all thread analyses*) + print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; + enableAnalyses notNeccessaryThreadAnalyses; | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true @@ -518,8 +525,8 @@ let chooseConfig file = if isActivated "mallocWrappers" then findMallocWrappers (); - (* if specificationIsActivated () then - focusOnSpecification (); *) + if specificationIsActivated () then + focusOnSpecification (); if isActivated "enums" && hasEnums file then set_bool "ana.int.enums" true; diff --git a/src/goblint.ml b/src/goblint.ml index 6c5a2df33d..9b95c95da4 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -39,7 +39,7 @@ let main () = print_endline GobSys.command_line; ); (* When analyzing a termination specification, activate the termination analysis before pre-processing. *) - if get_bool "ana.autotune.enabled" && AutoTune.specificationIsActivated () then AutoTune.focusOnSpecification (); + if get_bool "ana.autotune.enabled" && AutoTune.specificationIsActivated () then AutoTune.focusOnTermination (); let file = lazy (Fun.protect ~finally:GoblintDir.finalize preprocess_parse_merge) in if get_bool "server.enabled" then ( let file = From 9d8629dc30b557e319838070e260508d4def8cf5 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Sun, 19 Nov 2023 16:57:56 +0100 Subject: [PATCH 561/628] Use autotune.activated termination as separate switch whether termination analysis should be activated (instead of using specification). --- conf/svcomp.json | 3 +-- src/autoTune.ml | 3 +++ src/goblint.ml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index cc6d1e303a..107c59994c 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -72,8 +72,7 @@ "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", - "termination", - "specification" + "termination" ] } }, diff --git a/src/autoTune.ml b/src/autoTune.ml index 70f61d5172..346e9d7b6f 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -506,6 +506,9 @@ let isTerminationTask () = List.mem Svcomp.Specification.Termination (Svcomp.Spe let specificationIsActivated () = isActivated "specification" && get_string "ana.specification" <> "" +let specificationTerminationIsActivated () = + isActivated "termination" + let chooseConfig file = let factors = collectFactors visitCilFileSameGlobals file in let fileCompplexity = estimateComplexity factors file in diff --git a/src/goblint.ml b/src/goblint.ml index 9b95c95da4..25e809f9e9 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -39,7 +39,7 @@ let main () = print_endline GobSys.command_line; ); (* When analyzing a termination specification, activate the termination analysis before pre-processing. *) - if get_bool "ana.autotune.enabled" && AutoTune.specificationIsActivated () then AutoTune.focusOnTermination (); + if get_bool "ana.autotune.enabled" && AutoTune.specificationTerminationIsActivated () then AutoTune.focusOnTermination (); let file = lazy (Fun.protect ~finally:GoblintDir.finalize preprocess_parse_merge) in if get_bool "server.enabled" then ( let file = From 720cfeebd1987bda44e4b7f4a2d545be6530025d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 17:32:05 +0100 Subject: [PATCH 562/628] IsMallocCalled should be `may` --- src/analyses/memLeak.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 64fe7ab957..336943d407 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -7,7 +7,7 @@ open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) module ThreadsToHeapVarsMap = MapDomain.MapBot(ThreadIdDomain.Thread)(ToppedVarInfoSet) -module WasMallocCalled = BoolDomain.MustBool +module WasMallocCalled = BoolDomain.MayBool module Spec : Analyses.MCPSpec = struct include Analyses.IdentitySpec From f2ca6d146e1271709259be24d5b20f9e61aab7dd Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 19 Nov 2023 17:33:24 +0100 Subject: [PATCH 563/628] Use `unrollType` for non-pointer global struct vars --- src/analyses/memLeak.ml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 7e77d62a4e..ab25d49cc6 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -35,7 +35,11 @@ struct let get_global_struct_non_ptr_vars () = get_global_vars () - |> List.filter (fun v -> match v.vtype with TComp (_, _) | (TNamed ({ttype = TComp _; _}, _)) -> true | _ -> false) + |> List.filter (fun v -> + match unrollType v.vtype with + | TComp (_, _) + | (TNamed ({ttype = TComp _; _}, _)) -> true + | _ -> false) let get_reachable_mem_from_globals (global_vars:varinfo list) ctx = global_vars From 0e09d099d5facf7354014319805eb53e186119d2 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 19 Nov 2023 17:36:22 +0100 Subject: [PATCH 564/628] Don't forget to prepend to `acc` when collecting globally reachable mem --- src/analyses/memLeak.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index ab25d49cc6..3079faae1f 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -91,8 +91,8 @@ struct in global_struct_ptr_vars |> List.fold_left (fun acc var -> - if ctx.ask (Queries.IsHeapVar var) then eval_value_of_heap_var var - else if not (ctx.ask (Queries.IsAllocVar var)) && isPointerType var.vtype then get_pts_of_non_heap_ptr_var var + if ctx.ask (Queries.IsHeapVar var) then (eval_value_of_heap_var var) @ acc + else if not (ctx.ask (Queries.IsAllocVar var)) && isPointerType var.vtype then (get_pts_of_non_heap_ptr_var var) @ acc else acc ) [] From af9ddc766c5b72e7bbd9d3177e1cd028e52cfc52 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 17:36:26 +0100 Subject: [PATCH 565/628] Add unsound example --- tests/regression/76-memleak/10-leak-later.c | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/regression/76-memleak/10-leak-later.c diff --git a/tests/regression/76-memleak/10-leak-later.c b/tests/regression/76-memleak/10-leak-later.c new file mode 100644 index 0000000000..6e6e51bbdc --- /dev/null +++ b/tests/regression/76-memleak/10-leak-later.c @@ -0,0 +1,25 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include +#include + +int *g; +int *m1; +int *m2; + +void *f1(void *arg) { + int top; + + // Thread t1 leaks m0 here + exit(2); //WARN +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + int* m0 = malloc(sizeof(int)); + free(m0); + + // main thread is not leaking anything + return 0; +} From ada84914a0da7614e023d6c0bf2ca86725d6551a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 18:14:50 +0100 Subject: [PATCH 566/628] Make sound by accounting for alloc in global invariant --- src/analyses/memLeak.ml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index b1b57b6694..d2d3ce0d97 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -14,16 +14,19 @@ struct let name () = "memLeak" - module D = Lattice.Prod(ThreadsToHeapVarsMap)(WasMallocCalled) + module D = ThreadsToHeapVarsMap module C = D module P = IdentityP (D) + module V = UnitV + module G = WasMallocCalled + let context _ d = d (* HELPER FUNCTIONS *) let warn_for_multi_threaded_due_to_abort ctx = - let state = ctx.local in - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) && snd state then ( + let malloc_called = ctx.global () in + if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) && malloc_called then ( set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program aborted while running in multi-threaded mode. A memory leak might occur" @@ -32,7 +35,7 @@ struct (* If [is_return] is set to [true], then a thread return occurred, else a thread exit *) let warn_for_thread_return_or_exit current_thread ctx is_return = let state = ctx.local in - let heap_vars_of_curr_tid = ThreadsToHeapVarsMap.find current_thread (fst state) in + let heap_vars_of_curr_tid = ThreadsToHeapVarsMap.find current_thread state in if not (ToppedVarInfoSet.is_empty heap_vars_of_curr_tid) then ( set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s for thread %a" (if is_return then "return" else "exit") ThreadIdDomain.Thread.pretty current_thread @@ -40,7 +43,7 @@ struct let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in - if not (ThreadsToHeapVarsMap.for_all (fun tid heap_vars -> ToppedVarInfoSet.is_empty heap_vars) (fst state)) then + if not (ThreadsToHeapVarsMap.for_all (fun tid heap_vars -> ToppedVarInfoSet.is_empty heap_vars) state) then match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; @@ -71,14 +74,15 @@ struct | Malloc _ | Calloc _ | Realloc _ -> + ctx.sideg () true; begin match ctx.ask (Queries.AllocVar {on_stack = false}) with | `Lifted var -> begin match ctx.ask (Queries.CurrentThreadId) with | `Lifted tid -> - ((ThreadsToHeapVarsMap.add tid (ToppedVarInfoSet.singleton var) (fst state)), true) - | _ -> (fst state, true) + (ThreadsToHeapVarsMap.add tid (ToppedVarInfoSet.singleton var) state) + | _ -> state end - | _ -> (fst state, true) + | _ -> state end | Free ptr -> begin match ctx.ask (Queries.MayPointTo ptr) with @@ -90,10 +94,10 @@ struct | Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> begin match ctx.ask (Queries.CurrentThreadId) with | `Lifted tid -> - let heap_vars_of_tid = ThreadsToHeapVarsMap.find tid (fst state) in + let heap_vars_of_tid = ThreadsToHeapVarsMap.find tid state in let heap_vars_of_tid_without_v = ToppedVarInfoSet.remove v heap_vars_of_tid in - let new_fst_state = ThreadsToHeapVarsMap.add tid heap_vars_of_tid_without_v (fst state) in - (new_fst_state, snd state) + let new_fst_state = ThreadsToHeapVarsMap.add tid heap_vars_of_tid_without_v state in + new_fst_state | _ -> state end | _ -> state From e7d630231d2bfce552cbb262bf3f8a4882ddd1ff Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 18:49:03 +0100 Subject: [PATCH 567/628] Cleanup --- src/analyses/memLeak.ml | 53 +++++++------------ .../08-invalid-memcleanup-multi-threaded.c | 2 +- ...-invalid-memcleanup-multi-threaded-abort.c | 2 +- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index d2d3ce0d97..0f16cec4ab 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -6,7 +6,6 @@ open MessageCategory open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) -module ThreadsToHeapVarsMap = MapDomain.MapBot(ThreadIdDomain.Thread)(ToppedVarInfoSet) module WasMallocCalled = BoolDomain.MayBool module Spec : Analyses.MCPSpec = struct @@ -14,7 +13,7 @@ struct let name () = "memLeak" - module D = ThreadsToHeapVarsMap + module D = ToppedVarInfoSet module C = D module P = IdentityP (D) @@ -33,22 +32,20 @@ struct ) (* If [is_return] is set to [true], then a thread return occurred, else a thread exit *) - let warn_for_thread_return_or_exit current_thread ctx is_return = - let state = ctx.local in - let heap_vars_of_curr_tid = ThreadsToHeapVarsMap.find current_thread state in - if not (ToppedVarInfoSet.is_empty heap_vars_of_curr_tid) then ( + let warn_for_thread_return_or_exit ctx is_return = + if not (ToppedVarInfoSet.is_empty ctx.local) then ( set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s for thread %a" (if is_return then "return" else "exit") ThreadIdDomain.Thread.pretty current_thread + let current_thread = ctx.ask (Queries.CurrentThreadId) in + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s for thread %a" (if is_return then "return" else "exit") ThreadIdDomain.ThreadLifted.pretty current_thread ) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = - let state = ctx.local in - if not (ThreadsToHeapVarsMap.for_all (fun tid heap_vars -> ToppedVarInfoSet.is_empty heap_vars) state) then + if not (ToppedVarInfoSet.is_empty ctx.local) then match assert_exp_imprecise, exp with | true, Some exp -> set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; - M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty ctx.local | _ -> set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; @@ -58,10 +55,7 @@ struct let return ctx (exp:exp option) (f:fundec) : D.t = (* Check for a valid-memcleanup violation in a multi-threaded setting *) if (ctx.ask (Queries.MayBeThreadReturn)) then ( - match ctx.ask (Queries.CurrentThreadId) with - | `Lifted tid -> - warn_for_thread_return_or_exit tid ctx true - | _ -> () + warn_for_thread_return_or_exit ctx true ); (* Returning from "main" is one possible program exit => need to check for memory leaks *) if f.svar.vname = "main" then check_for_mem_leak ctx; @@ -74,35 +68,22 @@ struct | Malloc _ | Calloc _ | Realloc _ -> - ctx.sideg () true; + (ctx.sideg () true; begin match ctx.ask (Queries.AllocVar {on_stack = false}) with | `Lifted var -> - begin match ctx.ask (Queries.CurrentThreadId) with - | `Lifted tid -> - (ThreadsToHeapVarsMap.add tid (ToppedVarInfoSet.singleton var) state) - | _ -> state - end + ToppedVarInfoSet.add var state | _ -> state - end + end) | Free ptr -> begin match ctx.ask (Queries.MayPointTo ptr) with - (* TODO: The cardinality of 1 seems to lead to the situation where only free() calls in main() are detected here (affects 76/08 and 76/09) *) - (* | ad when not (Queries.AD.is_top ad) && Queries.AD.cardinal ad = 1 -> *) - | ad when not (Queries.AD.is_top ad) -> + | ad when (not (Queries.AD.is_top ad)) && Queries.AD.cardinal ad = 1 -> (* Note: Need to always set "ana.malloc.unique_address_count" to a value > 0 *) begin match Queries.AD.choose ad with | Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> - begin match ctx.ask (Queries.CurrentThreadId) with - | `Lifted tid -> - let heap_vars_of_tid = ThreadsToHeapVarsMap.find tid state in - let heap_vars_of_tid_without_v = ToppedVarInfoSet.remove v heap_vars_of_tid in - let new_fst_state = ThreadsToHeapVarsMap.add tid heap_vars_of_tid_without_v state in - new_fst_state - | _ -> state - end - | _ -> state + ToppedVarInfoSet.remove v ctx.local + | _ -> ctx.local end - | _ -> state + | _ -> ctx.local end | Abort -> check_for_mem_leak ctx; @@ -128,7 +109,7 @@ struct | ThreadExit _ -> begin match ctx.ask (Queries.CurrentThreadId) with | `Lifted tid -> - warn_for_thread_return_or_exit tid ctx false + warn_for_thread_return_or_exit ctx false | _ -> () end; state @@ -136,6 +117,8 @@ struct let startstate v = D.bot () let exitstate v = D.top () + + let threadenter ctx ~multiple lval f args = [D.bot ()] end let _ = diff --git a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c index 50b17fa65d..513a36db95 100644 --- a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c +++ b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c @@ -4,7 +4,6 @@ int *g; int *m1; -int *m2; void *f1(void *arg) { m1 = malloc(sizeof(int)); @@ -13,6 +12,7 @@ void *f1(void *arg) { } void *f2(void *arg) { + int *m2; m2 = malloc(sizeof(int)); free(m2); // No leak for thread t2, since it calls free before exiting pthread_exit(NULL); //NOWARN diff --git a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c index 9aef45198e..977510b9bb 100644 --- a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c +++ b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c @@ -4,7 +4,6 @@ int *g; int *m1; -int *m2; void *f1(void *arg) { m1 = malloc(sizeof(int)); @@ -13,6 +12,7 @@ void *f1(void *arg) { } void *f2(void *arg) { + int *m2; m2 = malloc(sizeof(int)); free(m2); // No leak for thread t2, since it calls free before exiting pthread_exit(NULL); //NOWARN From e6cee270129731e462b31a0a75cb360d02b784c6 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 19:01:11 +0100 Subject: [PATCH 568/628] Fix `memtrack` for multi-threaded case --- src/analyses/memLeak.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 0f16cec4ab..8a067cc80d 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -34,6 +34,7 @@ struct (* If [is_return] is set to [true], then a thread return occurred, else a thread exit *) let warn_for_thread_return_or_exit ctx is_return = if not (ToppedVarInfoSet.is_empty ctx.local) then ( + set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; let current_thread = ctx.ask (Queries.CurrentThreadId) in M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory may be leaked at thread %s for thread %a" (if is_return then "return" else "exit") ThreadIdDomain.ThreadLifted.pretty current_thread @@ -53,8 +54,9 @@ struct (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = - (* Check for a valid-memcleanup violation in a multi-threaded setting *) - if (ctx.ask (Queries.MayBeThreadReturn)) then ( + (* Check for a valid-memcleanup and memtrack violation in a multi-threaded setting *) + (* The check for multi-threadedness is to ensure that valid-memtrack and valid-memclenaup are treated separately for single-threaded programs *) + if (ctx.ask (Queries.MayBeThreadReturn) && not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true }))) then ( warn_for_thread_return_or_exit ctx true ); (* Returning from "main" is one possible program exit => need to check for memory leaks *) From 97eb7156d4a71fce2e84153b1a11906db5e9f2de Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 19 Nov 2023 19:23:20 +0100 Subject: [PATCH 569/628] Account for failing assertions in the multi-threaded case as well --- src/analyses/memLeak.ml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 8a067cc80d..8d83bcee83 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -98,12 +98,16 @@ struct | a when Queries.ID.is_bot a -> M.warn ~category:Assert "assert expression %a is bottom" d_exp exp | a -> begin match Queries.ID.to_bool a with - | Some b -> + | Some b -> ( (* If we know for sure that the expression in "assert" is false => need to check for memory leaks *) - if b = false then - check_for_mem_leak ctx - else () - | None -> check_for_mem_leak ctx ~assert_exp_imprecise:true ~exp:(Some exp) + if b = false then ( + warn_for_multi_threaded_due_to_abort ctx; + check_for_mem_leak ctx + ) + else ()) + | None -> + (warn_for_multi_threaded_due_to_abort ctx; + check_for_mem_leak ctx ~assert_exp_imprecise:true ~exp:(Some exp)) end in warn_for_assert_exp; From 987795ec92c6e03fc9b0b659dbc396b73df41098 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 19 Nov 2023 19:26:39 +0100 Subject: [PATCH 570/628] Add a few more test cases --- .../76-memleak/11-leak-later-nested.c | 34 +++++++++++++++++++ .../76-memleak/12-multi-threaded-assert.c | 34 +++++++++++++++++++ .../13-assert-unknown-multi-threaded.c | 20 +++++++++++ 3 files changed, 88 insertions(+) create mode 100644 tests/regression/76-memleak/11-leak-later-nested.c create mode 100644 tests/regression/76-memleak/12-multi-threaded-assert.c create mode 100644 tests/regression/76-memleak/13-assert-unknown-multi-threaded.c diff --git a/tests/regression/76-memleak/11-leak-later-nested.c b/tests/regression/76-memleak/11-leak-later-nested.c new file mode 100644 index 0000000000..952dc66334 --- /dev/null +++ b/tests/regression/76-memleak/11-leak-later-nested.c @@ -0,0 +1,34 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +#include +#include + +int *g; +int *m1; +int *m2; + +void *f2(void *arg) { + // Thread t2 leaks m0 and t1_ptr here + quick_exit(2); //WARN +} + +void *f1(void *arg) { + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + int *t1_ptr = malloc(sizeof(int)); + + pthread_join(t2, NULL); + // t1_ptr is leaked, since t2 calls quick_exit() potentially before this program point + free(t1_ptr); +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + int* m0 = malloc(sizeof(int)); + free(m0); + + // main thread is not leaking anything + return 0; +} diff --git a/tests/regression/76-memleak/12-multi-threaded-assert.c b/tests/regression/76-memleak/12-multi-threaded-assert.c new file mode 100644 index 0000000000..309a5dde75 --- /dev/null +++ b/tests/regression/76-memleak/12-multi-threaded-assert.c @@ -0,0 +1,34 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --disable warn.assert +#include +#include +#include + +int *g; +int *m1; +int *m2; + +void *f2(void *arg) { + // Thread t2 leaks m0 and t1_ptr here + assert(0); //WARN +} + +void *f1(void *arg) { + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + int *t1_ptr = malloc(sizeof(int)); + assert(1); //NOWARN + pthread_join(t2, NULL); + free(t1_ptr); +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + int* m0 = malloc(sizeof(int)); + free(m0); + + // main thread is not leaking anything + return 0; +} diff --git a/tests/regression/76-memleak/13-assert-unknown-multi-threaded.c b/tests/regression/76-memleak/13-assert-unknown-multi-threaded.c new file mode 100644 index 0000000000..95eb291887 --- /dev/null +++ b/tests/regression/76-memleak/13-assert-unknown-multi-threaded.c @@ -0,0 +1,20 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --disable warn.assert +#include +#include +#include + +void *f1(void *arg) { + int top; + assert(top); //WARN +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + int* m0 = malloc(sizeof(int)); + free(m0); + + // main thread is not leaking anything + return 0; +} From f6cef727d38bd2deb0c766d2f8bc6c726024bbbc Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sun, 19 Nov 2023 19:27:55 +0100 Subject: [PATCH 571/628] `<<` Fix wrong order of `minimal`/`maximal` --- src/cdomains/intDomain.ml | 2 +- tests/regression/39-signed-overflows/06-shiftleft.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 49065b9cc5..5a80d67bfe 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -874,7 +874,7 @@ struct | true, _ | _ , true -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (show a) (show b))) | _ -> - match a, maximal b, minimal b with + match a, minimal b, maximal b with | Some a, Some bl, Some bu when (Ints_t.compare bl Ints_t.zero >= 0) -> (try let r = IArith.shiftleft a (Ints_t.to_int bl, Ints_t.to_int bu) in diff --git a/tests/regression/39-signed-overflows/06-shiftleft.c b/tests/regression/39-signed-overflows/06-shiftleft.c index 987775c6f7..aff853ee36 100644 --- a/tests/regression/39-signed-overflows/06-shiftleft.c +++ b/tests/regression/39-signed-overflows/06-shiftleft.c @@ -19,5 +19,8 @@ int main() __goblint_check(r >= 8); __goblint_check(r <= 16); + int regval; + unsigned long bla = (unsigned long )((1 << ((int )regval >> 6)) << 20); //WARN + return 0; } From 8d55024d0580b5a4aec7bd32103d0b3f0ab84d72 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Sun, 19 Nov 2023 19:45:27 +0100 Subject: [PATCH 572/628] Add options to produce warnings only for memory leaks due to `memcleanup` or `memtrack` violations --- src/common/util/options.schema.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 9a6a66ee6b..5923612b5b 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2164,6 +2164,25 @@ "description": "Output messages in deterministic order. Useful for cram testing.", "type": "boolean", "default": false + }, + "memleak": { + "title": "warn.memleak", + "type":"object", + "properties": { + "memcleanup": { + "title": "warn.memleak.memcleanup", + "description": "Enable memory leak warnings only for violations of the SV-COMP \"valid-memcleanup\" category", + "type": "boolean", + "default": false + }, + "memtrack": { + "title": "warn.memleak.memtrack", + "description": "Enable memory leak warnings only for violations of the SV-COMP \"valid-memtrack\" category", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false } }, "additionalProperties": false From 85e6fdbfcba3d42bf35b44f1c41171e958890451 Mon Sep 17 00:00:00 2001 From: oliver Date: Mon, 20 Nov 2023 01:55:30 +0100 Subject: [PATCH 573/628] bump dune dependencies and rebuild goblint.opam --- goblint.opam | 2 +- goblint.opam.locked | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/goblint.opam b/goblint.opam index bf51924626..34912fde26 100644 --- a/goblint.opam +++ b/goblint.opam @@ -19,7 +19,7 @@ homepage: "https://goblint.in.tum.de" doc: "https://goblint.readthedocs.io/en/latest/" bug-reports: "https://github.com/goblint/analyzer/issues" depends: [ - "dune" {>= "3.6"} + "dune" {>= "3.7"} "ocaml" {>= "4.10"} "goblint-cil" {>= "2.0.2"} "batteries" {>= "3.5.0"} diff --git a/goblint.opam.locked b/goblint.opam.locked index 0abe989955..6e15ac8900 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -76,7 +76,7 @@ depends: [ "ocamlfind" {= "1.9.5"} "odoc" {= "2.2.0" & with-doc} "odoc-parser" {= "2.0.0" & with-doc} - "ordering" {= "3.6.1"} + "ordering" {= "3.7.1"} "ounit2" {= "2.2.6" & with-test} "pp" {= "1.1.2"} "ppx_derivers" {= "1.2.1"} @@ -93,7 +93,7 @@ depends: [ "sexplib0" {= "v0.15.1"} "sha" {= "1.15.2"} "stdlib-shims" {= "0.3.0"} - "stdune" {= "3.6.1"} + "stdune" {= "3.7.1"} "stringext" {= "1.6.0"} "topkg" {= "1.0.6"} "tyxml" {= "4.5.0" & with-doc} From ecd48aa318c0720c2f2b8b63a524635170df804e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 10:46:35 +0200 Subject: [PATCH 574/628] Make SV-COMP validation strict --- conf/svcomp24-validate.json | 1 + src/common/util/options.schema.json | 6 ++++++ src/witness/witness.ml | 13 ++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/conf/svcomp24-validate.json b/conf/svcomp24-validate.json index ce11af12f6..2d7e988fdf 100644 --- a/conf/svcomp24-validate.json +++ b/conf/svcomp24-validate.json @@ -114,6 +114,7 @@ }, "yaml": { "enabled": false, + "strict": true, "format-version": "2.0", "entry-types": [ "location_invariant", diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 328b4f277f..0732debcc9 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2487,6 +2487,12 @@ "type": "string", "default": "" }, + "strict": { + "title": "witness.yaml.strict", + "description": "", + "type": "boolean", + "default": false + }, "unassume": { "title": "witness.yaml.unassume", "description": "YAML witness input path", diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 235461c348..9d6a1ebe02 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -665,11 +665,18 @@ struct | Some false -> print_svcomp_result "ERROR (verify)" | _ -> if get_string "witness.yaml.validate" <> "" then ( - if !YamlWitness.cnt_refuted > 0 then + match get_bool "witness.yaml.strict" with + | true when !YamlWitness.cnt_error > 0 -> + print_svcomp_result "ERROR (witness error)" + | true when !YamlWitness.cnt_unsupported > 0 -> + print_svcomp_result "ERROR (witness unsupported)" + | true when !YamlWitness.cnt_disabled > 0 -> + print_svcomp_result "ERROR (witness disabled)" + | _ when !YamlWitness.cnt_refuted > 0 -> print_svcomp_result (Result.to_string (False None)) - else if !YamlWitness.cnt_unconfirmed > 0 then + | _ when !YamlWitness.cnt_unconfirmed > 0 -> print_svcomp_result (Result.to_string Unknown) - else + | _ -> write entrystates ) else From 9d77dec344287d4ad42e723abfa5777dc3d01afc Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 11:59:44 +0200 Subject: [PATCH 575/628] Move abs refine to BaseInvariant --- src/analyses/base.ml | 43 ++++++++--------------------------- src/analyses/baseInvariant.ml | 27 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 4911b0d033..f25f0a9693 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1753,40 +1753,15 @@ struct let branch ctx (exp:exp) (tv:bool) : store = let valu = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in let refine () = - let refine0 = - let res = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp tv in - if M.tracing then M.tracec "branch" "EqualSet result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.EqualSet exp)); - if M.tracing then M.tracec "branch" "CondVars result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.CondVars exp)); - if M.tracing then M.traceu "branch" "Invariant enforced!\n"; - match ctx.ask (Queries.CondVars exp) with - | s when Queries.ES.cardinal s = 1 -> - let e = Queries.ES.choose s in - invariant ctx (Analyses.ask_of_ctx ctx) ctx.global res e tv - | _ -> res - in - (* bodge for abs(...); To be removed once we have a clean solution *) - let refineAbs op absargexp valexp = - let flip op = match op with | Le -> Ge | Lt -> Gt | _ -> failwith "impossible" in - (* e.g. |arg| <= 40 *) - (* arg <= e (arg <= 40) *) - let le = BinOp (op, absargexp, valexp, intType) in - (* arg >= -e (arg >= -40) *) - let gt = BinOp(flip op, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in - let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in - invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv - in - match exp with - | BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> - (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> - refineAbs op (CastE (t, arg)) e - | _ -> refine0) - | BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv -> - (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> - refineAbs op arg e - | _ -> refine0) - | _ -> refine0 + let res = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp tv in + if M.tracing then M.tracec "branch" "EqualSet result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.EqualSet exp)); + if M.tracing then M.tracec "branch" "CondVars result for expression %a is %a\n" d_exp exp Queries.ES.pretty (ctx.ask (Queries.CondVars exp)); + if M.tracing then M.traceu "branch" "Invariant enforced!\n"; + match ctx.ask (Queries.CondVars exp) with + | s when Queries.ES.cardinal s = 1 -> + let e = Queries.ES.choose s in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global res e tv + | _ -> res in if M.tracing then M.traceli "branch" ~subsys:["invariant"] "Evaluating branch for expression %a with value %a\n" d_exp exp VD.pretty valu; (* First we want to see, if we can determine a dead branch: *) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 72e00efbb1..a99e25e7c6 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -821,4 +821,31 @@ struct FD.top_of fk in inv_exp (Float ftv) exp st + + let invariant ctx a gs st exp tv: D.t = + let refine0 = invariant ctx a gs st exp tv in + (* bodge for abs(...); To be removed once we have a clean solution *) + let refineAbs op absargexp valexp = + let flip op = match op with | Le -> Ge | Lt -> Gt | _ -> failwith "impossible" in + (* e.g. |arg| <= 40 *) + (* arg <= e (arg <= 40) *) + let le = BinOp (op, absargexp, valexp, intType) in + (* arg >= -e (arg >= -40) *) + let gt = BinOp(flip op, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in + let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in + invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv + in + match exp with + | BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> + (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> + refineAbs op (CastE (t, arg)) e + | _ -> refine0) + | BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv -> + (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> + refineAbs op arg e + | _ -> refine0) + | _ -> refine0 + end From 0cb1b7e1135fee97db9d4d7da6a90c1bc8261fa5 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 12:04:21 +0200 Subject: [PATCH 576/628] Fix BaseInvariant abs indentation --- src/analyses/baseInvariant.ml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index a99e25e7c6..86ec0d3bf7 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -837,15 +837,15 @@ struct in match exp with | BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> - (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> - refineAbs op (CastE (t, arg)) e - | _ -> refine0) + begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> refineAbs op (CastE (t, arg)) e + | _ -> refine0 + end | BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv -> - (match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> - refineAbs op arg e - | _ -> refine0) + begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with + | `Lifted (Abs arg) -> refineAbs op arg e + | _ -> refine0 + end | _ -> refine0 end From 19190ca63d43aaf14ae462823b3878ce65b25606 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:09:26 +0100 Subject: [PATCH 577/628] remove special cases handled by general case --- src/analyses/base.ml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index f25f0a9693..2a729c685e 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2339,13 +2339,9 @@ struct | None, _ -> ID.top_of ik | Some mx, Some mm when Z.equal mx mm -> ID.top_of ik | _, _ -> - match ID.le xcast (ID.of_int ik Z.zero) with - | d when d = ID.of_int ik Z.zero -> xcast (* x positive *) - | d when d = ID.of_int ik Z.one -> ID.neg xcast (* x negative *) - | _ -> (* both possible *) - let x1 = ID.neg (ID.meet (ID.ending ik Z.zero) xcast) in - let x2 = ID.meet (ID.starting ik Z.zero) xcast in - ID.join x1 x2 + let x1 = ID.neg (ID.meet (ID.ending ik Z.zero) xcast) in + let x2 = ID.meet (ID.starting ik Z.zero) xcast in + ID.join x1 x2 ) | _ -> failwith ("non-integer argument in call to function "^f.vname) end From 6797cbb9ec941646316ffb689a12135bf1282b6a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 12:21:32 +0200 Subject: [PATCH 578/628] Add ana.autotune.activated schema --- src/common/util/options.schema.json | 32 +++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 745aecfb57..2b1e738196 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -542,9 +542,37 @@ "title": "ana.autotune.activated", "description": "Lists of activated tuning options.", "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string", + "enum": [ + "congruence", + "singleThreaded", + "specification", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "loopUnrollHeuristic", + "forceLoopUnrollForFewLoops", + "arrayDomain", + "octagon", + "wideningThresholds", + "memsafetySpecification", + "termination" + ] + }, "default": [ - "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds", "memsafetySpecification" + "congruence", + "singleThreaded", + "specification", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "loopUnrollHeuristic", + "arrayDomain", + "octagon", + "wideningThresholds", + "memsafetySpecification", + "termination" ] } }, From 3af192da0600613de1f789e827d98b87d13c41ef Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 13:10:40 +0200 Subject: [PATCH 579/628] Deactivate mhp and region for single-threaded programs --- src/autoTune.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 346e9d7b6f..d9a866ffc2 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -184,7 +184,7 @@ let enableAnalyses anas = (*escape is also still enabled, because otherwise we get a warning*) (*does not consider dynamic calls!*) -let notNeccessaryThreadAnalyses = ["race"; "deadlock"; "maylocks"; "symb_locks"; "thread"; "threadid"; "threadJoins"; "threadreturn"] +let notNeccessaryThreadAnalyses = ["race"; "deadlock"; "maylocks"; "symb_locks"; "thread"; "threadid"; "threadJoins"; "threadreturn"; "mhp"; "region"] let reduceThreadAnalyses () = let isThreadCreate = function | LibraryDesc.ThreadCreate _ -> true From 0ee71a02f9fe08381c94eb6704bbc42055a778fa Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 13:48:28 +0200 Subject: [PATCH 580/628] Update SV-COMP releasing guide for 2024 --- docs/developer-guide/releasing.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/developer-guide/releasing.md b/docs/developer-guide/releasing.md index 69ffcb2461..fc5f5f68a1 100644 --- a/docs/developer-guide/releasing.md +++ b/docs/developer-guide/releasing.md @@ -97,16 +97,17 @@ This ensures that the environment and the archive have all the correct system libraries. -6. Commit and push the archive to an SV-COMP archives repository branch (but don't open a MR yet): (SV-COMP 2023). -7. Check pushed archive via CoveriTeam-Remote: . +6. Create (or add new version) Zenodo artifact and upload the archive. - 1. Clone coveriteam repository. - 2. Locally modify `actors/goblint.yml` archive location to the raw URL of the pushed archive. - 3. Run Goblint on some sv-benchmarks and properties via CoveriTeam. +7. Open MR with Zenodo version DOI to the [fm-tools](https://gitlab.com/sosy-lab/benchmarking/fm-tools) repository. - This ensures that Goblint runs on SoSy-Lab servers. + ### After all preruns From 5784ffeb5f0e26b4da059a0d762480a0ce999505 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 20 Nov 2023 14:44:56 +0200 Subject: [PATCH 581/628] Update Gobview submodule for dune 3.7.1 lock --- gobview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gobview b/gobview index 42b07f8253..b4467d820f 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit 42b07f825316052ec030370daf0d00ebe28ec092 +Subproject commit b4467d820f28bac578fc0baf7f81393c67f6b82b From 631f4fc69cf667a957a7575f653210a3702135c6 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 20 Nov 2023 16:25:47 +0100 Subject: [PATCH 582/628] Do not set overflow flag on cast. --- src/cdomains/intDomain.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 3bc84ae676..0a98e57a29 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -3410,14 +3410,14 @@ module IntDomTupleImpl = struct | Some(_, {underflow; overflow}) -> not (underflow || overflow) | _ -> false - let check_ov ik intv intv_set = + let check_ov ~cast ik intv intv_set = let no_ov = (no_overflow ik intv) || (no_overflow ik intv_set) in if not no_ov && ( BatOption.is_some intv || BatOption.is_some intv_set) then ( let (_,{underflow=underflow_intv; overflow=overflow_intv}) = match intv with None -> (I2.bot (), {underflow= true; overflow = true}) | Some x -> x in let (_,{underflow=underflow_intv_set; overflow=overflow_intv_set}) = match intv_set with None -> (I5.bot (), {underflow= true; overflow = true}) | Some x -> x in let underflow = underflow_intv && underflow_intv_set in let overflow = overflow_intv && overflow_intv_set in - set_overflow_flag ~cast:false ~underflow ~overflow ik; + set_overflow_flag ~cast ~underflow ~overflow ik; ); no_ov @@ -3426,7 +3426,7 @@ module IntDomTupleImpl = struct let map x = Option.map fst x in let intv = f p2 @@ r.fi2_ovc (module I2) in let intv_set = f p5 @@ r.fi2_ovc (module I5) in - ignore (check_ov ik intv intv_set); + ignore (check_ov ~cast:false ik intv intv_set); map @@ f p1 @@ r.fi2_ovc (module I1), map @@ f p2 @@ r.fi2_ovc (module I2), map @@ f p3 @@ r.fi2_ovc (module I3), map @@ f p4 @@ r.fi2_ovc (module I4), map @@ f p5 @@ r.fi2_ovc (module I5) let create2_ovc ik r x = (* use where values are introduced *) @@ -3607,7 +3607,7 @@ module IntDomTupleImpl = struct let map f ?no_ov = function Some x -> Some (f ?no_ov x) | _ -> None in let intv = map (r.f1_ovc (module I2)) b in let intv_set = map (r.f1_ovc (module I5)) e in - let no_ov = check_ov ik intv intv_set in + let no_ov = check_ov ~cast ik intv intv_set in let no_ov = no_ov || should_ignore_overflow ik in refine ik ( map (fun ?no_ov x -> r.f1_ovc ?no_ov (module I1) x |> fst) a @@ -3617,10 +3617,10 @@ module IntDomTupleImpl = struct , BatOption.map fst intv_set ) (* map2 with overflow check *) - let map2ovc ik r (xa, xb, xc, xd, xe) (ya, yb, yc, yd, ye) = + let map2ovc ?(cast=false) ik r (xa, xb, xc, xd, xe) (ya, yb, yc, yd, ye) = let intv = opt_map2 (r.f2_ovc (module I2)) xb yb in let intv_set = opt_map2 (r.f2_ovc (module I5)) xe ye in - let no_ov = check_ov ik intv intv_set in + let no_ov = check_ov ~cast ik intv intv_set in let no_ov = no_ov || should_ignore_overflow ik in refine ik ( opt_map2 (fun ?no_ov x y -> r.f2_ovc ?no_ov (module I1) x y |> fst) xa ya From 4f7eb52a54b75e01740f065eb4e3eccf783adabb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 20 Nov 2023 16:33:28 +0100 Subject: [PATCH 583/628] Add test case for cast. --- tests/regression/29-svcomp/32-no-ov.c | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/regression/29-svcomp/32-no-ov.c diff --git a/tests/regression/29-svcomp/32-no-ov.c b/tests/regression/29-svcomp/32-no-ov.c new file mode 100644 index 0000000000..0167098c29 --- /dev/null +++ b/tests/regression/29-svcomp/32-no-ov.c @@ -0,0 +1,7 @@ +// PARAM: --enable ana.int.interval --enable ana.sv-comp.enabled --enable ana.sv-comp.functions --set ana.specification "CHECK( init(main()), LTL(G ! overflow) )" + +int main(){ + // This is not an overflow, just implementation defined behavior on a cast + int data = ((int)(rand() & 1 ? (((unsigned)rand()<<30) ^ ((unsigned)rand()<<15) ^ rand()) : -(((unsigned)rand()<<30) ^ ((unsigned)rand()<<15) ^ rand()) - 1)); + return 0; +} \ No newline at end of file From 5a8863089b4526f51f997b58c22bba77427ac4e3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Mon, 20 Nov 2023 16:58:57 +0100 Subject: [PATCH 584/628] Unify naming --- src/cdomains/intDomain.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 5a80d67bfe..fde09a797a 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -610,7 +610,7 @@ module IntervalArith(Ints_t : IntOps.IntOps) = struct let x2y2 = (Ints_t.mul x2 y2) in (min4 x1y1 x1y2 x2y1 x2y2, max4 x1y1 x1y2 x2y1 x2y2) - let shiftleft (x1,x2) (y1,y2) = + let shift_left (x1,x2) (y1,y2) = let y1p = Ints_t.shift_left Ints_t.one y1 in let y2p = Ints_t.shift_left Ints_t.one y2 in mul (x1, x2) (y1p, y2p) @@ -877,7 +877,7 @@ struct match a, minimal b, maximal b with | Some a, Some bl, Some bu when (Ints_t.compare bl Ints_t.zero >= 0) -> (try - let r = IArith.shiftleft a (Ints_t.to_int bl, Ints_t.to_int bu) in + let r = IArith.shift_left a (Ints_t.to_int bl, Ints_t.to_int bu) in norm ik @@ Some r with Z.Overflow -> (top_of ik,{underflow=false; overflow=true})) | _ -> (top_of ik,{underflow=true; overflow=true}) From c9be89e68cd01a189f336f350cf8cae12c505b43 Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:40:40 +0100 Subject: [PATCH 585/628] add support for labs and llabs --- src/analyses/base.ml | 2 +- src/analyses/baseInvariant.ml | 4 ++-- src/analyses/libraryDesc.ml | 4 ++-- src/analyses/libraryFunctions.ml | 4 +++- .../regression/39-signed-overflows/08-labs.c | 22 +++++++++++++++++++ .../39-signed-overflows/09-labs-sqrt.c | 10 +++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/regression/39-signed-overflows/08-labs.c create mode 100644 tests/regression/39-signed-overflows/09-labs-sqrt.c diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 2a729c685e..84be8c7a19 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2375,7 +2375,7 @@ struct | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) | Sqrt (fk, x) -> Float (apply_unary fk FD.sqrt x) - | Abs x -> Int (ID.cast_to IInt (apply_abs IInt x)) + | Abs (ik, x) -> Int (ID.cast_to ik (apply_abs ik x)) end in begin match lv with diff --git a/src/analyses/baseInvariant.ml b/src/analyses/baseInvariant.ml index 86ec0d3bf7..f391231628 100644 --- a/src/analyses/baseInvariant.ml +++ b/src/analyses/baseInvariant.ml @@ -838,12 +838,12 @@ struct match exp with | BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv -> begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> refineAbs op (CastE (t, arg)) e + | `Lifted (Abs (ik, arg)) -> refineAbs op (CastE (t, arg)) e | _ -> refine0 end | BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv -> begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with - | `Lifted (Abs arg) -> refineAbs op arg e + | `Lifted (Abs (ik, arg)) -> refineAbs op arg e | _ -> refine0 end | _ -> refine0 diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 8cd3dfa1ba..45887b9c6b 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -27,7 +27,7 @@ type math = | Islessequal of (Basetype.CilExp.t * Basetype.CilExp.t) | Islessgreater of (Basetype.CilExp.t * Basetype.CilExp.t) | Isunordered of (Basetype.CilExp.t * Basetype.CilExp.t) - | Abs of Basetype.CilExp.t + | Abs of (CilType.Ikind.t * Basetype.CilExp.t) | Ceil of (CilType.Fkind.t * Basetype.CilExp.t) | Floor of (CilType.Fkind.t * Basetype.CilExp.t) | Fabs of (CilType.Fkind.t * Basetype.CilExp.t) @@ -160,7 +160,7 @@ module MathPrintable = struct | Islessequal (exp1, exp2) -> Pretty.dprintf "isLessEqual(%a, %a)" d_exp exp1 d_exp exp2 | Islessgreater (exp1, exp2) -> Pretty.dprintf "isLessGreater(%a, %a)" d_exp exp1 d_exp exp2 | Isunordered (exp1, exp2) -> Pretty.dprintf "isUnordered(%a, %a)" d_exp exp1 d_exp exp2 - | Abs exp -> Pretty.dprintf "abs(%a)" d_exp exp + | Abs (ik, exp) -> Pretty.dprintf "(%a )abs(%a)" d_ikind ik d_exp exp | Ceil (fk, exp) -> Pretty.dprintf "(%a )ceil(%a)" d_fkind fk d_exp exp | Floor (fk, exp) -> Pretty.dprintf "(%a )floor(%a)" d_fkind fk d_exp exp | Fabs (fk, exp) -> Pretty.dprintf "(%a )fabs(%a)" d_fkind fk d_exp exp diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index ae33f57f70..838d1817a9 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -130,7 +130,9 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("wcstombs", unknown ~attrs:[ThreadUnsafe] [drop "dst" [w]; drop "src" [r]; drop "size" []]); ("wcsrtombs", unknown ~attrs:[ThreadUnsafe] [drop "dst" [w]; drop "src" [r_deep; w]; drop "size" []; drop "ps" [r_deep; w_deep]]); ("mbstowcs", unknown [drop "dest" [w]; drop "src" [r]; drop "n" []]); - ("abs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs j) }); + ("abs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (IInt, j)) }); + ("labs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (ILong, j)) }); + ("llabs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (ILongLong, j)) }); ("localtime_r", unknown [drop "timep" [r]; drop "result" [w]]); ("strpbrk", unknown [drop "s" [r]; drop "accept" [r]]); ("_setjmp", special [__ "env" [w]] @@ fun env -> Setjmp { env }); (* only has one underscore *) diff --git a/tests/regression/39-signed-overflows/08-labs.c b/tests/regression/39-signed-overflows/08-labs.c new file mode 100644 index 0000000000..a9c6773d11 --- /dev/null +++ b/tests/regression/39-signed-overflows/08-labs.c @@ -0,0 +1,22 @@ +//PARAM: --enable ana.int.interval --set ana.activated[+] tmpSpecial +#include +int main() { + long data; + if (data > (-0xffffffff - 1)) + { + if (labs(data) < 100) + { + __goblint_check(data < 100); + __goblint_check(-100 < data); + int result = data * data; //NOWARN + } + + if(labs(data) <= 100) + { + __goblint_check(data <= 100); + __goblint_check(-100 <= data); + int result = data * data; //NOWARN + } + } + return 8; +} diff --git a/tests/regression/39-signed-overflows/09-labs-sqrt.c b/tests/regression/39-signed-overflows/09-labs-sqrt.c new file mode 100644 index 0000000000..3a4b20a82b --- /dev/null +++ b/tests/regression/39-signed-overflows/09-labs-sqrt.c @@ -0,0 +1,10 @@ +//PARAM: --enable ana.int.interval --enable ana.float.interval --set ana.activated[+] tmpSpecial +#include +int main() { + int data; + if (data > (-0x7fffffff - 1) && llabs(data) < (long)sqrt((double)0x7fffffff)) + { + int result = data * data; //NOWARN + } + return 8; +} From 75b3b83e1500f515ca6f3c4fecb3fe4908507fca Mon Sep 17 00:00:00 2001 From: stilscher <66023521+stilscher@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:19:07 +0100 Subject: [PATCH 586/628] add autotuner for math functions (activates tmpSpecial and float domain) --- src/autoTune.ml | 14 ++++++++++++++ src/common/util/options.schema.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 7ddc1aee43..77d91f9652 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -458,6 +458,17 @@ let wideningOption factors file = print_endline "Enabled widening thresholds"; } +let activateTmpSpecialAnalysis () = + let isMathFun = function + | LibraryDesc.Math _ -> true + | _ -> false + in + let hasMathFunctions = hasFunction isMathFun in + if hasMathFunctions then ( + print_endline @@ "math function -> enabling tmpSpecial analysis and floating-point domain"; + enableAnalyses ["tmpSpecial"]; + set_bool "ana.float.interval" true; + ) let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in @@ -518,6 +529,9 @@ let chooseConfig file = if isActivated "arrayDomain" then selectArrayDomains file; + if isActivated "tmpSpecialAnalysis" then + activateTmpSpecialAnalysis (); + let options = [] in let options = if isActivated "congruence" then (congruenceOption factors file)::options else options in let options = if isActivated "octagon" then (apronOctagonOption factors file)::options else options in diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 4e282b19a4..b392f56cd6 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -544,7 +544,7 @@ "type": "array", "items": { "type": "string" }, "default": [ - "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds", "memsafetySpecification" + "congruence", "singleThreaded", "specification", "mallocWrappers", "noRecursiveIntervals", "enums", "loopUnrollHeuristic", "arrayDomain", "octagon", "wideningThresholds", "memsafetySpecification", "tmpSpecialAnalysis" ] } }, From 464cdd35d3fb7b3358e9be0902035be0358511ea Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 09:01:33 +0100 Subject: [PATCH 587/628] Add cram test for sv-comp no-ov verdict. --- tests/regression/29-svcomp/32-no-ov.t | 16 ++++++++++++++++ tests/regression/29-svcomp/dune | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 tests/regression/29-svcomp/32-no-ov.t create mode 100644 tests/regression/29-svcomp/dune diff --git a/tests/regression/29-svcomp/32-no-ov.t b/tests/regression/29-svcomp/32-no-ov.t new file mode 100644 index 0000000000..92e53a914c --- /dev/null +++ b/tests/regression/29-svcomp/32-no-ov.t @@ -0,0 +1,16 @@ + $ goblint --enable ana.int.interval --enable ana.sv-comp.enabled --enable ana.sv-comp.functions --set ana.specification "CHECK( init(main()), LTL(G ! overflow) )" 32-no-ov.c + SV-COMP specification: CHECK( init(main()), LTL(G ! overflow) ) + [Warning][Integer > Overflow][CWE-190][CWE-191] Unsigned integer overflow and underflow (32-no-ov.c:5:6-5:159) + [Warning][Integer > Overflow][CWE-190][CWE-191] Unsigned integer overflow and underflow (32-no-ov.c:5:6-5:159) + [Warning][Integer > Overflow][CWE-191] Unsigned integer underflow (32-no-ov.c:5:6-5:159) + [Warning][Integer > Overflow][CWE-190] Signed integer overflow (32-no-ov.c:5:6-5:159) + [Info][Deadcode] Logical lines of code (LLoC) summary: + live: 3 + dead: 0 + total lines: 3 + SV-COMP result: true + [Info][Race] Memory locations race summary: + safe: 1 + vulnerable: 0 + unsafe: 0 + total memory locations: 1 diff --git a/tests/regression/29-svcomp/dune b/tests/regression/29-svcomp/dune new file mode 100644 index 0000000000..23c0dd3290 --- /dev/null +++ b/tests/regression/29-svcomp/dune @@ -0,0 +1,2 @@ +(cram + (deps (glob_files *.c))) From 8b7994869c98119e50e8d19f857baccad7194628 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 21 Nov 2023 11:21:46 +0200 Subject: [PATCH 588/628] Fix invariant_set elements schema in YAML witnesses --- src/witness/yamlWitnessType.ml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/witness/yamlWitnessType.ml b/src/witness/yamlWitnessType.ml index f9bcf3235f..de9fa151d8 100644 --- a/src/witness/yamlWitnessType.ml +++ b/src/witness/yamlWitnessType.ml @@ -311,13 +311,16 @@ struct } let to_yaml {invariant_type} = - `O ([ - ("type", `String (InvariantType.invariant_type invariant_type)); - ] @ InvariantType.to_yaml' invariant_type) + `O [ + ("invariant", `O ([ + ("type", `String (InvariantType.invariant_type invariant_type)); + ] @ InvariantType.to_yaml' invariant_type) + ) + ] let of_yaml y = let open GobYaml in - let+ invariant_type = y |> InvariantType.of_yaml in + let+ invariant_type = y |> find "invariant" >>= InvariantType.of_yaml in {invariant_type} end From ca61360dd19e18bba2ddeba89c3f4046cf4764ad Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Nov 2023 10:21:49 +0100 Subject: [PATCH 589/628] Add example where better privatization helps --- ...alid-memcleanup-multi-threaded-betterpiv.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c diff --git a/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c new file mode 100644 index 0000000000..c701461cb5 --- /dev/null +++ b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c @@ -0,0 +1,33 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.base.privatization mutex-meet-tid --set ana.path_sens[+] threadflag +#include +#include + +int *g; +int *m1; +int *m2; + +void *f1(void *arg) { + m1 = malloc(sizeof(int)); + // Thread t1 leaks m1 here + pthread_exit(NULL); //WARN +} + +void *f2(void *arg) { + m2 = malloc(sizeof(int)); + free(m2); // No leak for thread t2, since it calls free before exiting + pthread_exit(NULL); //NOWARN +} + +int main(int argc, char const *argv[]) { + g = malloc(sizeof(int)); + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + free(g); + + // main thread is not leaking anything + return 0; //NOWARN +} From 746014d9f9610afb4750c60fb50770a5d6f9cfb9 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 12:01:35 +0100 Subject: [PATCH 590/628] Extend test case. --- tests/regression/39-signed-overflows/06-shiftleft.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/regression/39-signed-overflows/06-shiftleft.c b/tests/regression/39-signed-overflows/06-shiftleft.c index aff853ee36..a8cb83381c 100644 --- a/tests/regression/39-signed-overflows/06-shiftleft.c +++ b/tests/regression/39-signed-overflows/06-shiftleft.c @@ -1,5 +1,6 @@ // PARAM: --enable ana.int.interval #include +#include int main() { int r; @@ -19,8 +20,12 @@ int main() __goblint_check(r >= 8); __goblint_check(r <= 16); - int regval; - unsigned long bla = (unsigned long )((1 << ((int )regval >> 6)) << 20); //WARN + int regval = INT_MAX; + int shift = ((int )regval >> 6); //NOWARN + int blub = 1 << shift; //WARN + + int regval2; + unsigned long bla = (unsigned long )((1 << ((int )regval2 >> 6)) << 20); //WARN return 0; } From 4e330e49d44226eaa1fb77d22f767d6af162c01c Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 12:03:12 +0100 Subject: [PATCH 591/628] Remove unnecessary cast and parantheses. --- tests/regression/39-signed-overflows/06-shiftleft.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/39-signed-overflows/06-shiftleft.c b/tests/regression/39-signed-overflows/06-shiftleft.c index a8cb83381c..7e790306ca 100644 --- a/tests/regression/39-signed-overflows/06-shiftleft.c +++ b/tests/regression/39-signed-overflows/06-shiftleft.c @@ -21,7 +21,7 @@ int main() __goblint_check(r <= 16); int regval = INT_MAX; - int shift = ((int )regval >> 6); //NOWARN + int shift = regval >> 6; //NOWARN int blub = 1 << shift; //WARN int regval2; From f6c9a52fb5c9fae1564ee038fd1c8ef374fa0304 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 12:30:35 +0100 Subject: [PATCH 592/628] Add tmpSpecialAnalysis to ana.autotune.activated in svcomp.json. --- conf/svcomp.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 73f99500b9..c915620987 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -71,7 +71,8 @@ "octagon", "wideningThresholds", "loopUnrollHeuristic", - "memsafetySpecification" + "memsafetySpecification", + "tmpSpecialAnalysis" ] } }, From ed90e61acff66fa96de9816d27951a65a30169a8 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Nov 2023 15:56:00 +0100 Subject: [PATCH 593/628] Fix `BlobSize` for calloc --- src/analyses/base.ml | 13 +++++++++++-- src/analyses/memOutOfBounds.ml | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 84be8c7a19..5b9a00313e 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1139,6 +1139,9 @@ struct (* interpreter end *) + let is_not_alloc_var ctx v = + not (ctx.ask (Queries.IsAllocVar v)) + let is_not_heap_alloc_var ctx v = let is_alloc = ctx.ask (Queries.IsAllocVar v) in not is_alloc || (is_alloc && not (ctx.ask (Queries.IsHeapVar v))) @@ -1277,7 +1280,7 @@ struct (* If there's a non-heap var or an offset in the lval set, we answer with bottom *) (* If we're asking for the BlobSize from the base address, then don't check for offsets => we want to avoid getting bot *) if AD.exists (function - | Addr (v,o) -> is_not_heap_alloc_var ctx v || (if not from_base_addr then o <> `NoOffset else false) + | Addr (v,o) -> is_not_alloc_var ctx v || (if not from_base_addr then o <> `NoOffset else false) | _ -> false) a then Queries.Result.bot q else ( @@ -1289,9 +1292,15 @@ struct else a in - let r = get ~full:true (Analyses.ask_of_ctx ctx) ctx.global ctx.local a None in + let r = get ~full:true (Analyses.ask_of_ctx ctx) ctx.global ctx.local a None in (* ignore @@ printf "BlobSize %a = %a\n" d_plainexp e VD.pretty r; *) (match r with + | Array a -> + (* unroll into array for Calloc calls *) + (match ValueDomain.CArrays.get (Queries.to_value_domain_ask (Analyses.ask_of_ctx ctx)) a (None, (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero)) with + | Blob (_,s,_) -> `Lifted s + | _ -> Queries.Result.top q + ) | Blob (_,s,_) -> `Lifted s | _ -> Queries.Result.top q) ) diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index fc60352298..9dccf77ff9 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -69,17 +69,17 @@ struct in host_contains_a_ptr host || offset_contains_a_ptr offset - let points_to_heap_only ctx ptr = + let points_to_alloc_only ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with | a when not (Queries.AD.is_top a)-> Queries.AD.for_all (function - | Addr (v, o) -> ctx.ask (Queries.IsHeapVar v) + | Addr (v, o) -> ctx.ask (Queries.IsAllocVar v) | _ -> false ) a | _ -> false let get_size_of_ptr_target ctx ptr = - if points_to_heap_only ctx ptr then + if points_to_alloc_only ctx ptr then (* Ask for BlobSize from the base address (the second component being set to true) in order to avoid BlobSize giving us bot *) ctx.ask (Queries.BlobSize {exp = ptr; base_address = true}) else From 9c808c98eb55baf8e0f5b4839ca5cd99ae68747b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Tue, 21 Nov 2023 17:22:04 +0200 Subject: [PATCH 594/628] Adapt cram test from #1258 to #1252 --- tests/regression/29-svcomp/32-no-ov.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/29-svcomp/32-no-ov.t b/tests/regression/29-svcomp/32-no-ov.t index 92e53a914c..85eb90c185 100644 --- a/tests/regression/29-svcomp/32-no-ov.t +++ b/tests/regression/29-svcomp/32-no-ov.t @@ -1,7 +1,7 @@ $ goblint --enable ana.int.interval --enable ana.sv-comp.enabled --enable ana.sv-comp.functions --set ana.specification "CHECK( init(main()), LTL(G ! overflow) )" 32-no-ov.c SV-COMP specification: CHECK( init(main()), LTL(G ! overflow) ) - [Warning][Integer > Overflow][CWE-190][CWE-191] Unsigned integer overflow and underflow (32-no-ov.c:5:6-5:159) - [Warning][Integer > Overflow][CWE-190][CWE-191] Unsigned integer overflow and underflow (32-no-ov.c:5:6-5:159) + [Warning][Integer > Overflow][CWE-190] Unsigned integer overflow (32-no-ov.c:5:6-5:159) + [Warning][Integer > Overflow][CWE-190] Unsigned integer overflow (32-no-ov.c:5:6-5:159) [Warning][Integer > Overflow][CWE-191] Unsigned integer underflow (32-no-ov.c:5:6-5:159) [Warning][Integer > Overflow][CWE-190] Signed integer overflow (32-no-ov.c:5:6-5:159) [Info][Deadcode] Logical lines of code (LLoC) summary: From 2cc915fe1757fcd032d17b8c017f052729430d21 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 17:16:47 +0100 Subject: [PATCH 595/628] Check at end of main thread that the program is certainly single-threaded. If other threads are not joined, they may be killed by the main thread returning. This will possibly leak memory. --- src/analyses/memLeak.ml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 8d83bcee83..4d37992a21 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -22,10 +22,16 @@ struct let context _ d = d + let must_be_single_threaded ~since_start ctx = + ctx.ask (Queries.MustBeSingleThreaded { since_start }) + + let was_malloc_called ctx = + ctx.global () + (* HELPER FUNCTIONS *) let warn_for_multi_threaded_due_to_abort ctx = - let malloc_called = ctx.global () in - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) && malloc_called then ( + let malloc_called = was_malloc_called ctx in + if not (must_be_single_threaded ctx ~since_start:true) && malloc_called then ( set_mem_safety_flag InvalidMemTrack; set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program aborted while running in multi-threaded mode. A memory leak might occur" @@ -56,11 +62,18 @@ struct let return ctx (exp:exp option) (f:fundec) : D.t = (* Check for a valid-memcleanup and memtrack violation in a multi-threaded setting *) (* The check for multi-threadedness is to ensure that valid-memtrack and valid-memclenaup are treated separately for single-threaded programs *) - if (ctx.ask (Queries.MayBeThreadReturn) && not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true }))) then ( - warn_for_thread_return_or_exit ctx true + if (ctx.ask (Queries.MayBeThreadReturn) && not (must_be_single_threaded ctx ~since_start:true)) then ( + warn_for_thread_return_or_exit ctx true ); (* Returning from "main" is one possible program exit => need to check for memory leaks *) - if f.svar.vname = "main" then check_for_mem_leak ctx; + if f.svar.vname = "main" then ( + check_for_mem_leak ctx; + if not (must_be_single_threaded ctx ~since_start:false) && was_malloc_called ctx then begin + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Possible memory leak: Memory was allocated in a multithreaded program, but not all threads are joined." + end + ); ctx.local let special ctx (lval:lval option) (f:varinfo) (arglist:exp list) : D.t = From 45ec8a663791d3675ca05ac68355ce1b1ea2c8c1 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 17:18:30 +0100 Subject: [PATCH 596/628] Add test case for memory leaking from a thead that is not joined, add thread_joins to other test cases. --- .../08-invalid-memcleanup-multi-threaded.c | 6 +++++- ...9-invalid-memcleanup-multi-threaded-abort.c | 7 +++++-- ...valid-memcleanup-multi-threaded-betterpiv.c | 5 ++++- .../76-memleak/15-mem-leak-not-joined-thread.c | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/regression/76-memleak/15-mem-leak-not-joined-thread.c diff --git a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c index 513a36db95..65e6e4e766 100644 --- a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c +++ b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid #include #include @@ -7,6 +7,7 @@ int *m1; void *f1(void *arg) { m1 = malloc(sizeof(int)); + free(m1); // Thread t1 leaks m1 here pthread_exit(NULL); //WARN } @@ -28,6 +29,9 @@ int main(int argc, char const *argv[]) { free(g); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + // main thread is not leaking anything return 0; //NOWARN } diff --git a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c index 977510b9bb..b991433f4d 100644 --- a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c +++ b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid #include #include @@ -25,9 +25,12 @@ int main(int argc, char const *argv[]) { pthread_t t2; pthread_create(&t2, NULL, f2, NULL); - + free(g); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + // main thread is not leaking anything return 0; //NOWARN } diff --git a/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c index c701461cb5..7ad9194d6e 100644 --- a/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c +++ b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.base.privatization mutex-meet-tid --set ana.path_sens[+] threadflag +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.base.privatization mutex-meet-tid --set ana.path_sens[+] threadflag --set ana.activated[+] thread --set ana.activated[+] threadid #include #include @@ -28,6 +28,9 @@ int main(int argc, char const *argv[]) { free(g); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + // main thread is not leaking anything return 0; //NOWARN } diff --git a/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c new file mode 100644 index 0000000000..c60809a9f4 --- /dev/null +++ b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c @@ -0,0 +1,18 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid +#include +#include + +int *m1; + +void *f1(void *arg) { + m1 = malloc(sizeof(int)); + while (1); +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + // memory from thread f1 which was not joined into main, is not freed + return 0; //WARN +} \ No newline at end of file From 56c4d620be0c7e3a3d2deb92197d3d161a850445 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 17:40:44 +0100 Subject: [PATCH 597/628] Add test case with pthread_exit called in main, remove threadid analysis from params as it is not needed. --- .../08-invalid-memcleanup-multi-threaded.c | 4 ++-- ...-invalid-memcleanup-multi-threaded-abort.c | 3 +-- ...alid-memcleanup-multi-threaded-betterpiv.c | 2 +- .../15-mem-leak-not-joined-thread.c | 2 +- .../16-no-mem-leak-thread-exit-main.c | 23 +++++++++++++++++++ 5 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c diff --git a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c index 65e6e4e766..89dc7a3416 100644 --- a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c +++ b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread #include #include @@ -26,7 +26,7 @@ int main(int argc, char const *argv[]) { pthread_t t2; pthread_create(&t2, NULL, f2, NULL); - + free(g); pthread_join(t1, NULL); diff --git a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c index b991433f4d..eaba1e91b5 100644 --- a/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c +++ b/tests/regression/76-memleak/09-invalid-memcleanup-multi-threaded-abort.c @@ -1,5 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid -#include +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread #include int *g; diff --git a/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c index 7ad9194d6e..9f636ab587 100644 --- a/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c +++ b/tests/regression/76-memleak/14-invalid-memcleanup-multi-threaded-betterpiv.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.base.privatization mutex-meet-tid --set ana.path_sens[+] threadflag --set ana.activated[+] thread --set ana.activated[+] threadid +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.base.privatization mutex-meet-tid --set ana.path_sens[+] threadflag --set ana.activated[+] thread #include #include diff --git a/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c index c60809a9f4..21c1992fc3 100644 --- a/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c +++ b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c @@ -1,4 +1,4 @@ -//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread --set ana.activated[+] threadid +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread #include #include diff --git a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c new file mode 100644 index 0000000000..5fb89113d2 --- /dev/null +++ b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c @@ -0,0 +1,23 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread +#include +#include + +int *m1; + +void *f1(void *arg) { + m1 = malloc(sizeof(int)); + while (1); +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_exit(NULL); + + pthread_join(t1, NULL); + + // A pthread_join called in main will wait for other threads to finish + // Therefore, no memory leak here + return 0; // NOWARN +} \ No newline at end of file From 2fef812ff9a11bebb6ac4b78ca010fde6bbfeea9 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 17:57:07 +0100 Subject: [PATCH 598/628] Add testcases for thread return and pthread_exit in thread different from main. --- .../15-mem-leak-not-joined-thread.c | 1 + .../16-no-mem-leak-thread-exit-main.c | 3 +-- .../76-memleak/17-mem-leak-thread-return.c | 26 ++++++++++++++++++ .../76-memleak/18-mem-leak-thread-exit.c | 27 +++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/regression/76-memleak/17-mem-leak-thread-return.c create mode 100644 tests/regression/76-memleak/18-mem-leak-thread-exit.c diff --git a/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c index 21c1992fc3..15f249ffe1 100644 --- a/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c +++ b/tests/regression/76-memleak/15-mem-leak-not-joined-thread.c @@ -7,6 +7,7 @@ int *m1; void *f1(void *arg) { m1 = malloc(sizeof(int)); while (1); + return NULL; } int main(int argc, char const *argv[]) { diff --git a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c index 5fb89113d2..663ea26663 100644 --- a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c +++ b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c @@ -7,6 +7,7 @@ int *m1; void *f1(void *arg) { m1 = malloc(sizeof(int)); while (1); + return NULL; } int main(int argc, char const *argv[]) { @@ -15,8 +16,6 @@ int main(int argc, char const *argv[]) { pthread_exit(NULL); - pthread_join(t1, NULL); - // A pthread_join called in main will wait for other threads to finish // Therefore, no memory leak here return 0; // NOWARN diff --git a/tests/regression/76-memleak/17-mem-leak-thread-return.c b/tests/regression/76-memleak/17-mem-leak-thread-return.c new file mode 100644 index 0000000000..bec64ca22f --- /dev/null +++ b/tests/regression/76-memleak/17-mem-leak-thread-return.c @@ -0,0 +1,26 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread +#include +#include + +int *m1; + +void *f2(void *arg) { + m1 = malloc(sizeof(int)); + while (1); + return NULL; +} + +void *f1(void *arg) { + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + return NULL; +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + pthread_join(t1, NULL); + + return 0; // WARN +} \ No newline at end of file diff --git a/tests/regression/76-memleak/18-mem-leak-thread-exit.c b/tests/regression/76-memleak/18-mem-leak-thread-exit.c new file mode 100644 index 0000000000..e98ae3f346 --- /dev/null +++ b/tests/regression/76-memleak/18-mem-leak-thread-exit.c @@ -0,0 +1,27 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread +#include +#include + +int *m1; + +void *f2(void *arg) { + m1 = malloc(sizeof(int)); + while (1); + return NULL; +} + +void *f1(void *arg) { + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_exit(NULL); + return NULL; +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + pthread_join(t1, NULL); + + return 0; // WARN +} \ No newline at end of file From d1d85b3496228a0979e6f21039409fd3473ef08a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Nov 2023 18:01:33 +0100 Subject: [PATCH 599/628] Add test --- tests/regression/74-invalid_deref/30-calloc.c | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/regression/74-invalid_deref/30-calloc.c diff --git a/tests/regression/74-invalid_deref/30-calloc.c b/tests/regression/74-invalid_deref/30-calloc.c new file mode 100644 index 0000000000..624e9c212d --- /dev/null +++ b/tests/regression/74-invalid_deref/30-calloc.c @@ -0,0 +1,9 @@ +//PARAM: --set ana.activated[+] useAfterFree --set ana.activated[+] threadJoins --set ana.activated[+] memOutOfBounds --enable ana.int.interval --set ana.base.arrays.domain partitioned +#include +#include + +int main(int argc, char **argv) +{ + int* ptrCalloc = calloc(100UL,8UL); + *ptrCalloc = 8; //NOWARN +} From 645b03cfa678acbf3fdc585d4ee0a7d71e8b9688 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 21 Nov 2023 20:31:00 +0100 Subject: [PATCH 600/628] ThreadAnalysis: Handle pthread_exit like return from thread. --- src/analyses/threadAnalysis.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index 0264f4b700..d9140dbb37 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -22,7 +22,7 @@ struct module P = IdentityP (D) (* transfer functions *) - let return ctx (exp:exp option) (f:fundec) : D.t = + let return ctx (exp:exp option) _ : D.t = let tid = ThreadId.get_current (Analyses.ask_of_ctx ctx) in begin match tid with | `Lifted tid -> ctx.sideg tid (false, TS.bot (), not (D.is_empty ctx.local)) @@ -64,6 +64,8 @@ struct | [t] -> join_thread ctx.local t (* single thread *) | _ -> ctx.local (* if several possible threads are may-joined, none are must-joined *) | exception SetDomain.Unsupported _ -> ctx.local) + | ThreadExit { ret_val } -> + return ctx (Some ret_val) () | _ -> ctx.local let query ctx (type a) (q: a Queries.t): a Queries.result = From 9153eb3becd5904b99aa8250e50b2cd22f74a128 Mon Sep 17 00:00:00 2001 From: Stanimir Bozhilov Date: Tue, 21 Nov 2023 21:04:04 +0100 Subject: [PATCH 601/628] Use `AD.fold` instead of `List.fold_left` --- src/analyses/memLeak.ml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 3079faae1f..f26157fdd0 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -117,12 +117,14 @@ struct match ValueDomain.Structs.get s field with | Queries.VD.Address a -> let reachable_from_addr_set = - List.fold_left (fun acc_addr addr -> + Queries.AD.fold (fun addr acc_addr -> match addr with - | Queries.AD.Addr.Addr (v, _) -> (v :: get_reachable_mem_from_str_ptr_globals [v] ctx) @ acc_addr + | Queries.AD.Addr.Addr (v, _) -> + let reachable_from_v = Queries.AD.of_list (List.map (fun v -> Queries.AD.Addr.Addr (v, `NoOffset)) (get_reachable_mem_from_str_ptr_globals [v] ctx)) in + Queries.AD.join (Queries.AD.add addr reachable_from_v) acc_addr | _ -> acc_addr - ) [] (Queries.AD.elements a) - in reachable_from_addr_set @ acc_field + ) a (Queries.AD.empty ()) + in (Queries.AD.to_var_may reachable_from_addr_set) @ acc_field | _ -> acc_field ) [] fields in From c6cb63e48a665e566531213bbc02b4a568f2bf79 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 22 Nov 2023 10:53:22 +0100 Subject: [PATCH 602/628] Update tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c Co-authored-by: Simmo Saan --- tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c index 663ea26663..77dd299896 100644 --- a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c +++ b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c @@ -16,7 +16,7 @@ int main(int argc, char const *argv[]) { pthread_exit(NULL); - // A pthread_join called in main will wait for other threads to finish + // A pthread_exit called in main will wait for other threads to finish // Therefore, no memory leak here return 0; // NOWARN } \ No newline at end of file From f12a39216068c87cc0785f1ed13f9573b8f2c08e Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 22 Nov 2023 11:02:01 +0100 Subject: [PATCH 603/628] Remove call to free. --- .../regression/76-memleak/08-invalid-memcleanup-multi-threaded.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c index 89dc7a3416..038801f219 100644 --- a/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c +++ b/tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c @@ -7,7 +7,6 @@ int *m1; void *f1(void *arg) { m1 = malloc(sizeof(int)); - free(m1); // Thread t1 leaks m1 here pthread_exit(NULL); //WARN } From be9171b2bf6a541358c702a4a62e31a79f3be676 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 22 Nov 2023 11:04:44 +0100 Subject: [PATCH 604/628] Add annotation of nowarn next to pthread_exit. --- .../regression/76-memleak/16-no-mem-leak-thread-exit-main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c index 77dd299896..f7340d1d4f 100644 --- a/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c +++ b/tests/regression/76-memleak/16-no-mem-leak-thread-exit-main.c @@ -14,9 +14,9 @@ int main(int argc, char const *argv[]) { pthread_t t1; pthread_create(&t1, NULL, f1, NULL); - pthread_exit(NULL); - // A pthread_exit called in main will wait for other threads to finish // Therefore, no memory leak here - return 0; // NOWARN + pthread_exit(NULL); // NOWARN + + return 0; // NOWARN (unreachable) } \ No newline at end of file From 585a65decbf38ddfdc66ce3c544547b47877b274 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 22 Nov 2023 11:13:04 +0100 Subject: [PATCH 605/628] Check in TheadAnalysis.return whether the return is actually a threadreturn before side-effecting. --- src/analyses/threadAnalysis.ml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/analyses/threadAnalysis.ml b/src/analyses/threadAnalysis.ml index d9140dbb37..01c5dd87fa 100644 --- a/src/analyses/threadAnalysis.ml +++ b/src/analyses/threadAnalysis.ml @@ -22,12 +22,15 @@ struct module P = IdentityP (D) (* transfer functions *) - let return ctx (exp:exp option) _ : D.t = + let handle_thread_return ctx (exp: exp option) = let tid = ThreadId.get_current (Analyses.ask_of_ctx ctx) in - begin match tid with + match tid with | `Lifted tid -> ctx.sideg tid (false, TS.bot (), not (D.is_empty ctx.local)) | _ -> () - end; + + let return ctx (exp:exp option) _ : D.t = + if ctx.ask Queries.MayBeThreadReturn then + handle_thread_return ctx exp; ctx.local let rec is_not_unique ctx tid = @@ -65,7 +68,8 @@ struct | _ -> ctx.local (* if several possible threads are may-joined, none are must-joined *) | exception SetDomain.Unsupported _ -> ctx.local) | ThreadExit { ret_val } -> - return ctx (Some ret_val) () + handle_thread_return ctx (Some ret_val); + ctx.local | _ -> ctx.local let query ctx (type a) (q: a Queries.t): a Queries.result = From bc7694b68b599662a11cafc0c75c259cafa68a0d Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 22 Nov 2023 11:27:04 +0100 Subject: [PATCH 606/628] Add test case that checking that analysis distinguishes between thread returns and normal returns of a thread. --- .../76-memleak/19-no-mem-leak-return.c | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/regression/76-memleak/19-no-mem-leak-return.c diff --git a/tests/regression/76-memleak/19-no-mem-leak-return.c b/tests/regression/76-memleak/19-no-mem-leak-return.c new file mode 100644 index 0000000000..70e0c66216 --- /dev/null +++ b/tests/regression/76-memleak/19-no-mem-leak-return.c @@ -0,0 +1,32 @@ +//PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread +#include +#include + + +void *f2(void *arg) { + int* m1 = malloc(sizeof(int)); + free(m1); + return NULL; +} + +// We check here that the analysis can distinguish between thread returns and normal returns + +void startf2(pthread_t* t){ + pthread_create(t, NULL, f2, NULL); + return; //NOWARN +} + +void *f1(void *arg) { + pthread_t t2; + startf2(&t2); + pthread_join(t2, NULL); + return NULL; // NOWARN +} + +int main(int argc, char const *argv[]) { + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + pthread_join(t1, NULL); + + return 0; // NOWARN +} \ No newline at end of file From 666795faca6dd5a20e01c78daefde8efc7fbe1de Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 22 Nov 2023 11:50:31 +0100 Subject: [PATCH 607/628] MemLeak: Do not consider unions --- src/analyses/memLeak.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index f26157fdd0..c7a044f8a6 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -27,8 +27,8 @@ struct get_global_vars () |> List.filter (fun v -> match unrollType v.vtype with - | TPtr (TComp _, _) - | TPtr ((TNamed ({ttype = TComp _; _}, _)), _) -> true + | TPtr (TComp (ci,_), _) + | TPtr ((TNamed ({ttype = TComp (ci, _); _}, _)), _) -> ci.cstruct | TComp (_, _) | (TNamed ({ttype = TComp _; _}, _)) -> false | _ -> false) @@ -37,8 +37,8 @@ struct get_global_vars () |> List.filter (fun v -> match unrollType v.vtype with - | TComp (_, _) - | (TNamed ({ttype = TComp _; _}, _)) -> true + | TComp (ci, _) + | (TNamed ({ttype = TComp (ci,_); _}, _)) -> ci.cstruct | _ -> false) let get_reachable_mem_from_globals (global_vars:varinfo list) ctx = From 4fa70bd813e40e6621e252e4adfdf0b77cedb8c5 Mon Sep 17 00:00:00 2001 From: Karoliine Holter Date: Wed, 22 Nov 2023 13:11:06 +0200 Subject: [PATCH 608/628] Add missing fun defs from sv-benchmarks #1239 --- src/analyses/libraryFunctions.ml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 12eda8f728..1a032c84b3 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -37,7 +37,9 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("asctime", unknown ~attrs:[ThreadUnsafe] [drop "time_ptr" [r_deep]]); ("fclose", unknown [drop "stream" [r_deep; w_deep; f_deep]]); ("feof", unknown [drop "stream" [r_deep; w_deep]]); + ("feof_unlocked", unknown [drop "stream" [r_deep; w_deep]]); ("ferror", unknown [drop "stream" [r_deep; w_deep]]); + ("ferror_unlocked", unknown [drop "stream" [r_deep; w_deep]]); ("fflush", unknown [drop "stream" [r_deep; w_deep]]); ("fgetc", unknown [drop "stream" [r_deep; w_deep]]); ("getc", unknown [drop "stream" [r_deep; w_deep]]); @@ -52,9 +54,11 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("putc", unknown [drop "ch" []; drop "stream" [r_deep; w_deep]]); ("fputs", unknown [drop "str" [r]; drop "stream" [r_deep; w_deep]]); ("fread", unknown [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); + ("__fread_chk_warn", unknown [drop "buffer" [w]; drop "os" []; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fseek", unknown [drop "stream" [r_deep; w_deep]; drop "offset" []; drop "origin" []]); ("ftell", unknown [drop "stream" [r_deep]]); ("fwrite", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); + ("fwrite_unlocked", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("rewind", unknown [drop "stream" [r_deep; w_deep]]); ("setvbuf", unknown [drop "stream" [r_deep; w_deep]; drop "buffer" [r; w]; drop "mode" []; drop "size" []]); (* TODO: if this is used to set an input buffer, the buffer (second argument) would need to remain TOP, *) @@ -119,6 +123,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("mktime", unknown [drop "tm" [r;w]]); ("ctime", unknown ~attrs:[ThreadUnsafe] [drop "rm" [r]]); ("clearerr", unknown [drop "stream" [w]]); + ("clearerr_unlocked", unknown [drop "stream" [w]]); ("setbuf", unknown [drop "stream" [w]; drop "buf" [w]]); ("swprintf", unknown (drop "wcs" [w] :: drop "maxlen" [] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); (* only used if assert is used without include, e.g. in transformed files *) @@ -133,6 +138,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("abs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (IInt, j)) }); ("labs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (ILong, j)) }); ("llabs", special [__ "j" []] @@ fun j -> Math { fun_args = (Abs (ILongLong, j)) }); + ("imaxabs", unknown [drop "j" []]); ("localtime_r", unknown [drop "timep" [r]; drop "result" [w]]); ("strpbrk", unknown [drop "s" [r]; drop "accept" [r]]); ("_setjmp", special [__ "env" [w]] @@ fun env -> Setjmp { env }); (* only has one underscore *) @@ -151,6 +157,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atomic_load", unknown [drop "obj" [r]]); ("atomic_store", unknown [drop "obj" [w]; drop "desired" []]); ("_Exit", special [drop "status" []] @@ Abort); + ("strcoll", unknown [drop "lhs" [r]; drop "rhs" [r]]); ] (** C POSIX library functions. @@ -300,6 +307,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("sendto", unknown [drop "sockfd" []; drop "buf" [r]; drop "len" []; drop "flags" []; drop "dest_addr" [r_deep]; drop "addrlen" []]); ("strdup", unknown [drop "s" [r]]); ("strndup", unknown [drop "s" [r]; drop "n" []]); + ("__strndup", unknown [drop "s" [r]; drop "n" []]); ("syscall", unknown (drop "number" [] :: VarArgs (drop' [r; w]))); ("sysconf", unknown [drop "name" []]); ("syslog", unknown (drop "priority" [] :: drop "format" [r] :: VarArgs (drop' [r]))); (* TODO: is the VarArgs correct here? *) @@ -408,6 +416,7 @@ let posix_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("srandom", unknown [drop "seed" []]); ("random", special [] Rand); ("posix_memalign", unknown [drop "memptr" [w]; drop "alignment" []; drop "size" []]); (* TODO: Malloc *) + ("stpcpy", unknown [drop "dest" [w]; drop "src" [r]]); ] (** Pthread functions. *) @@ -654,6 +663,8 @@ let linux_userspace_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fstatfs", unknown [drop "fd" []; drop "buf" [w]]); ("cfmakeraw", unknown [drop "termios" [r; w]]); ("process_vm_readv", unknown [drop "pid" []; drop "local_iov" [w_deep]; drop "liovcnt" []; drop "remote_iov" []; drop "riovcnt" []; drop "flags" []]); + ("__libc_current_sigrtmax", unknown []); + ("__libc_current_sigrtmin", unknown []); ] let big_kernel_lock = AddrOf (Cil.var (Cilfacade.create_var (makeGlobalVar "[big kernel lock]" intType))) From 7159875257d594d248b3b3b7b0560e4c37e91f09 Mon Sep 17 00:00:00 2001 From: Karoliine Holter Date: Wed, 22 Nov 2023 13:47:15 +0200 Subject: [PATCH 609/628] Add fun defs for wprintf, iswxdigit and .*wscanf #1239 --- src/analyses/libraryFunctions.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 1a032c84b3..20995e2f09 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -125,6 +125,8 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("clearerr", unknown [drop "stream" [w]]); ("clearerr_unlocked", unknown [drop "stream" [w]]); ("setbuf", unknown [drop "stream" [w]; drop "buf" [w]]); + ("wprintf", unknown (drop "fmt" [r] :: VarArgs (drop' [r]))); + ("fwprintf", unknown (drop "stream" [w] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("swprintf", unknown (drop "wcs" [w] :: drop "maxlen" [] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); (* only used if assert is used without include, e.g. in transformed files *) ("difftime", unknown [drop "time1" []; drop "time2" []]); @@ -158,6 +160,9 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atomic_store", unknown [drop "obj" [w]; drop "desired" []]); ("_Exit", special [drop "status" []] @@ Abort); ("strcoll", unknown [drop "lhs" [r]; drop "rhs" [r]]); + ("wscanf", unknown (drop "fmt" [r] :: VarArgs (drop' [r]))); + ("fwscanf", unknown (drop "stream" [r] :: drop "fmt" [r] :: VarArgs (drop' [r]))); + ("swscanf", unknown (drop "buffer" [r] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ] (** C POSIX library functions. From dd45d1960a6e72083cc2c62f4c857aa24756cb2b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 22 Nov 2023 13:48:28 +0200 Subject: [PATCH 610/628] Add initial CHANGELOG for SV-COMP 2024 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97cc399133..ab9bb8fef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## v2.3.0 (unreleased) +Functionally equivalent to Goblint in SV-COMP 2024. + +### SV-COMP 2024 +* Add termination analysis (#1093). +* Add OOB analysis (#1094, #1197). +* Add memory leak analysis (???, #1246, #1241). +* Improve multi-threaded use-after-free analysis (#1123, ). +* Support MemSafety in SV-COMP (#1201, #1199, #1262). +* YAML witnesses in SV-COMP mode (#1217, #1226, #1225, #1248). +* YAML witness version 2.0 (#1238, #1240). +* SV-COMP multi-property (#1220, #1228). +* Adapt autotuning (#912, #921, #987, #1214, #1234, #1168). +* Support `alloca` (#1179). +* Fix old thread analysis soundness (#1223, #1230). +* Add library functions (#1242, #1244, #1254, #1239). +* Fix some region escape unsoundness (#1247). + ## v2.2.1 * Bump batteries lower bound to 3.5.0. * Fix flaky dead code elimination transformation test. From 949432b389c53939c08693ef1febe14f5c27e09b Mon Sep 17 00:00:00 2001 From: Karoliine Holter Date: Wed, 22 Nov 2023 13:54:07 +0200 Subject: [PATCH 611/628] Add fun def for iswxdigit #1239 --- src/analyses/libraryFunctions.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 20995e2f09..a9cce50b60 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -93,6 +93,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("iswspace", unknown [drop "wc" []]); ("iswalnum", unknown [drop "wc" []]); ("iswprint", unknown [drop "wc" []]); + ("iswxdigit", unknown [drop "ch" []]); ("rename" , unknown [drop "oldpath" [r]; drop "newpath" [r];]); ("perror", unknown [drop "s" [r]]); ("getchar", unknown []); From bf754c06f343cbde55c4bee6a60524840fe34161 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 22 Nov 2023 13:56:56 +0200 Subject: [PATCH 612/628] Add initial CHANGELOG for v2.3.0 --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab9bb8fef2..c32bf566d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,24 @@ ## v2.3.0 (unreleased) Functionally equivalent to Goblint in SV-COMP 2024. +* Refactor/fix race analysis (#1170, #1198). +* Add library function (#1167, #1174, #1220, #1203, #1205, #1212). +* Refactor/fix `MayPointTo` and `ReachableFrom` queries (#1142, #1176, #1144). +* Add final messages about unsound results (#1190, #1191). + ### SV-COMP 2024 * Add termination analysis (#1093). * Add OOB analysis (#1094, #1197). * Add memory leak analysis (???, #1246, #1241). * Improve multi-threaded use-after-free analysis (#1123, ). -* Support MemSafety in SV-COMP (#1201, #1199, #1262). +* Support MemSafety in SV-COMP (#1201, #1199, #1259, #1262). * YAML witnesses in SV-COMP mode (#1217, #1226, #1225, #1248). * YAML witness version 2.0 (#1238, #1240). * SV-COMP multi-property (#1220, #1228). * Adapt autotuning (#912, #921, #987, #1214, #1234, #1168). * Support `alloca` (#1179). * Fix old thread analysis soundness (#1223, #1230). -* Add library functions (#1242, #1244, #1254, #1239). +* Add library functions (#1242, #1244, #1254, #1239, #1269). * Fix some region escape unsoundness (#1247). ## v2.2.1 From c98025cc96870659b7deff213bd7820c897d9a75 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 22 Nov 2023 14:09:50 +0200 Subject: [PATCH 613/628] Move *_unlocked functions to glibc group, fix *wscanf varargs --- src/analyses/libraryFunctions.ml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index a9cce50b60..8152e5b886 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -37,9 +37,7 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("asctime", unknown ~attrs:[ThreadUnsafe] [drop "time_ptr" [r_deep]]); ("fclose", unknown [drop "stream" [r_deep; w_deep; f_deep]]); ("feof", unknown [drop "stream" [r_deep; w_deep]]); - ("feof_unlocked", unknown [drop "stream" [r_deep; w_deep]]); ("ferror", unknown [drop "stream" [r_deep; w_deep]]); - ("ferror_unlocked", unknown [drop "stream" [r_deep; w_deep]]); ("fflush", unknown [drop "stream" [r_deep; w_deep]]); ("fgetc", unknown [drop "stream" [r_deep; w_deep]]); ("getc", unknown [drop "stream" [r_deep; w_deep]]); @@ -54,11 +52,9 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("putc", unknown [drop "ch" []; drop "stream" [r_deep; w_deep]]); ("fputs", unknown [drop "str" [r]; drop "stream" [r_deep; w_deep]]); ("fread", unknown [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); - ("__fread_chk_warn", unknown [drop "buffer" [w]; drop "os" []; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fseek", unknown [drop "stream" [r_deep; w_deep]; drop "offset" []; drop "origin" []]); ("ftell", unknown [drop "stream" [r_deep]]); ("fwrite", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); - ("fwrite_unlocked", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("rewind", unknown [drop "stream" [r_deep; w_deep]]); ("setvbuf", unknown [drop "stream" [r_deep; w_deep]; drop "buffer" [r; w]; drop "mode" []; drop "size" []]); (* TODO: if this is used to set an input buffer, the buffer (second argument) would need to remain TOP, *) @@ -123,11 +119,10 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("vsnprintf", unknown [drop "str" [w]; drop "size" []; drop "format" [r]; drop "ap" [r_deep]]); (* TODO: what to do with a va_list type? is r_deep correct? *) ("mktime", unknown [drop "tm" [r;w]]); ("ctime", unknown ~attrs:[ThreadUnsafe] [drop "rm" [r]]); - ("clearerr", unknown [drop "stream" [w]]); - ("clearerr_unlocked", unknown [drop "stream" [w]]); + ("clearerr", unknown [drop "stream" [w]]); (* TODO: why only w? *) ("setbuf", unknown [drop "stream" [w]; drop "buf" [w]]); ("wprintf", unknown (drop "fmt" [r] :: VarArgs (drop' [r]))); - ("fwprintf", unknown (drop "stream" [w] :: drop "fmt" [r] :: VarArgs (drop' [r]))); + ("fwprintf", unknown (drop "stream" [r_deep; w_deep] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("swprintf", unknown (drop "wcs" [w] :: drop "maxlen" [] :: drop "fmt" [r] :: VarArgs (drop' [r]))); ("assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); (* only used if assert is used without include, e.g. in transformed files *) ("difftime", unknown [drop "time1" []; drop "time2" []]); @@ -161,9 +156,9 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("atomic_store", unknown [drop "obj" [w]; drop "desired" []]); ("_Exit", special [drop "status" []] @@ Abort); ("strcoll", unknown [drop "lhs" [r]; drop "rhs" [r]]); - ("wscanf", unknown (drop "fmt" [r] :: VarArgs (drop' [r]))); - ("fwscanf", unknown (drop "stream" [r] :: drop "fmt" [r] :: VarArgs (drop' [r]))); - ("swscanf", unknown (drop "buffer" [r] :: drop "fmt" [r] :: VarArgs (drop' [r]))); + ("wscanf", unknown (drop "fmt" [r] :: VarArgs (drop' [w]))); + ("fwscanf", unknown (drop "stream" [r_deep; w_deep] :: drop "fmt" [r] :: VarArgs (drop' [w]))); + ("swscanf", unknown (drop "buffer" [r] :: drop "fmt" [r] :: VarArgs (drop' [w]))); ] (** C POSIX library functions. @@ -586,6 +581,10 @@ let gcc_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("fputs_unlocked", unknown [drop "s" [r]; drop "stream" [w]]); + ("feof_unlocked", unknown [drop "stream" [r_deep; w_deep]]); + ("ferror_unlocked", unknown [drop "stream" [r_deep; w_deep]]); + ("fwrite_unlocked", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); + ("clearerr_unlocked", unknown [drop "stream" [w]]); (* TODO: why only w? *) ("futimesat", unknown [drop "dirfd" []; drop "pathname" [r]; drop "times" [r]]); ("error", unknown ((drop "status" []) :: (drop "errnum" []) :: (drop "format" [r]) :: (VarArgs (drop' [r])))); ("warn", unknown (drop "format" [r] :: VarArgs (drop' [r]))); @@ -597,6 +596,7 @@ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__fgets_chk", unknown [drop "__s" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_alias", unknown [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_chk", unknown [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); + ("__fread_chk_warn", unknown [drop "buffer" [w]; drop "os" []; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("fread_unlocked", unknown ~attrs:[ThreadUnsafe] [drop "buffer" [w]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]); ("__fread_unlocked_alias", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); ("__fread_unlocked_chk", unknown ~attrs:[ThreadUnsafe] [drop "__ptr" [w]; drop "__ptrlen" []; drop "__size" []; drop "__n" []; drop "__stream" [r_deep; w_deep]]); From 9c650571f81b5c4d0b57a466b2adf935b90ddaa4 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Wed, 22 Nov 2023 14:30:14 +0200 Subject: [PATCH 614/628] Add CHANGELOG for v2.3.0 --- CHANGELOG.md | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c32bf566d2..7300c09206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,14 @@ ## v2.3.0 (unreleased) Functionally equivalent to Goblint in SV-COMP 2024. -* Refactor/fix race analysis (#1170, #1198). -* Add library function (#1167, #1174, #1220, #1203, #1205, #1212). -* Refactor/fix `MayPointTo` and `ReachableFrom` queries (#1142, #1176, #1144). -* Add final messages about unsound results (#1190, #1191). - -### SV-COMP 2024 -* Add termination analysis (#1093). -* Add OOB analysis (#1094, #1197). -* Add memory leak analysis (???, #1246, #1241). -* Improve multi-threaded use-after-free analysis (#1123, ). -* Support MemSafety in SV-COMP (#1201, #1199, #1259, #1262). -* YAML witnesses in SV-COMP mode (#1217, #1226, #1225, #1248). -* YAML witness version 2.0 (#1238, #1240). -* SV-COMP multi-property (#1220, #1228). -* Adapt autotuning (#912, #921, #987, #1214, #1234, #1168). -* Support `alloca` (#1179). -* Fix old thread analysis soundness (#1223, #1230). -* Add library functions (#1242, #1244, #1254, #1239, #1269). -* Fix some region escape unsoundness (#1247). +* Add termination analysis for loops (#1093). +* Add memory out-of-bounds analysis (#1094, #1197). +* Add memory leak analysis (#1127, #1241, #1246). +* Add SV-COMP `termination`, `valid-memsafety` and `valid-memcleanup` properties support (#1220, #1228, #1201, #1199, #1259, #1262). +* Add YAML witness version 2.0 support (#1238, #1240, #1217, #1226, #1225, #1248). +* Add final warnings about unsound results (#1190, #1191). +* Add many library function specifications (#1167, #1174, #1203, #1205, #1212, #1220, #1239, #1242, #1244, #1254, #1269). +* Adapt automatic configuration tuning (#912, #921, #987, #1168, #1214, #1234). ## v2.2.1 * Bump batteries lower bound to 3.5.0. From 6389a7f6a87c6495490858c75791920ac0c2ae7b Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Thu, 23 Nov 2023 10:28:27 +0200 Subject: [PATCH 615/628] Prevent num downgrade in lower-bounds CI --- .github/workflows/unlocked.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unlocked.yml b/.github/workflows/unlocked.yml index 990b7cfb49..57fa0cb6b5 100644 --- a/.github/workflows/unlocked.yml +++ b/.github/workflows/unlocked.yml @@ -160,7 +160,8 @@ jobs: - name: Downgrade dependencies # must specify ocaml-base-compiler again to prevent it from being downgraded - run: opam install $(opam exec -- opam-0install --prefer-oldest goblint ocaml-variants.4.14.0+options ocaml-option-flambda) + # prevent num downgrade to avoid dune/jbuilder error: https://github.com/ocaml/dune/issues/5280 + run: opam install $(opam exec -- opam-0install --prefer-oldest goblint ocaml-variants.4.14.0+options ocaml-option-flambda num.1.4) - name: Build run: ./make.sh nat From 9bb9ae2c29efcaa1bbc3b989e267f353e9804080 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 23 Nov 2023 10:32:51 +0100 Subject: [PATCH 616/628] Fix ordering of queries by deduplicating indices. --- src/domains/queries.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 52038fcf77..b9fa28f5be 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -331,8 +331,8 @@ struct | Any (MustTermLoop _) -> 53 | Any MustTermAllLoops -> 54 | Any IsEverMultiThreaded -> 55 - | Any (TmpSpecial _) -> 53 - | Any (IsAllocVar _) -> 54 + | Any (TmpSpecial _) -> 56 + | Any (IsAllocVar _) -> 57 let rec compare a b = let r = Stdlib.compare (order a) (order b) in From f2623868f8f6fbcc9230c62389625f89a1e1c7d5 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 23 Nov 2023 14:06:46 +0100 Subject: [PATCH 617/628] Fix Not_found exception in autotuner with congruences and termination. --- src/autoTune.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index fefdeb32fd..1fd1fa5ee6 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -99,7 +99,9 @@ let rec setCongruenceRecursive fd depth neigbourFunction = FunctionSet.iter (fun vinfo -> print_endline (" " ^ vinfo.vname); - setCongruenceRecursive (Cilfacade.find_varinfo_fundec vinfo) (depth -1) neigbourFunction + match (Cilfacade.find_varinfo_fundec vinfo) with + | fd -> setCongruenceRecursive fd (depth -1) neigbourFunction + | exception Not_found -> () (* Happens for __goblint_bounded*) ) (FunctionSet.filter (*for extern and builtin functions there is no function definition in CIL*) (fun x -> not (isExtern x.vstorage || BatString.starts_with x.vname "__builtin")) From 5be07e5e96c329ace898bcf973c5d7780bf44da8 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 23 Nov 2023 14:22:15 +0100 Subject: [PATCH 618/628] Remove unnecessary paranetheses. --- src/autoTune.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 1fd1fa5ee6..79f5f51a77 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -99,9 +99,9 @@ let rec setCongruenceRecursive fd depth neigbourFunction = FunctionSet.iter (fun vinfo -> print_endline (" " ^ vinfo.vname); - match (Cilfacade.find_varinfo_fundec vinfo) with + match Cilfacade.find_varinfo_fundec vinfo with | fd -> setCongruenceRecursive fd (depth -1) neigbourFunction - | exception Not_found -> () (* Happens for __goblint_bounded*) + | exception Not_found -> () (* Happens for __goblint_bounded *) ) (FunctionSet.filter (*for extern and builtin functions there is no function definition in CIL*) (fun x -> not (isExtern x.vstorage || BatString.starts_with x.vname "__builtin")) From 9b954b5cd0b14a146267bc80c476d6a81e281643 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 23 Nov 2023 15:00:25 +0100 Subject: [PATCH 619/628] Add example where autotuner crashed when trying to activate congruence domain when termination was enabled --- tests/regression/78-termination/51-modulo.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/regression/78-termination/51-modulo.c diff --git a/tests/regression/78-termination/51-modulo.c b/tests/regression/78-termination/51-modulo.c new file mode 100644 index 0000000000..5f5b8f1924 --- /dev/null +++ b/tests/regression/78-termination/51-modulo.c @@ -0,0 +1,14 @@ +// SKIP TERM PARAM: --enable ana.autotune.enabled --enable ana.sv-comp.functions --enable ana.sv-comp.enabled --set ana.autotune.activated "['congruence']" --set ana.specification "CHECK( init(main()), LTL(F end) )" + +// This task previously crashed due to the autotuner +int main() { + int a; + int odd, count = 0; + while(a > 1) { + odd = a % 2; + if(!odd) a = a / 2; + else a = a - 1; + count++; + } + return count; +} From 9f3fcac6baee113bfba38e789085e4537988eb64 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 16:25:20 +0200 Subject: [PATCH 620/628] Add ORCiD-s to metadata --- .zenodo.json | 15 ++++++++++----- CITATION.cff | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 5557622f9e..22705c2d9c 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -10,15 +10,18 @@ }, { "name": "Schwarz, Michael", - "affiliation": "Technische Universität München" + "affiliation": "Technische Universität München", + "orcid": "0000-0002-9828-0308" }, { "name": "Erhard, Julian", - "affiliation": "Technische Universität München" + "affiliation": "Technische Universität München", + "orcid": "0000-0002-1729-3925" }, { "name": "Tilscher, Sarah", - "affiliation": "Technische Universität München" + "affiliation": "Technische Universität München", + "orcid": "0009-0009-9644-7475" }, { "name": "Vogler, Ralf", @@ -30,14 +33,16 @@ }, { "name": "Vojdani, Vesal", - "affiliation": "University of Tartu" + "affiliation": "University of Tartu", + "orcid": "0000-0003-4336-7980" } ], "contributors": [ { "name": "Seidl, Helmut", "type": "ProjectLeader", - "affiliation": "Technische Universität München" + "affiliation": "Technische Universität München", + "orcid": "0000-0002-2135-1593" }, { "name": "Schwarz, Martin D.", diff --git a/CITATION.cff b/CITATION.cff index 7a2dcf188d..25d46cf762 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,12 +12,15 @@ authors: # same authors as in .zenodo.json and dune-project - given-names: Michael family-names: Schwarz affiliation: "Technische Universität München" + orcid: "https://orcid.org/0000-0002-9828-0308" - given-names: Julian family-names: Erhard affiliation: "Technische Universität München" + orcid: "https://orcid.org/0000-0002-1729-3925" - given-names: Sarah family-names: Tilscher affiliation: "Technische Universität München" + orcid: "https://orcid.org/0009-0009-9644-7475" - given-names: Ralf family-names: Vogler affiliation: "Technische Universität München" @@ -27,6 +30,7 @@ authors: # same authors as in .zenodo.json and dune-project - given-names: Vesal family-names: Vojdani affiliation: "University of Tartu" + orcid: "https://orcid.org/0000-0003-4336-7980" license: MIT repository-code: "https://github.com/goblint/analyzer" From 356136fb5cd85d1af1b38799282f1f64724a2b7a Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 16:26:13 +0200 Subject: [PATCH 621/628] Finalize CHANGELOG for v2.3.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7300c09206..d285480259 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## v2.3.0 (unreleased) +## v2.3.0 Functionally equivalent to Goblint in SV-COMP 2024. * Add termination analysis for loops (#1093). From 07463bf738482fb0273e32af3c976671dad03325 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 16:31:09 +0200 Subject: [PATCH 622/628] Disable zenodo-validate in metadata CI --- .github/workflows/metadata.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/metadata.yml b/.github/workflows/metadata.yml index 6c7360f9e3..3a48d52fa0 100644 --- a/.github/workflows/metadata.yml +++ b/.github/workflows/metadata.yml @@ -27,6 +27,9 @@ jobs: args: --validate zenodo-validate: + # Zenodo schema URL is dead + if: ${{ false }} + strategy: matrix: node-version: From ade7968858f8d6ad04ba8d5f788557ace5ddf926 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 16:33:55 +0200 Subject: [PATCH 623/628] Replace goblint-cil pin with published 2.0.3 --- dune-project | 2 +- goblint.opam | 5 +++-- goblint.opam.locked | 6 +----- goblint.opam.template | 3 ++- gobview | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dune-project b/dune-project index 05c7d9418c..81c8d2f091 100644 --- a/dune-project +++ b/dune-project @@ -24,7 +24,7 @@ (synopsis "Static analysis framework for C") (depends (ocaml (>= 4.10)) - (goblint-cil (>= 2.0.2)) ; TODO no way to define as pin-depends? Used goblint.opam.template to add it for now. https://github.com/ocaml/dune/issues/3231. Alternatively, removing this line and adding cil as a git submodule and `(vendored_dirs cil)` as ./dune also works. This way, no more need to reinstall the pinned cil opam package on changes. However, then cil is cleaned and has to be rebuild together with goblint. + (goblint-cil (>= 2.0.3)) ; TODO no way to define as pin-depends? Used goblint.opam.template to add it for now. https://github.com/ocaml/dune/issues/3231. Alternatively, removing this line and adding cil as a git submodule and `(vendored_dirs cil)` as ./dune also works. This way, no more need to reinstall the pinned cil opam package on changes. However, then cil is cleaned and has to be rebuild together with goblint. (batteries (>= 3.5.0)) (zarith (>= 1.8)) (yojson (>= 2.0.0)) diff --git a/goblint.opam b/goblint.opam index 34912fde26..669b2d9c40 100644 --- a/goblint.opam +++ b/goblint.opam @@ -21,7 +21,7 @@ bug-reports: "https://github.com/goblint/analyzer/issues" depends: [ "dune" {>= "3.7"} "ocaml" {>= "4.10"} - "goblint-cil" {>= "2.0.2"} + "goblint-cil" {>= "2.0.3"} "batteries" {>= "3.5.0"} "zarith" {>= "1.8"} "yojson" {>= "2.0.0"} @@ -75,7 +75,8 @@ dev-repo: "git+https://github.com/goblint/analyzer.git" # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" pin-depends: [ - [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] + # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed + # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] ] diff --git a/goblint.opam.locked b/goblint.opam.locked index 6e15ac8900..02eac0bb75 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -59,7 +59,7 @@ depends: [ "fileutils" {= "0.6.4"} "fmt" {= "0.9.0"} "fpath" {= "0.7.3"} - "goblint-cil" {= "2.0.2"} + "goblint-cil" {= "2.0.3"} "integers" {= "0.7.0"} "json-data-encoding" {= "0.12.1"} "jsonrpc" {= "1.15.0~5.0preview1"} @@ -130,10 +130,6 @@ post-messages: [ ] # TODO: manually reordered to avoid opam pin crash: https://github.com/ocaml/opam/issues/4936 pin-depends: [ - [ - "goblint-cil.2.0.2" - "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" - ] [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" diff --git a/goblint.opam.template b/goblint.opam.template index d8e25cde38..ca2796b3c7 100644 --- a/goblint.opam.template +++ b/goblint.opam.template @@ -2,7 +2,8 @@ # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" pin-depends: [ - [ "goblint-cil.2.0.2" "git+https://github.com/goblint/cil.git#c7ffc37ad83216a84d90fdbf427cc02a68ea5331" ] + # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed + # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] ] diff --git a/gobview b/gobview index b4467d820f..d4eb66b9eb 160000 --- a/gobview +++ b/gobview @@ -1 +1 @@ -Subproject commit b4467d820f28bac578fc0baf7f81393c67f6b82b +Subproject commit d4eb66b9eb277349a75141cb01899dbab9d3ef5d From dbd6479a53dbf76f351f853bbc9092d659a8a631 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 16:40:27 +0200 Subject: [PATCH 624/628] Disable pins for v2.3.0 release --- goblint.opam | 6 +++--- goblint.opam.locked | 7 ------- goblint.opam.template | 6 +++--- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/goblint.opam b/goblint.opam index 669b2d9c40..842c03933f 100644 --- a/goblint.opam +++ b/goblint.opam @@ -74,12 +74,12 @@ dev-repo: "git+https://github.com/goblint/analyzer.git" # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -pin-depends: [ +# pin-depends: [ # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) - [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -] + # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] +# ] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] diff --git a/goblint.opam.locked b/goblint.opam.locked index 02eac0bb75..aba9f38bda 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -128,10 +128,3 @@ conflicts: [ post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] -# TODO: manually reordered to avoid opam pin crash: https://github.com/ocaml/opam/issues/4936 -pin-depends: [ - [ - "ppx_deriving.5.2.1" - "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" - ] -] diff --git a/goblint.opam.template b/goblint.opam.template index ca2796b3c7..95f90bcbd1 100644 --- a/goblint.opam.template +++ b/goblint.opam.template @@ -1,12 +1,12 @@ # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -pin-depends: [ +# pin-depends: [ # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) - [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -] + # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] +# ] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] From 8c08a785a02b04d0af4a57f0c5cdce74780efb91 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 24 Nov 2023 23:23:26 +0200 Subject: [PATCH 625/628] Use opam 2.1 in releasing guide opam 2.1 with built-in depext is required to avoid qcheck version conflict with batteries. --- docs/developer-guide/releasing.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/developer-guide/releasing.md b/docs/developer-guide/releasing.md index fc5f5f68a1..4f49399f13 100644 --- a/docs/developer-guide/releasing.md +++ b/docs/developer-guide/releasing.md @@ -37,13 +37,11 @@ 2. Extract distribution archive. 3. Run Docker container in extracted directory: `docker run -it --rm -v $(pwd):/goblint ocaml/opam:ubuntu-22.04-ocaml-4.14` (or newer). 4. Navigate to distribution archive inside Docker container: `cd /goblint`. - 5. Pin package from distribution archive: `opam pin add --no-action .`. - 6. Install depexts: `opam depext --with-test goblint`. - 7. Install and test package: `opam install --with-test goblint`. - 8. Activate opam environment: `eval $(opam env)`. - 9. Check version: `goblint --version`. - 10. Check that analysis works: `goblint -v tests/regression/04-mutex/01-simple_rc.c`. - 11. Exit Docker container. + 5. Install and test package from distribution archive: `opam-2.1 install --with-test .`. + 6. Activate opam environment: `eval $(opam env)`. + 7. Check version: `goblint --version`. + 8. Check that analysis works: `goblint -v tests/regression/04-mutex/01-simple_rc.c`. + 9. Exit Docker container. 12. Temporarily enable Zenodo GitHub webhook. From ed5f25947405096d5b1851084c230aa2ccf87cf6 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 27 Nov 2023 10:16:41 +0200 Subject: [PATCH 626/628] Revert "Disable pins for v2.3.0 release" This reverts commit dbd6479a53dbf76f351f853bbc9092d659a8a631. --- goblint.opam | 6 +++--- goblint.opam.locked | 7 +++++++ goblint.opam.template | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/goblint.opam b/goblint.opam index 842c03933f..669b2d9c40 100644 --- a/goblint.opam +++ b/goblint.opam @@ -74,12 +74,12 @@ dev-repo: "git+https://github.com/goblint/analyzer.git" # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -# pin-depends: [ +pin-depends: [ # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) - # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -# ] + [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] +] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] diff --git a/goblint.opam.locked b/goblint.opam.locked index aba9f38bda..02eac0bb75 100644 --- a/goblint.opam.locked +++ b/goblint.opam.locked @@ -128,3 +128,10 @@ conflicts: [ post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] +# TODO: manually reordered to avoid opam pin crash: https://github.com/ocaml/opam/issues/4936 +pin-depends: [ + [ + "ppx_deriving.5.2.1" + "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" + ] +] diff --git a/goblint.opam.template b/goblint.opam.template index 95f90bcbd1..ca2796b3c7 100644 --- a/goblint.opam.template +++ b/goblint.opam.template @@ -1,12 +1,12 @@ # on `dune build` goblint.opam will be generated from goblint.opam.template and dune-project # also remember to generate/adjust goblint.opam.locked! available: os-distribution != "alpine" & arch != "arm64" -# pin-depends: [ +pin-depends: [ # published goblint-cil 2.0.3 is currently up-to-date, so no pin needed # [ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#d2760bacfbfdb25a374254de44f2ff1cb5f42abd" ] # TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252) - # [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] -# ] + [ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ] +] post-messages: [ "Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"} ] From 6d4f9e78f219edbf81563ac0a37d6fa147fd4bab Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 27 Nov 2023 10:20:36 +0200 Subject: [PATCH 627/628] Add opam pin revert step to releasing guide --- docs/developer-guide/releasing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/developer-guide/releasing.md b/docs/developer-guide/releasing.md index 4f49399f13..fcf69ea533 100644 --- a/docs/developer-guide/releasing.md +++ b/docs/developer-guide/releasing.md @@ -57,6 +57,7 @@ 15. Create an opam package: `dune-release opam pkg`. 16. Submit the opam package to opam-repository: `dune-release opam submit`. +17. Revert temporary removal of opam pins. ## SV-COMP From 975b502b684c01d4f988ba62a20d4a64d7b52b36 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 27 Nov 2023 10:27:36 +0200 Subject: [PATCH 628/628] Add few people to .mailmap --- .mailmap | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.mailmap b/.mailmap index 9153d55765..9aa2d0cc02 100644 --- a/.mailmap +++ b/.mailmap @@ -23,6 +23,7 @@ Kerem Çakırer Sarah Tilscher <66023521+stilscher@users.noreply.github.com> Karoliine Holter <44437975+karoliineh@users.noreply.github.com> + Elias Brandstetter <15275491+superbr4in@users.noreply.github.com> wherekonshade <80516286+Wherekonshade@users.noreply.github.com> @@ -37,3 +38,6 @@ Mireia Cano Pujol Felix Krayer Felix Krayer <91671586+FelixKrayer@users.noreply.github.com> Manuel Pietsch +Tim Ortel <100865202+TimOrtel@users.noreply.github.com> +Tomáš Dacík + <43824605+TDacik@users.noreply.github.com>