Skip to content

Commit 77103df

Browse files
committed
Merge branch 'master' into rm-libmaincil
2 parents 8e94981 + 887ebe0 commit 77103df

18 files changed

+176
-75
lines changed

docs/requirements.txt

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
# Python requirements for MkDocs and Read the Docs
22

3-
mkdocs==1.2.4
4-
5-
jinja2==3.1.3
3+
mkdocs==1.5.3

g2html

gobview

Submodule gobview updated 56 files

scripts/test-gobview.py

+66
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,72 @@ def serve():
6161
panel = browser.find_element(By.CLASS_NAME, "panel")
6262
print("found DOM elements main, sidebar-left, sidebar-right, content and panel")
6363

64+
# test syntactic search
65+
leftS.find_element(By.LINK_TEXT, "Search").click()
66+
leftS.find_element(By.CLASS_NAME, "switch-to-json").click()
67+
textfield = leftS.find_element(By.CLASS_NAME, "form-control")
68+
textfield.clear()
69+
textfield.send_keys('{"kind":["var"],"target":["name","fail"],"find":["uses"],"mode":["Must"]}')
70+
leftS.find_element(By.CLASS_NAME, "exec-button").click()
71+
results = leftS.find_elements(By.CLASS_NAME, "list-group-item")
72+
locations = []
73+
for r in results:
74+
for tr in r.find_elements(By.TAG_NAME, "tr"):
75+
if tr.find_element(By.TAG_NAME, "th").text == "Location":
76+
locations.insert(0,tr.find_element(By.TAG_NAME, "td").find_element(By.TAG_NAME, "a").text)
77+
78+
print("syntactic search for variable use of 'fail' found", len(results), "results")
79+
for l in locations:
80+
print(l)
81+
assert(len(results) == 2)
82+
assert("tests/regression/00-sanity/01-assert.c:7" in locations)
83+
assert("tests/regression/00-sanity/01-assert.c:12" in locations)
84+
85+
# clear results
86+
leftS.find_element(By.CLASS_NAME, "clear-btn").click()
87+
88+
# test semantic search 1
89+
textfield = leftS.find_element(By.CLASS_NAME, "form-control")
90+
textfield.clear()
91+
textfield.send_keys('{"kind":["var"],"target":["name","success"],"find":["uses"],"expression":"success == 1","mode":["Must"]}')
92+
leftS.find_element(By.CLASS_NAME, "exec-button").click()
93+
results = leftS.find_elements(By.CLASS_NAME, "list-group-item")
94+
locations = []
95+
for r in results:
96+
for tr in r.find_elements(By.TAG_NAME, "tr"):
97+
if tr.find_element(By.TAG_NAME, "th").text == "Location":
98+
locations.insert(0,tr.find_element(By.TAG_NAME, "td").find_element(By.TAG_NAME, "a").text)
99+
100+
print("semantic search for variable use of 'success' where it must be 1 found", len(results), "results")
101+
for l in locations:
102+
print(l)
103+
assert(len(results) == 2)
104+
assert("tests/regression/00-sanity/01-assert.c:10" in locations)
105+
assert("tests/regression/00-sanity/01-assert.c:5" in locations)
106+
107+
# clear results
108+
leftS.find_element(By.CLASS_NAME, "clear-btn").click()
109+
110+
# test semantic search 2
111+
textfield = leftS.find_element(By.CLASS_NAME, "form-control")
112+
textfield.clear()
113+
textfield.send_keys('{"kind":["var"],"target":["name","success"],"find":["uses"],"expression":"success == 0","mode":["Must"]}')
114+
leftS.find_element(By.CLASS_NAME, "exec-button").click()
115+
results = leftS.find_elements(By.CLASS_NAME, "list-group-item")
116+
locations = []
117+
for r in results:
118+
for tr in r.find_elements(By.TAG_NAME, "tr"):
119+
if tr.find_element(By.TAG_NAME, "th").text == "Location":
120+
locations.insert(0,tr.find_element(By.TAG_NAME, "td").find_element(By.TAG_NAME, "a").text)
121+
122+
print("semantic search for variable use of 'success' where it must be 0 found", len(results), "results")
123+
for l in locations:
124+
print(l)
125+
assert(len(results) == 0)
126+
127+
# close "No results found" alert
128+
leftS.find_element(By.CLASS_NAME, "btn-close").click()
129+
64130
cleanup(browser, thread)
65131

66132
except Exception as e:

src/analyses/apron/affineEqualityAnalysis.apron.ml

