1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 AbstractState, AbstractTransformer, AbstractionFunction, ArrayBoundsAnalysis,
9 AssumeGuaranteeContract, Bound, ConcretizationFunction, DataflowAnalysis, DelayedWidening,
10 FixpointComputation, GaloisConnection, IntervalDomain, IntervalWidening, LoopBound,
11 NullPointerAnalysis, OctagonDomain, ParityDomain, PolyhedralDomain,
12 ProbabilisticAbstractDomain, ReachabilityAnalysis, SignDomain, TaintAnalysis,
13 TemplatePolyhedronDomain, ZonotopeDomain,
14};
15
16pub fn app(f: Expr, a: Expr) -> Expr {
17 Expr::App(Box::new(f), Box::new(a))
18}
19pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
20 app(app(f, a), b)
21}
22pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
23 app(app2(f, a, b), c)
24}
25pub fn cst(s: &str) -> Expr {
26 Expr::Const(Name::str(s), vec![])
27}
28pub fn prop() -> Expr {
29 Expr::Sort(Level::zero())
30}
31pub fn type0() -> Expr {
32 Expr::Sort(Level::succ(Level::zero()))
33}
34pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
35 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
36}
37pub fn arrow(a: Expr, b: Expr) -> Expr {
38 pi(BinderInfo::Default, "_", a, b)
39}
40pub fn impl_pi(name: &str, dom: Expr, body: Expr) -> Expr {
41 pi(BinderInfo::Implicit, name, dom, body)
42}
43pub fn bvar(n: u32) -> Expr {
44 Expr::BVar(n)
45}
46pub fn nat_ty() -> Expr {
47 cst("Nat")
48}
49pub fn bool_ty() -> Expr {
50 cst("Bool")
51}
52pub fn abstract_domain_ty() -> Expr {
57 impl_pi("A", type0(), type0())
58}
59pub fn abstract_lattice_ty() -> Expr {
63 impl_pi(
64 "A",
65 type0(),
66 arrow(app(cst("AbstractDomain"), bvar(0)), prop()),
67 )
68}
69pub fn interval_domain_ty() -> Expr {
74 type0()
75}
76pub fn octagon_domain_ty() -> Expr {
81 arrow(nat_ty(), type0())
82}
83pub fn polyhedral_domain_ty() -> Expr {
88 arrow(nat_ty(), type0())
89}
90pub fn sign_domain_ty() -> Expr {
94 type0()
95}
96pub fn parity_domain_ty() -> Expr {
100 type0()
101}
102pub fn abstract_join_ty() -> Expr {
106 impl_pi("A", type0(), arrow(bvar(0), arrow(bvar(1), bvar(2))))
107}
108pub fn abstract_meet_ty() -> Expr {
112 impl_pi("A", type0(), arrow(bvar(0), arrow(bvar(1), bvar(2))))
113}
114pub fn abstract_widen_ty() -> Expr {
119 impl_pi("A", type0(), arrow(bvar(0), arrow(bvar(1), bvar(2))))
120}
121pub fn abstract_narrow_ty() -> Expr {
126 impl_pi("A", type0(), arrow(bvar(0), arrow(bvar(1), bvar(2))))
127}
128pub fn abstract_state_ty() -> Expr {
133 type0()
134}
135pub fn abstract_transformer_ty() -> Expr {
140 arrow(cst("AbstractState"), cst("AbstractState"))
141}
142pub fn transfer_function_ty() -> Expr {
147 type0()
148}
149pub fn join_semilattice_ty() -> Expr {
154 arrow(
155 cst("AbstractState"),
156 arrow(cst("AbstractState"), cst("AbstractState")),
157 )
158}
159pub fn fixpoint_computation_ty() -> Expr {
164 arrow(
165 cst("TransferFunction"),
166 arrow(cst("AbstractState"), cst("AbstractState")),
167 )
168}
169pub fn soundness_condition_ty() -> Expr {
173 arrow(cst("AbstractTransformer"), prop())
174}
175pub fn galois_connection_ty() -> Expr {
180 impl_pi(
181 "C",
182 type0(),
183 impl_pi(
184 "A",
185 type0(),
186 arrow(
187 arrow(bvar(1), bvar(1)),
188 arrow(arrow(bvar(2), bvar(2)), prop()),
189 ),
190 ),
191 )
192}
193pub fn abstraction_function_ty() -> Expr {
198 impl_pi(
199 "C",
200 type0(),
201 impl_pi("A", type0(), arrow(app(cst("List"), bvar(1)), bvar(1))),
202 )
203}
204pub fn concretization_function_ty() -> Expr {
209 impl_pi(
210 "C",
211 type0(),
212 impl_pi("A", type0(), arrow(bvar(0), app(cst("List"), bvar(2)))),
213 )
214}
215pub fn optimal_abstraction_ty() -> Expr {
220 impl_pi(
221 "C",
222 type0(),
223 impl_pi("A", type0(), arrow(app(cst("List"), bvar(1)), bvar(1))),
224 )
225}
226pub fn galois_insertion_ty() -> Expr {
230 impl_pi(
231 "C",
232 type0(),
233 impl_pi(
234 "A",
235 type0(),
236 arrow(app2(cst("GaloisConnection"), bvar(1), bvar(0)), prop()),
237 ),
238 )
239}
240pub fn dataflow_analysis_ty() -> Expr {
245 type0()
246}
247pub fn reachability_analysis_ty() -> Expr {
252 arrow(type0(), prop())
253}
254pub fn null_pointer_analysis_ty() -> Expr {
259 type0()
260}
261pub fn array_bounds_analysis_ty() -> Expr {
266 type0()
267}
268pub fn taint_analysis_ty() -> Expr {
273 type0()
274}
275pub fn live_variable_analysis_ty() -> Expr {
280 type0()
281}
282pub fn available_expr_analysis_ty() -> Expr {
287 type0()
288}
289pub fn interval_widening_ty() -> Expr {
294 arrow(
295 cst("IntervalDomain"),
296 arrow(cst("IntervalDomain"), cst("IntervalDomain")),
297 )
298}
299pub fn convex_hull_widening_ty() -> Expr {
304 arrow(
305 app(cst("PolyhedralDomain"), nat_ty()),
306 arrow(
307 app(cst("PolyhedralDomain"), nat_ty()),
308 app(cst("PolyhedralDomain"), nat_ty()),
309 ),
310 )
311}
312pub fn delayed_widening_ty() -> Expr {
317 arrow(
318 nat_ty(),
319 arrow(
320 cst("AbstractState"),
321 arrow(cst("AbstractState"), cst("AbstractState")),
322 ),
323 )
324}
325pub fn loop_bound_ty() -> Expr {
330 arrow(cst("AbstractState"), nat_ty())
331}
332pub fn build_env(env: &mut Environment) {
334 let axioms: &[(&str, Expr)] = &[
335 ("AbstractDomain", abstract_domain_ty()),
336 ("AbstractLattice", abstract_lattice_ty()),
337 ("IntervalDomain", interval_domain_ty()),
338 ("OctagonDomain", octagon_domain_ty()),
339 ("PolyhedralDomain", polyhedral_domain_ty()),
340 ("SignDomain", sign_domain_ty()),
341 ("ParityDomain", parity_domain_ty()),
342 ("AbstractJoin", abstract_join_ty()),
343 ("AbstractMeet", abstract_meet_ty()),
344 ("AbstractWiden", abstract_widen_ty()),
345 ("AbstractNarrow", abstract_narrow_ty()),
346 ("AbstractState", abstract_state_ty()),
347 ("AbstractTransformer", abstract_transformer_ty()),
348 ("TransferFunction", transfer_function_ty()),
349 ("JoinSemilattice", join_semilattice_ty()),
350 ("FixpointComputation", fixpoint_computation_ty()),
351 ("SoundnessCondition", soundness_condition_ty()),
352 ("GaloisConnection", galois_connection_ty()),
353 ("AbstractionFunction", abstraction_function_ty()),
354 ("ConcretizationFunction", concretization_function_ty()),
355 ("OptimalAbstraction", optimal_abstraction_ty()),
356 ("GaloisInsertion", galois_insertion_ty()),
357 ("DataflowAnalysis", dataflow_analysis_ty()),
358 ("ReachabilityAnalysis", reachability_analysis_ty()),
359 ("NullPointerAnalysis", null_pointer_analysis_ty()),
360 ("ArrayBoundsAnalysis", array_bounds_analysis_ty()),
361 ("TaintAnalysis", taint_analysis_ty()),
362 ("LiveVariableAnalysis", live_variable_analysis_ty()),
363 ("AvailableExprAnalysis", available_expr_analysis_ty()),
364 ("IntervalWidening", interval_widening_ty()),
365 ("ConvexHullWidening", convex_hull_widening_ty()),
366 ("DelayedWidening", delayed_widening_ty()),
367 ("LoopBound", loop_bound_ty()),
368 ];
369 for (name, ty) in axioms {
370 env.add(Declaration::Axiom {
371 name: Name::str(*name),
372 univ_params: vec![],
373 ty: ty.clone(),
374 })
375 .ok();
376 }
377}
378pub fn ellipsoid_domain_ty() -> Expr {
383 arrow(nat_ty(), type0())
384}
385pub fn zonotope_domain_ty() -> Expr {
390 arrow(nat_ty(), arrow(nat_ty(), type0()))
391}
392pub fn template_polyhedron_domain_ty() -> Expr {
397 arrow(nat_ty(), arrow(nat_ty(), type0()))
398}
399pub fn reduced_product_domain_ty() -> Expr {
404 impl_pi(
405 "A",
406 type0(),
407 impl_pi("B", type0(), arrow(bvar(1), arrow(bvar(1), type0()))),
408 )
409}
410pub fn smashing_domain_ty() -> Expr {
415 impl_pi(
416 "A",
417 type0(),
418 arrow(app(cst("AbstractDomain"), bvar(0)), type0()),
419 )
420}
421pub fn powerset_lifting_domain_ty() -> Expr {
426 impl_pi(
427 "A",
428 type0(),
429 arrow(app(cst("AbstractDomain"), bvar(0)), type0()),
430 )
431}
432pub fn trace_abstraction_ty() -> Expr {
437 impl_pi("A", type0(), type0())
438}
439pub fn abstract_trace_ty() -> Expr {
444 type0()
445}
446pub fn trace_semantics_monotone_ty() -> Expr {
450 arrow(cst("AbstractTrace"), arrow(cst("AbstractTrace"), prop()))
451}
452pub fn thread_modular_analysis_ty() -> Expr {
457 arrow(nat_ty(), arrow(cst("AbstractState"), cst("AbstractState")))
458}
459pub fn interference_abstraction_ty() -> Expr {
464 arrow(
465 cst("AbstractState"),
466 arrow(cst("AbstractState"), cst("AbstractState")),
467 )
468}
469pub fn partial_order_reduction_abs_ty() -> Expr {
474 arrow(cst("AbstractState"), cst("AbstractState"))
475}
476pub fn lockset_analysis_ty() -> Expr {
481 type0()
482}
483pub fn widening_operator_ty() -> Expr {
488 impl_pi(
489 "A",
490 type0(),
491 arrow(
492 app(cst("AbstractDomain"), bvar(0)),
493 arrow(bvar(1), arrow(bvar(2), bvar(3))),
494 ),
495 )
496}
497pub fn narrowing_operator_ty() -> Expr {
502 impl_pi(
503 "A",
504 type0(),
505 arrow(
506 app(cst("AbstractDomain"), bvar(0)),
507 arrow(bvar(1), arrow(bvar(2), bvar(3))),
508 ),
509 )
510}
511pub fn extrapolation_lemma_ty() -> Expr {
516 impl_pi(
517 "A",
518 type0(),
519 arrow(app(cst("WideningOperator"), bvar(0)), prop()),
520 )
521}
522pub fn accelerated_fixpoint_ty() -> Expr {
527 arrow(cst("AbstractState"), cst("AbstractState"))
528}
529pub fn probabilistic_abstract_domain_ty() -> Expr {
534 type0()
535}
536pub fn abstract_distribution_ty() -> Expr {
541 impl_pi("A", type0(), type0())
542}
543pub fn abstract_expectation_ty() -> Expr {
548 arrow(
549 app(cst("AbstractDistribution"), type0()),
550 arrow(arrow(type0(), cst("Real")), cst("Real")),
551 )
552}
553pub fn probabilistic_soundness_ty() -> Expr {
558 arrow(app(cst("AbstractDistribution"), type0()), prop())
559}
560pub fn bdd_abstract_domain_ty() -> Expr {
565 arrow(nat_ty(), type0())
566}
567pub fn sat_abstract_domain_ty() -> Expr {
572 type0()
573}
574pub fn symbolic_transformer_ty() -> Expr {
579 arrow(cst("SatAbstractDomain"), cst("SatAbstractDomain"))
580}
581pub fn abstract_model_checking_ty() -> Expr {
586 arrow(cst("AbstractState"), arrow(prop(), cst("Bool")))
587}
588pub fn separation_logic_abs_domain_ty() -> Expr {
593 type0()
594}
595pub fn abstract_heap_predicate_ty() -> Expr {
600 arrow(type0(), prop())
601}
602pub fn separating_conjunction_ty() -> Expr {
606 arrow(
607 app(cst("AbstractHeapPredicate"), type0()),
608 arrow(
609 app(cst("AbstractHeapPredicate"), type0()),
610 app(cst("AbstractHeapPredicate"), type0()),
611 ),
612 )
613}
614pub fn shape_analysis_ty() -> Expr {
619 arrow(
620 cst("SeparationLogicAbsDomain"),
621 app(cst("AbstractHeapPredicate"), type0()),
622 )
623}
624pub fn higher_order_abstract_domain_ty() -> Expr {
629 arrow(arrow(type0(), type0()), type0())
630}
631pub fn abstract_closure_ty() -> Expr {
636 arrow(
637 cst("AbstractState"),
638 arrow(arrow(cst("AbstractState"), cst("AbstractState")), type0()),
639 )
640}
641pub fn closure_abstraction_ty() -> Expr {
645 arrow(
646 app2(
647 cst("AbstractClosure"),
648 cst("AbstractState"),
649 arrow(cst("AbstractState"), cst("AbstractState")),
650 ),
651 arrow(cst("AbstractState"), cst("AbstractState")),
652 )
653}
654pub fn higher_order_fixpoint_ty() -> Expr {
659 arrow(
660 arrow(cst("AbstractState"), cst("AbstractState")),
661 cst("AbstractState"),
662 )
663}
664pub fn information_flow_lattice_ty() -> Expr {
669 type0()
670}
671pub fn non_interference_ty() -> Expr {
676 arrow(
677 cst("AbstractState"),
678 arrow(cst("InformationFlowLattice"), prop()),
679 )
680}
681pub fn declassification_policy_ty() -> Expr {
686 arrow(type0(), arrow(cst("InformationFlowLattice"), prop()))
687}
688pub fn secure_abstract_interpreter_ty() -> Expr {
693 arrow(
694 cst("AbstractState"),
695 arrow(cst("InformationFlowLattice"), prop()),
696 )
697}
698pub fn type_lattice_ty() -> Expr {
703 type0()
704}
705pub fn type_refinement_ty() -> Expr {
710 arrow(
711 cst("TypeLattice"),
712 arrow(app(cst("AbstractDomain"), type0()), type0()),
713 )
714}
715pub fn typed_abstract_transformer_ty() -> Expr {
720 arrow(
721 cst("TypeLattice"),
722 arrow(cst("AbstractState"), cst("AbstractState")),
723 )
724}
725pub fn deep_poly_domain_ty() -> Expr {
730 arrow(nat_ty(), type0())
731}
732pub fn abstract_relu_ty() -> Expr {
737 arrow(
738 app(cst("DeepPolyDomain"), nat_ty()),
739 app(cst("DeepPolyDomain"), nat_ty()),
740 )
741}
742pub fn neural_network_verification_ty() -> Expr {
747 arrow(
748 app(cst("DeepPolyDomain"), nat_ty()),
749 arrow(prop(), cst("Bool")),
750 )
751}
752pub fn abstract_affine_transform_ty() -> Expr {
757 arrow(
758 nat_ty(),
759 arrow(
760 nat_ty(),
761 arrow(
762 app(cst("DeepPolyDomain"), nat_ty()),
763 app(cst("DeepPolyDomain"), nat_ty()),
764 ),
765 ),
766 )
767}
768pub fn assume_guarantee_contract_ty() -> Expr {
773 arrow(cst("AbstractState"), arrow(cst("AbstractState"), type0()))
774}
775pub fn contract_composition_ty() -> Expr {
780 let ag = app2(
781 cst("AssumeGuaranteeContract"),
782 cst("AbstractState"),
783 cst("AbstractState"),
784 );
785 arrow(ag.clone(), arrow(ag.clone(), ag))
786}
787pub fn summary_function_ty() -> Expr {
792 arrow(cst("AbstractState"), cst("AbstractState"))
793}
794pub fn composition_soundness_ty() -> Expr {
799 arrow(
800 cst("SummaryFunction"),
801 arrow(
802 app2(
803 cst("AssumeGuaranteeContract"),
804 cst("AbstractState"),
805 cst("AbstractState"),
806 ),
807 prop(),
808 ),
809 )
810}
811pub fn modular_fixpoint_ty() -> Expr {
816 arrow(
817 arrow(cst("AbstractState"), cst("AbstractState")),
818 arrow(cst("AbstractState"), cst("AbstractState")),
819 )
820}
821pub fn build_env_extended(env: &mut Environment) {
823 let axioms: &[(&str, Expr)] = &[
824 ("EllipsoidDomain", ellipsoid_domain_ty()),
825 ("ZonotopeDomain", zonotope_domain_ty()),
826 ("TemplatePolyhedronDomain", template_polyhedron_domain_ty()),
827 ("ReducedProductDomain", reduced_product_domain_ty()),
828 ("SmashingDomain", smashing_domain_ty()),
829 ("PowersetLiftingDomain", powerset_lifting_domain_ty()),
830 ("TraceAbstraction", trace_abstraction_ty()),
831 ("AbstractTrace", abstract_trace_ty()),
832 ("TraceSemanticsMonotone", trace_semantics_monotone_ty()),
833 ("ThreadModularAnalysis", thread_modular_analysis_ty()),
834 ("InterferenceAbstraction", interference_abstraction_ty()),
835 ("PartialOrderReductionAbs", partial_order_reduction_abs_ty()),
836 ("LocksetAnalysis", lockset_analysis_ty()),
837 ("WideningOperator", widening_operator_ty()),
838 ("NarrowingOperator", narrowing_operator_ty()),
839 ("ExtrapolationLemma", extrapolation_lemma_ty()),
840 ("AcceleratedFixpoint", accelerated_fixpoint_ty()),
841 (
842 "ProbabilisticAbstractDomain",
843 probabilistic_abstract_domain_ty(),
844 ),
845 ("AbstractDistribution", abstract_distribution_ty()),
846 ("AbstractExpectation", abstract_expectation_ty()),
847 ("ProbabilisticSoundness", probabilistic_soundness_ty()),
848 ("BddAbstractDomain", bdd_abstract_domain_ty()),
849 ("SatAbstractDomain", sat_abstract_domain_ty()),
850 ("SymbolicTransformer", symbolic_transformer_ty()),
851 ("AbstractModelChecking", abstract_model_checking_ty()),
852 ("SeparationLogicAbsDomain", separation_logic_abs_domain_ty()),
853 ("AbstractHeapPredicate", abstract_heap_predicate_ty()),
854 ("SeparatingConjunction", separating_conjunction_ty()),
855 ("ShapeAnalysis", shape_analysis_ty()),
856 (
857 "HigherOrderAbstractDomain",
858 higher_order_abstract_domain_ty(),
859 ),
860 ("AbstractClosure", abstract_closure_ty()),
861 ("ClosureAbstraction", closure_abstraction_ty()),
862 ("HigherOrderFixpoint", higher_order_fixpoint_ty()),
863 ("InformationFlowLattice", information_flow_lattice_ty()),
864 ("NonInterference", non_interference_ty()),
865 ("DeclassificationPolicy", declassification_policy_ty()),
866 (
867 "SecureAbstractInterpreter",
868 secure_abstract_interpreter_ty(),
869 ),
870 ("TypeLattice", type_lattice_ty()),
871 ("TypeRefinement", type_refinement_ty()),
872 ("TypedAbstractTransformer", typed_abstract_transformer_ty()),
873 ("DeepPolyDomain", deep_poly_domain_ty()),
874 ("AbstractRelu", abstract_relu_ty()),
875 (
876 "NeuralNetworkVerification",
877 neural_network_verification_ty(),
878 ),
879 ("AbstractAffineTransform", abstract_affine_transform_ty()),
880 ("AssumeGuaranteeContract", assume_guarantee_contract_ty()),
881 ("ContractComposition", contract_composition_ty()),
882 ("SummaryFunction", summary_function_ty()),
883 ("CompositionSoundness", composition_soundness_ty()),
884 ("ModularFixpoint", modular_fixpoint_ty()),
885 ];
886 for (name, ty) in axioms {
887 env.add(Declaration::Axiom {
888 name: Name::str(*name),
889 univ_params: vec![],
890 ty: ty.clone(),
891 })
892 .ok();
893 }
894}
895#[cfg(test)]
896mod tests {
897 use super::*;
898 fn registered_env() -> Environment {
899 let mut env = Environment::new();
900 build_env(&mut env);
901 env
902 }
903 #[test]
904 fn test_abstract_domain_registered() {
905 let env = registered_env();
906 assert!(env.get(&Name::str("AbstractDomain")).is_some());
907 }
908 #[test]
909 fn test_interval_domain_registered() {
910 let env = registered_env();
911 assert!(env.get(&Name::str("IntervalDomain")).is_some());
912 }
913 #[test]
914 fn test_galois_connection_registered() {
915 let env = registered_env();
916 assert!(env.get(&Name::str("GaloisConnection")).is_some());
917 }
918 #[test]
919 fn test_sign_domain_join() {
920 assert_eq!(SignDomain::Pos.join(&SignDomain::Zero), SignDomain::NonNeg);
921 assert_eq!(SignDomain::Neg.join(&SignDomain::Pos), SignDomain::Top);
922 assert_eq!(SignDomain::Bottom.join(&SignDomain::Neg), SignDomain::Neg);
923 }
924 #[test]
925 fn test_parity_domain_add() {
926 assert_eq!(
927 ParityDomain::Even.add(&ParityDomain::Even),
928 ParityDomain::Even
929 );
930 assert_eq!(
931 ParityDomain::Odd.add(&ParityDomain::Odd),
932 ParityDomain::Even
933 );
934 assert_eq!(
935 ParityDomain::Even.add(&ParityDomain::Odd),
936 ParityDomain::Odd
937 );
938 }
939 #[test]
940 fn test_interval_join_widen() {
941 let a = IntervalDomain::new(Bound::Finite(0), Bound::Finite(5));
942 let b = IntervalDomain::new(Bound::Finite(3), Bound::Finite(10));
943 let j = a.join(&b);
944 assert_eq!(j.lower, Bound::Finite(0));
945 assert_eq!(j.upper, Bound::Finite(10));
946 let a2 = IntervalDomain::new(Bound::Finite(0), Bound::Finite(5));
947 let b2 = IntervalDomain::new(Bound::Finite(0), Bound::Finite(20));
948 let w = a2.widen(&b2);
949 assert_eq!(w.upper, Bound::PosInf);
950 }
951 #[test]
952 fn test_interval_contains() {
953 let i = IntervalDomain::new(Bound::Finite(1), Bound::Finite(10));
954 assert!(i.contains(5));
955 assert!(!i.contains(0));
956 assert!(!i.contains(11));
957 }
958 #[test]
959 fn test_galois_connection() {
960 let gc = GaloisConnection::interval_galois();
961 let abs = gc.abstract_of(&[1, 3, 5, 7]);
962 assert_eq!(abs.lower, Bound::Finite(1));
963 assert_eq!(abs.upper, Bound::Finite(7));
964 }
965 #[test]
966 fn test_abstract_state_widen() {
967 let mut s1 = AbstractState::bottom();
968 s1.set("x", IntervalDomain::new(Bound::Finite(0), Bound::Finite(5)));
969 let mut s2 = AbstractState::bottom();
970 s2.set(
971 "x",
972 IntervalDomain::new(Bound::Finite(0), Bound::Finite(10)),
973 );
974 let w = s1.widen(&s2);
975 assert_eq!(w.get("x").upper, Bound::PosInf);
976 }
977 #[test]
978 fn test_taint_analysis() {
979 let mut ta = TaintAnalysis::new();
980 ta.add_source("user_input");
981 assert!(ta.is_tainted("user_input"));
982 ta.propagate("result", &["user_input", "constant"]);
983 assert!(ta.is_tainted("result"));
984 }
985 #[test]
986 fn test_delayed_widening() {
987 let a = IntervalDomain::new(Bound::Finite(0), Bound::Finite(5));
988 let b = IntervalDomain::new(Bound::Finite(0), Bound::Finite(10));
989 let mut dw = DelayedWidening::new(2);
990 let r1 = dw.apply(&a, &b);
991 assert_eq!(r1.upper, Bound::Finite(10));
992 let r2 = dw.apply(&a, &b);
993 assert_eq!(r2.upper, Bound::Finite(10));
994 let r3 = dw.apply(&a, &b);
995 assert_eq!(r3.upper, Bound::PosInf);
996 }
997 #[test]
998 fn test_octagon_satisfiable() {
999 let mut oct = OctagonDomain::top(2);
1000 oct.add_upper_bound(0, 10);
1001 assert!(oct.is_satisfiable());
1002 }
1003 #[test]
1004 fn test_polyhedral_contains() {
1005 let mut poly = PolyhedralDomain::top(2);
1006 poly.add_constraint(vec![1.0, 0.0], 5.0);
1007 poly.add_constraint(vec![0.0, 1.0], 3.0);
1008 assert!(poly.contains(&[4.0, 2.0]));
1009 assert!(!poly.contains(&[6.0, 2.0]));
1010 }
1011}