-
Notifications
You must be signed in to change notification settings - Fork 88
Bachelor's Thesis "Synthesizing Ranking Functions for LASW programs with Goblint" #1941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -613,7 +613,7 @@ struct | |||||
| if (one_var || GobApron.Lincons1.num_vars lincons1 >= 2) && (exact || Apron.Lincons1.get_typ lincons1 <> EQ) then | ||||||
| RD.cil_exp_of_lincons1 lincons1 | ||||||
| |> Option.map e_inv | ||||||
| |> Option.filter (InvariantCil.exp_is_suitable ~scope) | ||||||
| (*|> Option.filter (InvariantCil.exp_is_suitable ~scope)*) | ||||||
|
||||||
| (*|> Option.filter (InvariantCil.exp_is_suitable ~scope)*) | |
| |> Option.filter (InvariantCil.exp_is_suitable ~scope) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,10 +5,325 @@ | |||||||||||||||||||
| open Analyses | ||||||||||||||||||||
| open GoblintCil | ||||||||||||||||||||
| open TerminationPreprocessing | ||||||||||||||||||||
| open ListMatrix | ||||||||||||||||||||
| open SparseVector | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) | ||||||||||||||||||||
| let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module V = struct | ||||||||||||||||||||
| type t = string | ||||||||||||||||||||
| let is_int _ = true | ||||||||||||||||||||
| let compare = String.compare | ||||||||||||||||||||
| let print fmt v = Format.fprintf fmt "%s" v | ||||||||||||||||||||
| end | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module Rat = struct | ||||||||||||||||||||
| include Mpqf | ||||||||||||||||||||
| let zero = of_int 0 | ||||||||||||||||||||
| let one = of_int 1 | ||||||||||||||||||||
| let m_one = of_int (-1) | ||||||||||||||||||||
| let is_zero x = cmp_int x 0 = 0 | ||||||||||||||||||||
| let is_one x = cmp_int x 1 = 0 | ||||||||||||||||||||
| let is_m_one x = cmp_int x (-1) = 0 | ||||||||||||||||||||
| let is_int x = is_one (of_mpz (get_den x)) (* I assume the numbers to be normalized *) | ||||||||||||||||||||
| let min x y = if cmp x y <= 0 then x else y | ||||||||||||||||||||
| let floor x = | ||||||||||||||||||||
| let n = get_num x in | ||||||||||||||||||||
| let d = get_den x in | ||||||||||||||||||||
| of_mpz (Mpzf.fdiv_q n d) | ||||||||||||||||||||
| let ceiling x = | ||||||||||||||||||||
| let n = get_num x in | ||||||||||||||||||||
| let d = get_den x in | ||||||||||||||||||||
| of_mpz (Mpzf.cdiv_q n d) | ||||||||||||||||||||
| let minus = neg | ||||||||||||||||||||
| let sign = sgn | ||||||||||||||||||||
| let compare = cmp | ||||||||||||||||||||
| let mult = mul | ||||||||||||||||||||
| let hash _ = 0 | ||||||||||||||||||||
| let get_den x = Z.of_string (Mpzf.to_string (get_den x)) | ||||||||||||||||||||
| let get_num x = Z.of_string (Mpzf.to_string (get_num x)) | ||||||||||||||||||||
| end | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module Ex = struct | ||||||||||||||||||||
| include Set.Make(String) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| let print fmt s = match elements s with | ||||||||||||||||||||
| | [] -> Format.fprintf fmt "()" | ||||||||||||||||||||
| | e::l -> | ||||||||||||||||||||
| Format.fprintf fmt "%s" e; | ||||||||||||||||||||
| List.iter (Format.fprintf fmt ", %s") l | ||||||||||||||||||||
| end | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module Sim = OcplibSimplex.Basic.Make (V) (Rat) (Ex) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module Matrix = ListMatrix (Rat) (SparseVector) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module SparseVec = SparseVector (Rat) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| module VarSet = Set.Make(String) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| let string_of_constraints (constraints: Invariant.t) = | ||||||||||||||||||||
| match constraints with | ||||||||||||||||||||
| | `Top -> "Top" | ||||||||||||||||||||
| | `Bot -> "Bot" | ||||||||||||||||||||
| | `Lifted constraints -> constraints |> Invariant.Exp.process |> List.map Invariant.Exp.show |> String.concat "; " | ||||||||||||||||||||
|
|
||||||||||||||||||||
| let exp_list_of_constraints (constraints : Invariant.t) = | ||||||||||||||||||||
| match constraints with | ||||||||||||||||||||
| | `Top -> [] | ||||||||||||||||||||
| | `Bot -> failwith "Constraints are Bot" | ||||||||||||||||||||
|
||||||||||||||||||||
| | `Bot -> failwith "Constraints are Bot" | |
| | `Bot -> | |
| if M.tracing then | |
| M.trace "termination" "Ignoring Bot constraints (unreachable state)"; | |
| [] |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The to_leq function uses failwith when encountering constraint types other than Le, Ge, Eq, or Ne. Invariants may contain other binary operations or unary operations that should be handled. This will cause crashes when analyzing loops with more complex conditions.
| | _ -> failwith "Found something else, help me" in | |
| | _ -> | |
| (* Ignore expressions that are not simple comparison constraints. *) | |
| acc | |
| in |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple failwith calls with unhelpful messages like "This shouldn't happen", "found a Minus", "found another Mult", "found something else". These indicate incomplete implementation of expression parsing. When encountering MinusA operations, the code immediately fails instead of handling them. Since MinusA is a common operation in C expressions (subtraction), this will cause the analysis to crash on many valid programs. These cases should be properly handled or at minimum report meaningful errors via M.warn.
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The const_in_exp function has the same issues as coeff_in_exp: it uses failwith for common expression forms that should be handled. This incomplete implementation will cause crashes on valid C programs.
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue with failwith on CastE and Question expressions. These are valid expression types that may appear in loop conditions and should be handled appropriately rather than causing the analysis to crash.
| | CastE _ -> failwith "Encountered cast" | |
| | Question _ -> failwith "Encountered question" | |
| | CastE (_, e) -> | |
| vars_from_exp acc e | |
| | Question (e1, e2, e3, _) -> | |
| let acc1 = vars_from_exp acc e1 in | |
| let acc2 = vars_from_exp acc e2 in | |
| let acc3 = vars_from_exp acc e3 in | |
| VarSet.union acc1 (VarSet.union acc2 acc3) |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test_termination_provable function is defined but never called. It contains hardcoded test cases that should either be converted to actual unit tests or removed. Dead code reduces maintainability and can cause confusion about what is actually being tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break the framework in unexpected places, I'd recommend getting rid of it soon, so you don't go chasing failures from other analyses that are caused by this. You can, e.g., add a custom query for now that doesn't do this and then get rid of it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing this is using the witness invariant query internally somewhere. It's not really intended to be used this way:
analyzer/src/cdomain/value/domains/invariant.mli
Lines 9 to 10 in d2d183c
I didn't look closely but it seems to me that
exp_list_of_constraintsis then trying to convert that invariant back into constraints. It's a very roundabout way to get constraints from one analysis to the other, going back and forth via lossy translations that aren't intended for this.I think the same matter came up a while ago, maybe in relation to #1635 or something similar.