+1-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,10 @@ include RelationAnalysis
99
let spec_module: (module MCPSpec) Lazy.t =
1010
lazy (
1111
let module AD = AffineEqualityDomain.D2 (VectorMatrix.ArrayVector) (VectorMatrix.ArrayMatrix) in
12-
let module RD: RelationDomain.RD =
13-
struct
14-
module V = AffineEqualityDomain.V
15-
include AD
16-
end
17-
in
1812
let module Priv = (val RelationPriv.get_priv ()) in
1913
let module Spec =
2014
struct
21-
include SpecFunctor (Priv) (RD) (RelationPrecCompareUtil.DummyUtil)
15+
include SpecFunctor (Priv) (AD) (RelationPrecCompareUtil.DummyUtil)
2216
let name () = "affeq"
2317
end
2418
in

src/analyses/apron/apronAnalysis.apron.ml

+2-9
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,11 @@ let spec_module: (module MCPSpec) Lazy.t =
99
let module Man = (val ApronDomain.get_manager ()) in
1010
let module AD = ApronDomain.D2 (Man) in
1111
let diff_box = GobConfig.get_bool "ana.apron.invariant.diff-box" in
12-
let module AD = (val if diff_box then (module ApronDomain.BoxProd (AD): ApronDomain.S3) else (module AD)) in
13-
let module RD: RelationDomain.RD =
14-
struct
15-
module V = ApronDomain.V
16-
include AD
17-
type var = Apron.Var.t
18-
end
19-
in
12+
let module AD = (val if diff_box then (module ApronDomain.BoxProd (AD): RelationDomain.RD) else (module AD)) in
2013
let module Priv = (val RelationPriv.get_priv ()) in
2114
let module Spec =
2215
struct
23-
include SpecFunctor (Priv) (RD) (ApronPrecCompareUtil.Util)
16+
include SpecFunctor (Priv) (AD) (ApronPrecCompareUtil.Util)
2417
let name () = "apron"
2518
end
2619
in

src/analyses/base.ml

+13-6
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,15 @@ struct
177177
| LNot -> ID.c_lognot
178178

179179
let unop_FD = function
180-
| Neg -> FD.neg
181-
(* other unary operators are not implemented on float values *)
182-
| _ -> (fun c -> FD.top_of (FD.get_fkind c))
180+
| Neg -> (fun v -> (Float (FD.neg v):value))
181+
| LNot -> (fun c -> Int (FD.eq c (FD.of_const (FD.get_fkind c) 0.)))
182+
| BNot -> failwith "BNot on a value of type float!"
183+
183184

184185
(* Evaluating Cil's unary operators. *)
185186
let evalunop op typ: value -> value = function
186187
| Int v1 -> Int (ID.cast_to (Cilfacade.get_ikind typ) (unop_ID op v1))
187-
| Float v -> Float (unop_FD op v)
188+
| Float v -> unop_FD op v
188189
| Address a when op = LNot ->
189190
if AD.is_null a then
190191
Int (ID.of_bool (Cilfacade.get_ikind typ) true)
@@ -877,9 +878,9 @@ struct
877878
| CastE (t, Const (CStr (x,e))) -> (* VD.top () *) eval_rv ~ctx st (Const (CStr (x,e))) (* TODO safe? *)
878879
| CastE (t, exp) ->
879880
(let v = eval_rv ~ctx st exp in
880-
try
881+
try
881882
VD.cast ~torg:(Cilfacade.typeOf exp) t v
882-
with Cilfacade.TypeOfError _ ->
883+
with Cilfacade.TypeOfError _ ->
883884
VD.cast t v)
884885
| SizeOf _
885886
| Real _
@@ -1644,6 +1645,9 @@ struct
16441645
module V = V
16451646
module G = G
16461647

1648+
let unop_ID = unop_ID
1649+
let unop_FD = unop_FD
1650+
16471651
let eval_rv = eval_rv
16481652
let eval_rv_address = eval_rv_address
16491653
let eval_lv = eval_lv
@@ -2841,6 +2845,9 @@ struct
28412845

28422846
let ost = octx.local
28432847

2848+
let unop_ID = unop_ID
2849+
let unop_FD = unop_FD
2850+
28442851
(* all evals happen in octx with non-top values *)
28452852
let eval_rv ~ctx st e = eval_rv ~ctx:octx ost e
28462853
let eval_rv_address ~ctx st e = eval_rv_address ~ctx:octx ost e

src/analyses/baseInvariant.ml

+28-22
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ sig
1414
module V: Analyses.SpecSysVar
1515
module G: Lattice.S
1616

17+
val unop_ID: Cil.unop -> ID.t -> ID.t
18+
val unop_FD: Cil.unop -> FD.t -> VD.t
19+
1720
val eval_rv: ctx:(D.t, G.t, _, V.t) Analyses.ctx -> D.t -> exp -> VD.t
1821
val eval_rv_address: ctx:(D.t, G.t, _, V.t) Analyses.ctx -> D.t -> exp -> VD.t
1922
val eval_lv: ctx:(D.t, G.t, _, V.t) Analyses.ctx -> D.t -> lval -> AD.t
@@ -41,16 +44,6 @@ module Make (Eval: Eval) =
4144
struct
4245
open Eval
4346

44-
let unop_ID = function
45-
| Neg -> ID.neg
46-
| BNot -> ID.lognot
47-
| LNot -> ID.c_lognot
48-
49-
let unop_FD = function
50-
| Neg -> FD.neg
51-
(* other unary operators are not implemented on float values *)
52-
| _ -> (fun c -> FD.top_of (FD.get_fkind c))
53-
5447
let is_some_bot (x:VD.t) =
5548
match x with
5649
| Bot -> false (* HACK: bot is here due to typing conflict (we do not cast appropriately) *)
@@ -565,18 +558,31 @@ struct
565558
else
566559
match exp, c_typed with
567560
| UnOp (LNot, e, _), Int c ->
568-
let ikind = Cilfacade.get_ikind_exp e in
569-
let c' =
570-
match ID.to_bool (unop_ID LNot c) with
571-
| Some true ->
572-
(* i.e. e should evaluate to [1,1] *)
573-
(* LNot x is 0 for any x != 0 *)
574-
ID.of_excl_list ikind [Z.zero]
575-
| Some false -> ID.of_bool ikind false
576-
| _ -> ID.top_of ikind
577-
in
578-
inv_exp (Int c') e st
579-
| UnOp (Neg, e, _), Float c -> inv_exp (Float (unop_FD Neg c)) e st
561+
(match Cilfacade.typeOf e with
562+
| TInt _ | TPtr _ ->
563+
let ikind = Cilfacade.get_ikind_exp e in
564+
let c' =
565+
match ID.to_bool (unop_ID LNot c) with
566+
| Some true ->
567+
(* i.e. e should evaluate to [1,1] *)
568+
(* LNot x is 0 for any x != 0 *)
569+
ID.of_excl_list ikind [Z.zero]
570+
| Some false -> ID.of_bool ikind false
571+
| _ -> ID.top_of ikind
572+
in
573+
inv_exp (Int c') e st
574+
| TFloat(fkind, _) when ID.to_bool (unop_ID LNot c) = Some false ->
575+
(* C99 §6.5.3.3/5 *)
576+
(* The result of the logical negation operator ! is 0 if the value of its operand compares *)
577+
(* unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. *)
578+
(* The expression !E is equivalent to (0==E). *)
579+
(* NaN compares unequal to 0 so no problems *)
580+
(* We do not have exclusions for floats, so we do not bother here with the other case *)
581+
let zero_float = FD.of_const fkind 0. in
582+
inv_exp (Float zero_float) e st
583+
| _ -> st
584+
)
585+
| UnOp (Neg, e, _), Float c -> inv_exp (unop_FD Neg c) e st
580586
| UnOp ((BNot|Neg) as op, e, _), Int c -> inv_exp (Int (unop_ID op c)) e st
581587
(* no equivalent for Float, as VD.is_safe_cast fails for all float types anyways *)
582588
| 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) ->

src/cdomains/apron/affineEqualityDomain.apron.ml

+3-5
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ module Mpqf = struct
2626
let hash x = 31 * (Z.hash (get_den x)) + Z.hash (get_num x)
2727
end
2828

29-
module V = RelationDomain.V
30-
3129
(** It defines the type t of the affine equality domain (a struct that contains an optional matrix and an apron environment) and provides the functions needed for handling variables (which are defined by RelationDomain.D2) such as add_vars remove_vars.
3230
Furthermore, it provides the function get_coeff_vec that parses an apron expression into a vector of coefficients if the apron expression has an affine form. *)
3331
module VarManagement (Vec: AbstractVector) (Mx: AbstractMatrix)=
@@ -240,7 +238,7 @@ struct
240238
include VarManagement (Vc) (Mx)
241239

242240
module Bounds = ExpressionBounds (Vc) (Mx)
243-
241+
module V = RelationDomain.V
244242
module Convert = SharedFunctions.Convert (V) (Bounds) (struct let allow_global = true end) (SharedFunctions.Tracked)
245243

246244
type var = V.t
@@ -703,9 +701,9 @@ struct
703701
let unmarshal t = t
704702
end
705703

706-
module D2(Vc: AbstractVector) (Mx: AbstractMatrix): RelationDomain.S3 with type var = Var.t =
704+
module D2(Vc: AbstractVector) (Mx: AbstractMatrix): RelationDomain.RD with type var = Var.t =
707705
struct
708706
module D = D (Vc) (Mx)
709-
include SharedFunctions.AssertionModule (V) (D)
707+
include SharedFunctions.AssertionModule (D.V) (D)
710708
include D
711709
end

src/cdomains/apron/apronDomain.apron.ml

+6-1
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ module type S2 =
779779
(* TODO: ExS3 or better extend RelationDomain.S3 directly?*)
780780
sig
781781
module Man: Manager
782+
module V: RV
782783
include module type of AOps (Tracked) (Man)
783784
include SLattice with type t = Man.mt A.t
784785

@@ -803,6 +804,7 @@ sig
803804
include SLattice
804805
include AOps with type t := t
805806

807+
module V: RV
806808
module Tracked: RelationDomain.Tracked
807809

808810
val assert_inv : t -> exp -> bool -> bool Lazy.t -> t
@@ -813,6 +815,7 @@ end
813815
module D2 (Man: Manager) : S2 with module Man = Man =
814816
struct
815817
include D (Man)
818+
module V = RelationDomain.V
816819

817820
type marshal = OctagonD.marshal
818821

@@ -926,8 +929,10 @@ struct
926929
|> Lincons1Set.elements
927930
end
928931

929-
module BoxProd (D: S3): S3 =
932+
module BoxProd (D: S3): RD =
930933
struct
934+
module V = D.V
935+
type var = V.t
931936
module BP0 = BoxProd0 (D)
932937
module Tracked = SharedFunctions.Tracked
933938
include BP0

src/cdomains/apron/relationDomain.apron.ml

-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ end
128128
module type S3 =
129129
sig
130130
include S2
131-
132131
val cil_exp_of_lincons1: Lincons1.t -> exp option
133132
val invariant: t -> Lincons1.t list
134133
end

src/common/framework/cfgTools.ml

-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ let rec pretty_edges () = function
122122
| [_,x] -> Edge.pretty_plain () x
123123
| (_,x)::xs -> Pretty.dprintf "%a; %a" Edge.pretty_plain x pretty_edges xs
124124

125-
126125
let node_scc_global = NH.create 113
127126

128127
exception Not_connect of fundec

src/common/util/cilfacade.ml

+3-7
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ include Cilfacade0
88

99
(** Command for assigning an id to a varinfo. All varinfos directly created by Goblint should be modified by this method *)
1010
let create_var (var: varinfo) =
11-
(* TODO Hack: this offset should preempt conflicts with ids generated by CIL *)
12-
let start_id = 10_000_000_000 in
11+
(* Hack: using negative integers should preempt conflicts with ids generated by CIL *)
1312
let hash = Hashtbl.hash { var with vid = 0 } in
14-
let hash = if hash < start_id then hash + start_id else hash in
15-
{ var with vid = hash }
13+
{ var with vid = - hash } (* Hashtbl.hash returns non-negative integer *)
1614

1715

1816
(** Is character type (N1570 6.2.5.15)? *)
@@ -531,9 +529,7 @@ let stmt_fundecs: fundec StmtH.t ResettableLazy.t =
531529

532530

533531
let get_pseudo_return_id fd =
534-
let start_id = 10_000_000_000 in (* TODO get max_sid? *)
535-
let sid = Hashtbl.hash fd.svar.vid in (* Need pure sid instead of Cil.new_sid for incremental, similar to vid in Cilfacade.create_var. We only add one return stmt per loop, so the hash from the functions vid should be unique. *)
536-
if sid < start_id then sid + start_id else sid
532+
- fd.svar.vid (* Need pure sid instead of Cil.new_sid for incremental, similar to vid in Cilfacade.create_var. We only add one return stmt per loop, so the hash from the functions vid should be unique. *)
537533

538534
let pseudo_return_to_fun = StmtH.create 113
539535

src/framework/analysisResult.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct
5252
(* Not using Node.location here to have updated locations in incremental analysis.
5353
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
5454
let loc = UpdateCil.getLoc n in
55-
BatPrintf.fprintf f "<call id=\"%s\" file=\"%s\" line=\"%d\" order=\"%d\" column=\"%d\">\n" (Node.show_id n) loc.file loc.line loc.byte loc.column;
55+
BatPrintf.fprintf f "<call id=\"%s\" file=\"%s\" line=\"%d\" order=\"%d\" column=\"%d\" endLine=\"%d\" endColumn=\"%d\" synthetic=\"%B\">\n" (Node.show_id n) loc.file loc.line loc.byte loc.column loc.endLine loc.endColumn loc.synthetic;
5656
BatPrintf.fprintf f "%a</call>\n" Range.printXml v
5757
in
5858
iter print_one xs

0 commit comments

Comments
 (0)